* arch/arm64/src/common/arm64_boot.c
*
* 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 <nuttx/init.h>
#include <arch/barriers.h>
#include "arm64_internal.h"
#include "arm64_arch.h"
* Public Data
****************************************************************************/
extern void *_vector_table[];
* Private Data
****************************************************************************/
* Public Functions
****************************************************************************/
#ifdef CONFIG_ARCH_HAVE_EL3
* these two function should never called
* defined to available compile error when with gcc option
*/
void arm64_boot_el3_init(void)
{
uint64_t reg;
#ifndef CONFIG_ARM64_ICACHE_DISABLE
reg = read_sysreg(sctlr_el3);
reg |= SCTLR_I_BIT;
write_sysreg(reg, sctlr_el3);
#endif
write_sysreg((uint64_t)_vector_table, vbar_el3);
UP_ISB();
reg = 0U;
reg &= ~(CPTR_TTA_BIT |
CPTR_TFP_BIT |
CPTR_TCPAC_BIT);
write_sysreg(reg, cptr_el3);
reg = 0U;
reg |= SCR_NS_BIT;
reg |= (SCR_RES1 |
#if CONFIG_ARCH_ARM64_EXCEPTION_LEVEL == 3
SCR_IRQ_BIT |
SCR_FIQ_BIT |
SCR_EA_BIT |
#endif
SCR_RW_BIT |
SCR_ST_BIT |
SCR_HCE_BIT |
SCR_SMD_BIT);
write_sysreg(reg, scr_el3);
#if CONFIG_ARM64_GIC_VERSION > 2
reg = read_sysreg(ICC_SRE_EL3);
reg |= (ICC_SRE_ELX_DFB_BIT |
ICC_SRE_ELX_DIB_BIT |
ICC_SRE_ELX_SRE_BIT |
ICC_SRE_EL3_EN_BIT);
* ICC_SRE_EL1 */
write_sysreg(reg, ICC_SRE_EL3);
#endif
UP_ISB();
}
void arm64_boot_el3_get_next_el(uint64_t switch_addr)
{
uint64_t spsr;
write_sysreg(switch_addr, elr_el3);
spsr = SPSR_DAIF_MASK;
spsr |= SPSR_MODE_EL2T;
write_sysreg(spsr, spsr_el3);
}
#endif
void arm64_boot_el2_init(void)
{
uint64_t reg;
up_flush_dcache_all();
reg = 0U;
reg = (SCTLR_EL2_RES1 |
#ifndef CONFIG_ARM64_ICACHE_DISABLE
SCTLR_I_BIT |
#endif
SCTLR_SA_BIT);
write_sysreg(reg, sctlr_el2);
#ifdef CONFIG_ARCH_CLUSTER_PMU
reg = read_sysreg(actlr_el2);
reg |= ACTLR_CLPMU_BIT;
write_sysreg(reg, actlr_el2);
#endif
reg = read_sysreg(hcr_el2);
reg |= HCR_RW_BIT;
#ifdef CONFIG_ARM64_MTE
reg |= HCR_ATA_BIT;
#endif
write_sysreg(reg, hcr_el2);
reg = 0U;
reg |= CPTR_EL2_RES1;
reg &= ~(CPTR_TFP_BIT |
CPTR_TCPAC_BIT);
write_sysreg(reg, cptr_el2);
reg = read_sysreg(cnthctl_el2);
reg |= (CNTHCTL_EL2_EL1PCEN_EN | CNTHCTL_EL2_EL1PCTEN_EN);
write_sysreg(reg, cnthctl_el2);
zero_sysreg(cntvoff_el2);
#ifdef CONFIG_ARCH_ARMV8R
zero_sysreg(cnthps_ctl_el2);
#else
zero_sysreg(cnthp_ctl_el2);
#endif
#ifdef CONFIG_ARCH_SET_VMPIDR_EL2
reg = read_sysreg(mpidr_el1);
write_sysreg(reg, vmpidr_el2);
#endif
* write_cnthp_cval_el2(~(uint64_t)0);
*/
UP_ISB();
}
void arm64_boot_el1_init(void)
{
uint64_t reg;
write_sysreg((uint64_t)_vector_table, vbar_el1);
UP_ISB();
reg = 0U;
reg |= CPACR_EL1_FPEN_NOTRAP;
write_sysreg(reg, cpacr_el1);
up_flush_dcache_all();
reg = 0U;
reg = (SCTLR_EL1_RES1 |
#ifndef CONFIG_ARM64_ICACHE_DISABLE
SCTLR_I_BIT |
#endif
SCTLR_SA_BIT);
write_sysreg(reg, sctlr_el1);
write_sysreg((~(uint64_t)0), cntv_cval_el0);
* write_cntp_cval_el0(~(uint64_t)0);
* write_cntps_cval_el1(~(uint64_t)0);
*/
UP_ISB();
}
void arm64_boot_primary_c_routine(void)
{
arm64_chip_boot();
nx_start();
}