blob: fbb5665ee636ea62db0b59f52329a40e44620f89 [file] [log] [blame]
/****************************************************************************
* 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