/** * 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); }
/** * * DistInit 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 DistInit(XScuGic_Config *Config, u32 CpuID) { u32 Int_Id; #if USE_AMP==1 #warning "Building GIC for AMP" /* * The distrubutor should not be initialized by FreeRTOS in the case of * AMP -- it is assumed that Linux is the master of this device in that * case. */ return; #endif XScuGic_WriteReg(Config->DistBaseAddress, XSCUGIC_DIST_EN_OFFSET, 0UL); /* * 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 = 32; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id+=16) { /* * Each INT_ID uses two bits, or 16 INT_ID per register * Set them all to be level sensitive, active HIGH. */ XScuGic_WriteReg(Config->DistBaseAddress, XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id), 0UL); } #define DEFAULT_PRIORITY 0xa0a0a0a0UL for (Int_Id = 0; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id+=4) { /* * 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_WriteReg(Config->DistBaseAddress, XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id), DEFAULT_PRIORITY); } for (Int_Id = 32; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id+=4) { /* * 3. The CPU interface in the spi_target register * Only write to the SPI interrupts, so start at 32 */ CpuID |= CpuID << 8; CpuID |= CpuID << 16; XScuGic_WriteReg(Config->DistBaseAddress, XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), CpuID); } for (Int_Id = 0; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id+=32) { /* * 4. Enable the SPI using the enable_set register. Leave all disabled * for now. */ XScuGic_WriteReg(Config->DistBaseAddress, XSCUGIC_ENABLE_DISABLE_OFFSET_CALC(XSCUGIC_DISABLE_OFFSET, Int_Id), 0xFFFFFFFFUL); } XScuGic_WriteReg(Config->DistBaseAddress, XSCUGIC_DIST_EN_OFFSET, XSCUGIC_EN_INT_MASK); }
/** * * Hardware initialization. * * @return none * *****************************************************************************/ void hal_hardware_init(void) { cyg_uint32 dw_i, dwCPUID; // -------- Ininializing GIC ------------------------------------------- // Connect GIC to CORE0 dwCPUID = 1; HAL_WRITE_UINT32(XC7Z_SCUGIC_DIST_BASEADDR + XSCUGIC_DIST_EN_OFFSET, 0UL); // 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 (dw_i = 32; dw_i < XSCUGIC_MAX_NUM_INTR_INPUTS; dw_i += 16) { // // Each INT_ID uses two bits, or 16 INT_ID per register // Set them all to be level sensitive, active HIGH. // HAL_WRITE_UINT32(XC7Z_SCUGIC_DIST_BASEADDR + XSCUGIC_INT_CFG_OFFSET_CALC(dw_i), 0UL); } for (dw_i = 0; dw_i < XSCUGIC_MAX_NUM_INTR_INPUTS; dw_i += 4) { // // 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. // HAL_WRITE_UINT32(XC7Z_SCUGIC_DIST_BASEADDR + XSCUGIC_PRIORITY_OFFSET_CALC(dw_i), DEFAULT_PRIORITY); } for (dw_i = 32; dw_i < XSCUGIC_MAX_NUM_INTR_INPUTS; dw_i += 4) { // // 3. The CPU interface in the spi_target register // Only write to the SPI interrupts, so start at 32 // dwCPUID |= dwCPUID << 8; dwCPUID |= dwCPUID << 16; HAL_WRITE_UINT32(XC7Z_SCUGIC_DIST_BASEADDR + XSCUGIC_SPI_TARGET_OFFSET_CALC(dw_i), dwCPUID); } for (dw_i = 0; dw_i < XSCUGIC_MAX_NUM_INTR_INPUTS; dw_i += 32) { // // 4. Enable the SPI using the enable_set register. Leave all // disabled for now. // HAL_WRITE_UINT32(XC7Z_SCUGIC_DIST_BASEADDR + XSCUGIC_ENABLE_DISABLE_OFFSET_CALC(XSCUGIC_DISABLE_OFFSET, dw_i), 0xFFFFFFFFUL); } HAL_WRITE_UINT32(XC7Z_SCUGIC_DIST_BASEADDR + XSCUGIC_DIST_EN_OFFSET, XSCUGIC_EN_INT_MASK); // // Program the priority mask of the CPU using the Priority mask register // HAL_WRITE_UINT32(XC7Z_SCUGIC_CPU_BASEADDR + XSCUGIC_CPU_PRIOR_OFFSET, 0xF0); // // If the CPU operates in both security domains, set parameters in the // control_s register. // 1. Set FIQen=1 to use FIQ for secure interrupts, // 2. Program the AckCtl bit // 3. Program the SBPR bit to select the binary pointer behavior // 4. Set EnableS = 1 to enable secure interrupts // 5. Set EnbleNS = 1 to enable non secure interrupts // // // If the CPU operates only in the secure domain, setup the // control_s register. // 1. Set FIQen=1, // 2. Set EnableS=1, to enable the CPU interface to signal secure interrupts. // Only enable the IRQ output unless secure interrupts are needed. // HAL_WRITE_UINT32(XC7Z_SCUGIC_CPU_BASEADDR + XSCUGIC_CONTROL_OFFSET, 0x07); #ifdef HAL_PLF_HARDWARE_INIT // Perform any platform specific initializations HAL_PLF_HARDWARE_INIT(); #endif #ifdef CYGSEM_HAL_ENABLE_DCACHE_ON_STARTUP HAL_DCACHE_ENABLE(); // Enable DCache #endif #ifdef CYGSEM_HAL_ENABLE_ICACHE_ON_STARTUP HAL_ICACHE_ENABLE(); // Enable ICache #endif // Set up eCos/ROM interfaces hal_if_init(); HAL_CLOCK_INITIALIZE(CYGNUM_HAL_RTC_PERIOD); #ifdef CYGPKG_HAL_SMP_SUPPORT cyg_uint32 reg; /* Disable the distributor */ HAL_READ_UINT32(XC7Z_ICD_DCR_BASEADDR, reg); reg &= ~(0x2); HAL_WRITE_UINT32(XC7Z_ICD_DCR_BASEADDR, reg); /* Clear pending interrupts */ HAL_WRITE_UINT32(XC7Z_ICD_ICPR0_BASEADDR, 0xffffffff); HAL_WRITE_UINT32(XC7Z_ICD_ICPR1_BASEADDR, 0xffffffff); HAL_WRITE_UINT32(XC7Z_ICD_ICPR2_BASEADDR, 0xffffffff); /* Re-enable the distributor */ HAL_READ_UINT32(XC7Z_ICD_DCR_BASEADDR, reg); reg |= 0x2; HAL_WRITE_UINT32(XC7Z_ICD_DCR_BASEADDR, reg); /* Start the cpu */ cyg_hal_smp_init(); hal_interrupt_init_cpu(); cyg_hal_smp_cpu_start_first(); #endif }
/** * * 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); }