| /**************************************************************************** |
| * arch/arm/src/qemu/qemu_irq.c |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. The |
| * ASF licenses this file to you 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 |
| * |
| * http://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. |
| * |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Included Files |
| ****************************************************************************/ |
| |
| #include <nuttx/config.h> |
| #include <nuttx/arch.h> |
| |
| #include "arm_internal.h" |
| #include "sctlr.h" |
| #include "gic.h" |
| |
| /**************************************************************************** |
| * Pre-processor Definitions |
| ****************************************************************************/ |
| |
| /* Size of the interrupt stack allocation */ |
| |
| #define INTSTACK_ALLOC (CONFIG_SMP_NCPUS * INTSTACK_SIZE) |
| |
| /**************************************************************************** |
| * Public Data |
| ****************************************************************************/ |
| |
| #if defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 7 |
| /* In the SMP configuration, we will need custom IRQ and FIQ stacks. |
| * These definitions provide the aligned stack allocations. |
| */ |
| |
| static uint64_t g_irqstack_alloc[INTSTACK_ALLOC >> 3]; |
| static uint64_t g_fiqstack_alloc[INTSTACK_ALLOC >> 3]; |
| |
| /* These are arrays that point to the top of each interrupt stack */ |
| |
| uintptr_t g_irqstack_top[CONFIG_SMP_NCPUS] = |
| { |
| (uintptr_t)g_irqstack_alloc + INTSTACK_SIZE, |
| #if CONFIG_SMP_NCPUS > 1 |
| (uintptr_t)g_irqstack_alloc + (2 * INTSTACK_SIZE), |
| #endif |
| #if CONFIG_SMP_NCPUS > 2 |
| (uintptr_t)g_irqstack_alloc + (3 * INTSTACK_SIZE), |
| #endif |
| #if CONFIG_SMP_NCPUS > 3 |
| (uintptr_t)g_irqstack_alloc + (4 * INTSTACK_SIZE) |
| #endif |
| }; |
| |
| uintptr_t g_fiqstack_top[CONFIG_SMP_NCPUS] = |
| { |
| (uintptr_t)g_fiqstack_alloc + INTSTACK_SIZE, |
| #if CONFIG_SMP_NCPUS > 1 |
| (uintptr_t)g_fiqstack_alloc + 2 * INTSTACK_SIZE, |
| #endif |
| #if CONFIG_SMP_NCPUS > 2 |
| (uintptr_t)g_fiqstack_alloc + 3 * INTSTACK_SIZE, |
| #endif |
| #if CONFIG_SMP_NCPUS > 3 |
| (uintptr_t)g_fiqstack_alloc + 4 * INTSTACK_SIZE |
| #endif |
| }; |
| |
| #endif |
| |
| /* Symbols defined via the linker script */ |
| |
| extern uint8_t _vector_start[]; /* Beginning of vector block */ |
| extern uint8_t _vector_end[]; /* End+1 of vector block */ |
| |
| /**************************************************************************** |
| * Public Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Name: up_irqinitialize |
| * |
| * Description: |
| * This function is called by up_initialize() during the bring-up of the |
| * system. It is the responsibility of this function to but the interrupt |
| * subsystem into the working and ready state. |
| * |
| ****************************************************************************/ |
| |
| void up_irqinitialize(void) |
| { |
| #ifdef CONFIG_ARCH_LOWVECTORS |
| /* Set the VBAR register to the address of the vector table */ |
| |
| DEBUGASSERT((((uintptr_t)_vector_start) & ~VBAR_MASK) == 0); |
| cp15_wrvbar((uint32_t)_vector_start); |
| #endif |
| |
| /* The following operations need to be atomic, but since this function is |
| * called early in the initialization sequence, we expect to have exclusive |
| * access to the GIC. |
| */ |
| |
| /* Initialize the Generic Interrupt Controller (GIC) for CPU0. |
| * In AMP mode, we want arm_gic0_initialize to be called only once. |
| */ |
| |
| if (sched_getcpu() == 0) |
| { |
| arm_gic0_initialize(); /* Initialization unique to CPU0 */ |
| } |
| |
| arm_gic_initialize(); /* Initialization common to all CPUs */ |
| |
| #ifndef CONFIG_SUPPRESS_INTERRUPTS |
| /* And finally, enable interrupts */ |
| |
| arm_color_intstack(); |
| up_irq_enable(); |
| #endif |
| } |
| |
| /**************************************************************************** |
| * Name: up_get_intstackbase |
| * |
| * Description: |
| * Return a pointer to the "alloc" the correct interrupt stack allocation |
| * for the current CPU. |
| * |
| ****************************************************************************/ |
| |
| #if defined(CONFIG_SMP) && CONFIG_ARCH_INTERRUPTSTACK > 7 |
| uintptr_t up_get_intstackbase(int cpu) |
| { |
| return g_irqstack_top[cpu] - INTSTACK_SIZE; |
| } |
| #endif |