Initial commit
This commit is contained in:
		
							
								
								
									
										410
									
								
								Drivers/CMSIS/Core_A/Source/irq_ctrl_gic.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										410
									
								
								Drivers/CMSIS/Core_A/Source/irq_ctrl_gic.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,410 @@ | ||||
| /**************************************************************************//** | ||||
|  * @file     irq_ctrl_gic.c | ||||
|  * @brief    Interrupt controller handling implementation for GIC | ||||
|  * @version  V1.0.1 | ||||
|  * @date     9. April 2018 | ||||
|  ******************************************************************************/ | ||||
| /* | ||||
|  * Copyright (c) 2017 ARM Limited. All rights reserved. | ||||
|  * | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the License); you may | ||||
|  * not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  * www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an AS IS BASIS, WITHOUT | ||||
|  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
|  | ||||
| #include <stddef.h> | ||||
|  | ||||
| #include "RTE_Components.h" | ||||
| #include CMSIS_device_header | ||||
|  | ||||
| #include "irq_ctrl.h" | ||||
|  | ||||
| #if defined(__GIC_PRESENT) && (__GIC_PRESENT == 1U) | ||||
|  | ||||
| /// Number of implemented interrupt lines | ||||
| #ifndef IRQ_GIC_LINE_COUNT | ||||
| #define IRQ_GIC_LINE_COUNT      (1020U) | ||||
| #endif | ||||
|  | ||||
| static IRQHandler_t IRQTable[IRQ_GIC_LINE_COUNT] = { 0U }; | ||||
| static uint32_t     IRQ_ID0; | ||||
|  | ||||
| /// Initialize interrupt controller. | ||||
| __WEAK int32_t IRQ_Initialize (void) { | ||||
|   uint32_t i; | ||||
|  | ||||
|   for (i = 0U; i < IRQ_GIC_LINE_COUNT; i++) { | ||||
|     IRQTable[i] = (IRQHandler_t)NULL; | ||||
|   } | ||||
|   GIC_Enable(); | ||||
|   return (0); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Register interrupt handler. | ||||
| __WEAK int32_t IRQ_SetHandler (IRQn_ID_t irqn, IRQHandler_t handler) { | ||||
|   int32_t status; | ||||
|  | ||||
|   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) { | ||||
|     IRQTable[irqn] = handler; | ||||
|     status =  0; | ||||
|   } else { | ||||
|     status = -1; | ||||
|   } | ||||
|  | ||||
|   return (status); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Get the registered interrupt handler. | ||||
| __WEAK IRQHandler_t IRQ_GetHandler (IRQn_ID_t irqn) { | ||||
|   IRQHandler_t h; | ||||
|  | ||||
|   // Ignore CPUID field (software generated interrupts) | ||||
|   irqn &= 0x3FFU; | ||||
|  | ||||
|   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) { | ||||
|     h = IRQTable[irqn]; | ||||
|   } else { | ||||
|     h = (IRQHandler_t)0; | ||||
|   } | ||||
|  | ||||
|   return (h); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Enable interrupt. | ||||
| __WEAK int32_t IRQ_Enable (IRQn_ID_t irqn) { | ||||
|   int32_t status; | ||||
|  | ||||
|   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) { | ||||
|     GIC_EnableIRQ ((IRQn_Type)irqn); | ||||
|     status = 0; | ||||
|   } else { | ||||
|     status = -1; | ||||
|   } | ||||
|  | ||||
|   return (status); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Disable interrupt. | ||||
| __WEAK int32_t IRQ_Disable (IRQn_ID_t irqn) { | ||||
|   int32_t status; | ||||
|  | ||||
|   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) { | ||||
|     GIC_DisableIRQ ((IRQn_Type)irqn); | ||||
|     status = 0; | ||||
|   } else { | ||||
|     status = -1; | ||||
|   } | ||||
|  | ||||
|   return (status); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Get interrupt enable state. | ||||
| __WEAK uint32_t IRQ_GetEnableState (IRQn_ID_t irqn) { | ||||
|   uint32_t enable; | ||||
|  | ||||
|   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) { | ||||
|     enable = GIC_GetEnableIRQ((IRQn_Type)irqn); | ||||
|   } else { | ||||
|     enable = 0U; | ||||
|   } | ||||
|  | ||||
|   return (enable); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Configure interrupt request mode. | ||||
| __WEAK int32_t IRQ_SetMode (IRQn_ID_t irqn, uint32_t mode) { | ||||
|   uint32_t val; | ||||
|   uint8_t cfg; | ||||
|   uint8_t secure; | ||||
|   uint8_t cpu; | ||||
|   int32_t status = 0; | ||||
|  | ||||
|   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) { | ||||
|     // Check triggering mode | ||||
|     val = (mode & IRQ_MODE_TRIG_Msk); | ||||
|  | ||||
|     if (val == IRQ_MODE_TRIG_LEVEL) { | ||||
|       cfg = 0x00U; | ||||
|     } else if (val == IRQ_MODE_TRIG_EDGE) { | ||||
|       cfg = 0x02U; | ||||
|     } else { | ||||
|       cfg = 0x00U; | ||||
|       status = -1; | ||||
|     } | ||||
|  | ||||
|     // Check interrupt type | ||||
|     val = mode & IRQ_MODE_TYPE_Msk; | ||||
|  | ||||
|     if (val != IRQ_MODE_TYPE_IRQ) { | ||||
|       status = -1; | ||||
|     } | ||||
|  | ||||
|     // Check interrupt domain | ||||
|     val = mode & IRQ_MODE_DOMAIN_Msk; | ||||
|  | ||||
|     if (val == IRQ_MODE_DOMAIN_NONSECURE) { | ||||
|       secure = 0U; | ||||
|     } else { | ||||
|       // Check security extensions support | ||||
|       val = GIC_DistributorInfo() & (1UL << 10U); | ||||
|  | ||||
|       if (val != 0U) { | ||||
|         // Security extensions are supported | ||||
|         secure = 1U; | ||||
|       } else { | ||||
|         secure = 0U; | ||||
|         status = -1; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // Check interrupt CPU targets | ||||
|     val = mode & IRQ_MODE_CPU_Msk; | ||||
|  | ||||
|     if (val == IRQ_MODE_CPU_ALL) { | ||||
|       cpu = 0xFFU; | ||||
|     } else { | ||||
|       cpu = val >> IRQ_MODE_CPU_Pos; | ||||
|     } | ||||
|  | ||||
|     // Apply configuration if no mode error | ||||
|     if (status == 0) { | ||||
|       GIC_SetConfiguration((IRQn_Type)irqn, cfg); | ||||
|       GIC_SetTarget       ((IRQn_Type)irqn, cpu); | ||||
|  | ||||
|       if (secure != 0U) { | ||||
|         GIC_SetGroup ((IRQn_Type)irqn, secure); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return (status); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Get interrupt mode configuration. | ||||
| __WEAK uint32_t IRQ_GetMode (IRQn_ID_t irqn) { | ||||
|   uint32_t mode; | ||||
|   uint32_t val; | ||||
|  | ||||
|   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) { | ||||
|     mode = IRQ_MODE_TYPE_IRQ; | ||||
|  | ||||
|     // Get trigger mode | ||||
|     val = GIC_GetConfiguration((IRQn_Type)irqn); | ||||
|  | ||||
|     if ((val & 2U) != 0U) { | ||||
|       // Corresponding interrupt is edge triggered | ||||
|       mode |= IRQ_MODE_TRIG_EDGE; | ||||
|     } else { | ||||
|       // Corresponding interrupt is level triggered | ||||
|       mode |= IRQ_MODE_TRIG_LEVEL; | ||||
|     } | ||||
|  | ||||
|     // Get interrupt CPU targets | ||||
|     mode |= GIC_GetTarget ((IRQn_Type)irqn) << IRQ_MODE_CPU_Pos; | ||||
|  | ||||
|   } else { | ||||
|     mode = IRQ_MODE_ERROR; | ||||
|   } | ||||
|  | ||||
|   return (mode); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Get ID number of current interrupt request (IRQ). | ||||
| __WEAK IRQn_ID_t IRQ_GetActiveIRQ (void) { | ||||
|   IRQn_ID_t irqn; | ||||
|   uint32_t prio; | ||||
|  | ||||
|   /* Dummy read to avoid GIC 390 errata 801120 */ | ||||
|   GIC_GetHighPendingIRQ(); | ||||
|  | ||||
|   irqn = GIC_AcknowledgePending(); | ||||
|  | ||||
|   __DSB(); | ||||
|  | ||||
|   /* Workaround GIC 390 errata 733075 (GIC-390_Errata_Notice_v6.pdf, 09-Jul-2014)  */ | ||||
|   /* The following workaround code is for a single-core system.  It would be       */ | ||||
|   /* different in a multi-core system.                                             */ | ||||
|   /* If the ID is 0 or 0x3FE or 0x3FF, then the GIC CPU interface may be locked-up */ | ||||
|   /* so unlock it, otherwise service the interrupt as normal.                      */ | ||||
|   /* Special IDs 1020=0x3FC and 1021=0x3FD are reserved values in GICv1 and GICv2  */ | ||||
|   /* so will not occur here.                                                       */ | ||||
|  | ||||
|   if ((irqn == 0) || (irqn >= 0x3FE)) { | ||||
|     /* Unlock the CPU interface with a dummy write to Interrupt Priority Register */ | ||||
|     prio = GIC_GetPriority((IRQn_Type)0); | ||||
|     GIC_SetPriority ((IRQn_Type)0, prio); | ||||
|  | ||||
|     __DSB(); | ||||
|  | ||||
|     if ((irqn == 0U) && ((GIC_GetIRQStatus ((IRQn_Type)irqn) & 1U) != 0U) && (IRQ_ID0 == 0U)) { | ||||
|       /* If the ID is 0, is active and has not been seen before */ | ||||
|       IRQ_ID0 = 1U; | ||||
|     } | ||||
|     /* End of Workaround GIC 390 errata 733075 */ | ||||
|   } | ||||
|  | ||||
|   return (irqn); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Get ID number of current fast interrupt request (FIQ). | ||||
| __WEAK IRQn_ID_t IRQ_GetActiveFIQ (void) { | ||||
|   return ((IRQn_ID_t)-1); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Signal end of interrupt processing. | ||||
| __WEAK int32_t IRQ_EndOfInterrupt (IRQn_ID_t irqn) { | ||||
|   int32_t status; | ||||
|   IRQn_Type irq = (IRQn_Type)irqn; | ||||
|  | ||||
|   irqn &= 0x3FFU; | ||||
|  | ||||
|   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) { | ||||
|     GIC_EndInterrupt (irq); | ||||
|  | ||||
|     if (irqn == 0) { | ||||
|       IRQ_ID0 = 0U; | ||||
|     } | ||||
|  | ||||
|     status = 0; | ||||
|   } else { | ||||
|     status = -1; | ||||
|   } | ||||
|  | ||||
|   return (status); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Set interrupt pending flag. | ||||
| __WEAK int32_t IRQ_SetPending (IRQn_ID_t irqn) { | ||||
|   int32_t status; | ||||
|  | ||||
|   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) { | ||||
|     GIC_SetPendingIRQ ((IRQn_Type)irqn); | ||||
|     status = 0; | ||||
|   } else { | ||||
|     status = -1; | ||||
|   } | ||||
|  | ||||
|   return (status); | ||||
| } | ||||
|  | ||||
| /// Get interrupt pending flag. | ||||
| __WEAK uint32_t IRQ_GetPending (IRQn_ID_t irqn) { | ||||
|   uint32_t pending; | ||||
|  | ||||
|   if ((irqn >= 16) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) { | ||||
|     pending = GIC_GetPendingIRQ ((IRQn_Type)irqn); | ||||
|   } else { | ||||
|     pending = 0U; | ||||
|   } | ||||
|  | ||||
|   return (pending & 1U); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Clear interrupt pending flag. | ||||
| __WEAK int32_t IRQ_ClearPending (IRQn_ID_t irqn) { | ||||
|   int32_t status; | ||||
|  | ||||
|   if ((irqn >= 16) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) { | ||||
|     GIC_ClearPendingIRQ ((IRQn_Type)irqn); | ||||
|     status = 0; | ||||
|   } else { | ||||
|     status = -1; | ||||
|   } | ||||
|  | ||||
|   return (status); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Set interrupt priority value. | ||||
| __WEAK int32_t IRQ_SetPriority (IRQn_ID_t irqn, uint32_t priority) { | ||||
|   int32_t status; | ||||
|  | ||||
|   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) { | ||||
|     GIC_SetPriority ((IRQn_Type)irqn, priority); | ||||
|     status = 0; | ||||
|   } else { | ||||
|     status = -1; | ||||
|   } | ||||
|  | ||||
|   return (status); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Get interrupt priority. | ||||
| __WEAK uint32_t IRQ_GetPriority (IRQn_ID_t irqn) { | ||||
|   uint32_t priority; | ||||
|  | ||||
|   if ((irqn >= 0) && (irqn < (IRQn_ID_t)IRQ_GIC_LINE_COUNT)) { | ||||
|     priority = GIC_GetPriority ((IRQn_Type)irqn); | ||||
|   } else { | ||||
|     priority = IRQ_PRIORITY_ERROR; | ||||
|   } | ||||
|  | ||||
|   return (priority); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Set priority masking threshold. | ||||
| __WEAK int32_t IRQ_SetPriorityMask (uint32_t priority) { | ||||
|   GIC_SetInterfacePriorityMask (priority); | ||||
|   return (0); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Get priority masking threshold | ||||
| __WEAK uint32_t IRQ_GetPriorityMask (void) { | ||||
|   return GIC_GetInterfacePriorityMask(); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Set priority grouping field split point | ||||
| __WEAK int32_t IRQ_SetPriorityGroupBits (uint32_t bits) { | ||||
|   int32_t status; | ||||
|  | ||||
|   if (bits == IRQ_PRIORITY_Msk) { | ||||
|     bits = 7U; | ||||
|   } | ||||
|  | ||||
|   if (bits < 8U) { | ||||
|     GIC_SetBinaryPoint (7U - bits); | ||||
|     status = 0; | ||||
|   } else { | ||||
|     status = -1; | ||||
|   } | ||||
|  | ||||
|   return (status); | ||||
| } | ||||
|  | ||||
|  | ||||
| /// Get priority grouping field split point | ||||
| __WEAK uint32_t IRQ_GetPriorityGroupBits (void) { | ||||
|   uint32_t bp; | ||||
|  | ||||
|   bp = GIC_GetBinaryPoint() & 0x07U; | ||||
|  | ||||
|   return (7U - bp); | ||||
| } | ||||
|  | ||||
| #endif | ||||
		Reference in New Issue
	
	Block a user