/** * Sets the interrupt priority and trigger type for the specificd IRQ source. * * @param InstancePtr is a pointer to the instance to be worked on. * @param Int_Id is the IRQ source number to modify * @param Priority is the new priority for the IRQ source. 0 is highest * priority, 0xF8 (248) is lowest. There are 32 priority levels * supported with a step of 8. Hence the supported priorities are * 0, 8, 16, 32, 40 ..., 248. * @param Trigger is the new trigger type for the IRQ source. * Each bit pair describes the configuration for an INT_ID. * SFI Read Only b10 always * PPI Read Only depending on how the PPIs are configured. * b01 Active HIGH level sensitive * b11 Rising edge sensitive * SPI LSB is read only. * b01 Active HIGH level sensitive * b11 Rising edge sensitive/ * * @return None. * * @note None. * *****************************************************************************/ void XScuGic_SetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, u8 Priority, u8 Trigger) { u32 RegValue; u8 LocalPriority; LocalPriority = Priority; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); Xil_AssertVoid(Trigger <= (u8)XSCUGIC_INT_CFG_MASK); Xil_AssertVoid(LocalPriority <= (u8)XSCUGIC_MAX_INTR_PRIO_VAL); /* * Determine the register to write to using the Int_Id. */ RegValue = XScuGic_DistReadReg(InstancePtr, XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id)); /* * The priority bits are Bits 7 to 3 in GIC Priority Register. This * means the number of priority levels supported are 32 and they are * in steps of 8. The priorities can be 0, 8, 16, 32, 48, ... etc. * The lower order 3 bits are masked before putting it in the register. */ LocalPriority = LocalPriority & (u8)XSCUGIC_INTR_PRIO_MASK; /* * Shift and Mask the correct bits for the priority and trigger in the * register */ RegValue &= ~(XSCUGIC_PRIORITY_MASK << ((Int_Id%4U)*8U)); RegValue |= (u32)LocalPriority << ((Int_Id%4U)*8U); /* * Write the value back to the register. */ XScuGic_DistWriteReg(InstancePtr, XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id), RegValue); /* * Determine the register to write to using the Int_Id. */ RegValue = XScuGic_DistReadReg(InstancePtr, XSCUGIC_INT_CFG_OFFSET_CALC (Int_Id)); /* * Shift and Mask the correct bits for the priority and trigger in the * register */ RegValue &= ~(XSCUGIC_INT_CFG_MASK << ((Int_Id%16U)*2U)); RegValue |= (u32)Trigger << ((Int_Id%16U)*2U); /* * Write the value back to the register. */ XScuGic_DistWriteReg(InstancePtr, XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id), RegValue); }
/** * * Run a self-test on the driver/device. This test reads the ID registers and * compares them. * * @param InstancePtr is a pointer to the XScuGic instance. * * @return * * - XST_SUCCESS if self-test is successful. * - XST_FAILURE if the self-test is not successful. * * @note None. * ******************************************************************************/ int XScuGic_SelfTest(XScuGic *InstancePtr) { u32 RegValue1 =0; int Index; /* * Assert the arguments */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Read the ID registers. */ for(Index=0; Index<=3; Index++) { RegValue1 |= XScuGic_DistReadReg(InstancePtr, (XSCUGIC_PCELLID_OFFSET + (Index * 4))) << (Index * 8); } if(XSCUGIC_PCELL_ID != RegValue1){ return XST_FAILURE; } return XST_SUCCESS; }
/** * Gets the interrupt priority and trigger type for the specificd IRQ source. * * @param InstancePtr is a pointer to the instance to be worked on. * @param Int_Id is the IRQ source number to modify * @param Priority is a pointer to the value of the priority of the IRQ * source. This is a return value. * @param Trigger is pointer to the value of the trigger of the IRQ * source. This is a return value. * * @return None. * * @note None * *****************************************************************************/ void XScuGic_GetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id, u8 *Priority, u8 *Trigger) { u32 RegValue; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS); Xil_AssertVoid(Priority != NULL); Xil_AssertVoid(Trigger != NULL); /* * Determine the register to read to using the Int_Id. */ RegValue = XScuGic_DistReadReg(InstancePtr, XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id)); /* * Shift and Mask the correct bits for the priority and trigger in the * register */ RegValue = RegValue >> ((Int_Id%4U)*8U); *Priority = (u8)(RegValue & XSCUGIC_PRIORITY_MASK); /* * Determine the register to read to using the Int_Id. */ RegValue = XScuGic_DistReadReg(InstancePtr, XSCUGIC_INT_CFG_OFFSET_CALC (Int_Id)); /* * Shift and Mask the correct bits for the priority and trigger in the * register */ RegValue = RegValue >> ((Int_Id%16U)*2U); *Trigger = (u8)(RegValue & XSCUGIC_INT_CFG_MASK); }
/** * Sets the target CPU for the interrupt of a peripheral * * @param InstancePtr is a pointer to the instance to be worked on. * @param Cpu_Id is a CPU number for which the interrupt has to be targeted * @param Int_Id is the IRQ source number to modify * * @return None. * * @note None * *****************************************************************************/ void XScuGic_InterruptMaptoCpu(XScuGic *InstancePtr, u8 Cpu_Id, u32 Int_Id) { u32 RegValue, Offset; RegValue = XScuGic_DistReadReg(InstancePtr, XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); Offset = (Int_Id & 0x3); RegValue = (RegValue | (~(0xFF << (Offset*8))) ); RegValue |= ((Cpu_Id) << (Offset*8)); XScuGic_DistWriteReg(InstancePtr, XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), RegValue); }
/** * * DistributorInit initializes the distributor of the GIC. The * initialization entails: * * - Write the trigger mode, priority and target CPU * - All interrupt sources are disabled * - Enable the distributor * * @param InstancePtr is a pointer to the XScuGic instance. * @param CpuID is the Cpu ID to be initialized. * * @return None * * @note None. * ******************************************************************************/ static void DistributorInit(XScuGic *InstancePtr, u32 CpuID) { u32 Int_Id; u32 LocalCpuID = CpuID; #if USE_AMP==1 #warning "Building GIC for AMP" #ifdef ARMR5 u32 RegValue; /* * The overall distributor should not be initialized in AMP case where * another CPU is taking care of it. */ LocalCpuID |= LocalCpuID << 8U; LocalCpuID |= LocalCpuID << 16U; for (Int_Id = 32U; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id=Int_Id+4U) { RegValue = XScuGic_DistReadReg(InstancePtr, XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id)); RegValue |= LocalCpuID; XScuGic_DistWriteReg(InstancePtr, XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), RegValue); } #endif return; #endif Xil_AssertVoid(InstancePtr != NULL); XScuGic_DistWriteReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET, 0U); /* * Set the security domains in the int_security registers for * non-secure interrupts * All are secure, so leave at the default. Set to 1 for non-secure * interrupts. */ /* * For the Shared Peripheral Interrupts INT_ID[MAX..32], set: */ /* * 1. The trigger mode in the int_config register * Only write to the SPI interrupts, so start at 32 */ for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; Int_Id=Int_Id+16U) { /* * Each INT_ID uses two bits, or 16 INT_ID per register * Set them all to be level sensitive, active HIGH. */ XScuGic_DistWriteReg(InstancePtr, XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id), 0U); } #define DEFAULT_PRIORITY 0xa0a0a0a0U for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; Int_Id=Int_Id+4U) { /* * 2. The priority using int the priority_level register * The priority_level and spi_target registers use one byte per * INT_ID. * Write a default value that can be changed elsewhere. */ XScuGic_DistWriteReg(InstancePtr, XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id), DEFAULT_PRIORITY); } for (Int_Id = 32U; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id=Int_Id+4U) { /* * 3. The CPU interface in the spi_target register * Only write to the SPI interrupts, so start at 32 */ LocalCpuID |= LocalCpuID << 8U; LocalCpuID |= LocalCpuID << 16U; XScuGic_DistWriteReg(InstancePtr, XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), LocalCpuID); } for (Int_Id = 0U; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id=Int_Id+32U) { /* * 4. Enable the SPI using the enable_set register. Leave all * disabled for now. */ XScuGic_DistWriteReg(InstancePtr, XSCUGIC_EN_DIS_OFFSET_CALC(XSCUGIC_DISABLE_OFFSET, Int_Id), 0xFFFFFFFFU); } XScuGic_DistWriteReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET, XSCUGIC_EN_INT_MASK); }