diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index c44ebec8cf..a601a04af8 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -44,6 +44,11 @@ config ARCH_CHIP_QEMU ---help--- QEMU virt platform (ARMv8a) +config ARCH_CHIP_FVP_ARMV8R + bool "ARM FVP virt platform (ARMv8r)" + select ARCH_CORTEX_R82 + ---help--- + ARM FVP virt platform (ARMv8r) endchoice config ARCH_ARMV8A @@ -167,6 +172,7 @@ config ARCH_CHIP string default "a64" if ARCH_CHIP_A64 default "qemu" if ARCH_CHIP_QEMU + default "fvp-v8r" if ARCH_CHIP_FVP_ARMV8R config ARCH_HAVE_TRUSTZONE bool @@ -198,4 +204,7 @@ if ARCH_CHIP_QEMU source "arch/arm64/src/qemu/Kconfig" endif +if ARCH_CHIP_FVP_ARMV8R +source "arch/arm64/src/fvp-v8r/Kconfig" +endif endif # ARCH_ARM64 diff --git a/arch/arm64/include/fvp-v8r/chip.h b/arch/arm64/include/fvp-v8r/chip.h new file mode 100644 index 0000000000..665b1ebaf9 --- /dev/null +++ b/arch/arm64/include/fvp-v8r/chip.h @@ -0,0 +1,74 @@ +/**************************************************************************** + * arch/arm64/include/fvp-v8r/chip.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_INCLUDE_FVP_V8R_CHIP_H +#define __ARCH_ARM64_INCLUDE_FVP_V8R_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/* Number of bytes in @p x kibibytes/mebibytes/gibibytes */ + +#define KB(x) ((x) << 10) +#define MB(x) (KB(x) << 10) +#define GB(x) (MB(UINT64_C(x)) << 10) + +#if defined(CONFIG_ARCH_CHIP_FVP_ARMV8R) + +#if CONFIG_ARM_GIC_VERSION == 2 + +#define CONFIG_GICD_BASE 0xAF000000 +#define CONFIG_GICR_BASE 0xAF100000 + +#elif CONFIG_ARM_GIC_VERSION == 3 || CONFIG_ARM_GIC_VERSION == 4 + +#define CONFIG_GICD_BASE 0xAF000000 +#define CONFIG_GICR_BASE 0xAF100000 +#define CONFIG_GICR_OFFSET 0x20000 + +#else + +#error CONFIG_ARM_GIC_VERSION should be 2, 3 or 4 + +#endif /* CONFIG_ARM_GIC_VERSION */ + +#define CONFIG_RAMBANK_ADDR 0x00000000 +#define CONFIG_RAMBANK_SIZE MB(128) +#define CONFIG_RAMBANK_END \ + (CONFIG_RAMBANK_ADDR + CONFIG_RAMBANK_SIZE) + +#define CONFIG_DEVICEIO1_BASEADDR 0xAF000000 +#define CONFIG_DEVICEIO1_SIZE MB(128) +#define CONFIG_DEVICEIO1_END \ + (CONFIG_DEVICEIO1_BASEADDR + CONFIG_DEVICEIO1_SIZE) + +#define CONFIG_DEVICEIO2_BASEADDR 0x9C000000 +#define CONFIG_DEVICEIO2_SIZE MB(128) +#define CONFIG_DEVICEIO2_END \ + (CONFIG_DEVICEIO2_BASEADDR + CONFIG_DEVICEIO2_SIZE) + +#define CONFIG_LOAD_BASE 0x00000000 + +#endif + +#endif /* __ARCH_ARM64_INCLUDE_FVP_V8R_CHIP_H */ diff --git a/arch/arm64/include/fvp-v8r/irq.h b/arch/arm64/include/fvp-v8r/irq.h new file mode 100644 index 0000000000..19cc56028f --- /dev/null +++ b/arch/arm64/include/fvp-v8r/irq.h @@ -0,0 +1,34 @@ +/**************************************************************************** + * arch/arm64/include/fvp-v8r/irq.h + * + * 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. + * + ****************************************************************************/ + +/* This file should never be included directly but, rather, + * only indirectly through nuttx/irq.h + */ + +#ifndef __ARCH_ARM64_INCLUDE_FVP_V8R_IRQ_H +#define __ARCH_ARM64_INCLUDE_FVP_V8R_IRQ_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NR_IRQS 220 /* Total number of interrupts */ + +#endif /* __ARCH_ARM64_INCLUDE_FVP_V8R_IRQ_H */ diff --git a/arch/arm64/src/a64/a64_boot.c b/arch/arm64/src/a64/a64_boot.c index 65a5c8ce99..ac60abe843 100644 --- a/arch/arm64/src/a64/a64_boot.c +++ b/arch/arm64/src/a64/a64_boot.c @@ -49,7 +49,7 @@ * Private Data ****************************************************************************/ -static const struct arm_mmu_region mmu_regions[] = +static const struct arm_mmu_region g_mmu_regions[] = { MMU_REGION_FLAT_ENTRY("DEVICE_REGION", CONFIG_DEVICEIO_BASEADDR, CONFIG_DEVICEIO_SIZE, @@ -60,10 +60,10 @@ static const struct arm_mmu_region mmu_regions[] = MT_NORMAL | MT_RW | MT_SECURE), }; -const struct arm_mmu_config mmu_config = +const struct arm_mmu_config g_mmu_config = { - .num_regions = nitems(mmu_regions), - .mmu_regions = mmu_regions, + .num_regions = nitems(g_mmu_regions), + .mmu_regions = g_mmu_regions, }; /**************************************************************************** diff --git a/arch/arm64/src/common/arm64_cache.c b/arch/arm64/src/common/arm64_cache.c index 5e69d4c010..ce0d3f7758 100644 --- a/arch/arm64/src/common/arm64_cache.c +++ b/arch/arm64/src/common/arm64_cache.c @@ -98,7 +98,7 @@ static inline void __ic_ialluis(void) __asm__ volatile ("ic ialluis" : : : "memory"); } -size_t dcache_line_size; +size_t g_dcache_line_size; /**************************************************************************** * Private Function Prototypes @@ -111,7 +111,7 @@ static inline int arm64_dcache_range(uintptr_t start_addr, { /* Align address to line size */ - start_addr = LINE_ALIGN_DOWN(start_addr, dcache_line_size); + start_addr = LINE_ALIGN_DOWN(start_addr, g_dcache_line_size); while (start_addr < end_addr) { @@ -140,7 +140,7 @@ static inline int arm64_dcache_range(uintptr_t start_addr, DEBUGASSERT(0); } } - start_addr += dcache_line_size; + start_addr += g_dcache_line_size; } ARM64_DSB(); @@ -358,7 +358,7 @@ void up_invalidate_icache_all(void) void up_clean_dcache(uintptr_t start, uintptr_t end) { - if (dcache_line_size < (end - start)) + if (g_dcache_line_size < (end - start)) { arm64_dcache_range(start, end, CACHE_OP_WB); } @@ -419,7 +419,7 @@ void up_clean_dcache_all(void) void up_flush_dcache(uintptr_t start, uintptr_t end) { - if (dcache_line_size < (end - start)) + if (g_dcache_line_size < (end - start)) { arm64_dcache_range(start, end, CACHE_OP_WB_INVD); } diff --git a/arch/arm64/src/common/arm64_mmu.c b/arch/arm64/src/common/arm64_mmu.c index 025183a8ef..cb27bb2798 100644 --- a/arch/arm64/src/common/arm64_mmu.c +++ b/arch/arm64/src/common/arm64_mmu.c @@ -157,7 +157,7 @@ aligned_data(XLAT_TABLE_ENTRIES * sizeof(uint64_t)); /* NuttX RTOS execution regions with appropriate attributes */ -static const struct arm_mmu_region mmu_nxrt_regions[] = +static const struct arm_mmu_region g_mmu_nxrt_regions[] = { /* Mark text segment cacheable,read only and executable */ @@ -184,10 +184,10 @@ static const struct arm_mmu_region mmu_nxrt_regions[] = MT_NORMAL | MT_RW | MT_SECURE), }; -static const struct arm_mmu_config mmu_nxrt_config = +static const struct arm_mmu_config g_mmu_nxrt_config = { - .num_regions = nitems(mmu_nxrt_regions), - .mmu_regions = mmu_nxrt_regions, + .num_regions = nitems(g_mmu_nxrt_regions), + .mmu_regions = g_mmu_nxrt_regions, }; /*************************************************************************** @@ -488,9 +488,9 @@ static void setup_page_tables(void) const struct arm_mmu_region *region; uint64_t max_va = 0, max_pa = 0; - for (index = 0; index < mmu_config.num_regions; index++) + for (index = 0; index < g_mmu_config.num_regions; index++) { - region = &mmu_config.mmu_regions[index]; + region = &g_mmu_config.mmu_regions[index]; max_va = MAX(max_va, region->base_va + region->size); max_pa = MAX(max_pa, region->base_pa + region->size); } @@ -502,9 +502,9 @@ static void setup_page_tables(void) /* create translation tables for user provided platform regions */ - for (index = 0; index < mmu_config.num_regions; index++) + for (index = 0; index < g_mmu_config.num_regions; index++) { - region = &mmu_config.mmu_regions[index]; + region = &g_mmu_config.mmu_regions[index]; if (region->size || region->attrs) { init_xlat_tables(region); @@ -513,9 +513,9 @@ static void setup_page_tables(void) /* setup translation table for mirtos execution regions */ - for (index = 0; index < mmu_nxrt_config.num_regions; index++) + for (index = 0; index < g_mmu_nxrt_config.num_regions; index++) { - region = &mmu_nxrt_config.mmu_regions[index]; + region = &g_mmu_nxrt_config.mmu_regions[index]; if (region->size || region->attrs) { init_xlat_tables(region); @@ -622,7 +622,7 @@ int arm64_mmu_init(bool is_primary_core) ctr_el0 = read_sysreg(CTR_EL0); dminline = (ctr_el0 >> CTR_EL0_DMINLINE_SHIFT) & CTR_EL0_DMINLINE_MASK; - dcache_line_size = 4 << dminline; + g_dcache_line_size = 4 << dminline; return 0; } diff --git a/arch/arm64/src/common/arm64_mmu.h b/arch/arm64/src/common/arm64_mmu.h index ad627579f3..eea3ea52b5 100644 --- a/arch/arm64/src/common/arm64_mmu.h +++ b/arch/arm64/src/common/arm64_mmu.h @@ -240,8 +240,8 @@ struct arm_mmu_ptables * regions enabled during kernel initialization. */ -extern const struct arm_mmu_config mmu_config; -extern size_t dcache_line_size; +extern const struct arm_mmu_config g_mmu_config; +extern size_t g_dcache_line_size; /**************************************************************************** * Public Function Prototypes diff --git a/arch/arm64/src/common/arm64_mpu.c b/arch/arm64/src/common/arm64_mpu.c index 3344d5f544..aec54f130f 100644 --- a/arch/arm64/src/common/arm64_mpu.c +++ b/arch/arm64/src/common/arm64_mpu.c @@ -206,7 +206,7 @@ void arm64_mpu_init(bool is_primary_core) return; } - if (mpu_config.num_regions > get_num_regions()) + if (g_mpu_config.num_regions > get_num_regions()) { /* Attempt to configure more MPU regions than * what is supported by hardware. As this operation @@ -216,7 +216,7 @@ void arm64_mpu_init(bool is_primary_core) */ __MPU_ASSERT(0, "Request to configure: %u regions (supported: %u)\n", - mpu_config.num_regions, get_num_regions()); + g_mpu_config.num_regions, get_num_regions()); return; } @@ -228,14 +228,14 @@ void arm64_mpu_init(bool is_primary_core) /* Program fixed regions configured at SOC definition. */ - for (r_index = 0U; r_index < mpu_config.num_regions; r_index++) + for (r_index = 0U; r_index < g_mpu_config.num_regions; r_index++) { - region_init(r_index, &mpu_config.mpu_regions[r_index]); + region_init(r_index, &g_mpu_config.mpu_regions[r_index]); } /* Update the number of programmed MPU regions. */ - static_regions_num = mpu_config.num_regions; + static_regions_num = g_mpu_config.num_regions; arm64_core_mpu_enable(); } diff --git a/arch/arm64/src/common/arm64_mpu.h b/arch/arm64/src/common/arm64_mpu.h index fe19fdaf43..e25236775e 100644 --- a/arch/arm64/src/common/arm64_mpu.h +++ b/arch/arm64/src/common/arm64_mpu.h @@ -288,7 +288,7 @@ struct arm64_mpu_config * regions enabled during kernel initialization. */ -extern const struct arm64_mpu_config mpu_config; +extern const struct arm64_mpu_config g_mpu_config; /**************************************************************************** * Public Function Prototypes diff --git a/arch/arm64/src/fvp-v8r/Kconfig b/arch/arm64/src/fvp-v8r/Kconfig new file mode 100644 index 0000000000..5abaa4a9e4 --- /dev/null +++ b/arch/arm64/src/fvp-v8r/Kconfig @@ -0,0 +1,32 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_CHIP_FVP_ARMV8R + +menu "FVP ARMv8-R Virt Chip Selection" + +choice + prompt "FVP Core Configuration" + default ARCH_CHIP_FVP_R82 + +config ARCH_CHIP_FVP_R82 + bool "FVP virtual Processor (Cortex-r82)" + select ARCH_HAVE_MULTICPU + select ARMV8R_HAVE_GICv3 + select ARCH_EARLY_PRINT + select ARCH_SET_VMPIDR_EL2 + +endchoice # FVP Chip Selection + +endmenu # "FVP Chip Selection" + +menu "FVP Peripheral Selection" +config FVP_UART_PL011 + bool "UART" + default n + select UART1_SERIALDRIVER +endmenu # FVP Peripheral Selection + +endif # ARCH_CHIP_FVP_ARMV8R diff --git a/arch/arm64/src/fvp-v8r/Make.defs b/arch/arm64/src/fvp-v8r/Make.defs new file mode 100644 index 0000000000..9cf766dd1d --- /dev/null +++ b/arch/arm64/src/fvp-v8r/Make.defs @@ -0,0 +1,25 @@ +############################################################################ +# arch/arm64/src/fvp-v8r/Make.defs +# +# 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. +# +############################################################################ + +include common/Make.defs + +# fvp-specific C source files +CHIP_CSRCS = fvp_boot.c serial_pl011.c +CHIP_ASRCS = fvp_lowputc.S diff --git a/arch/arm64/src/fvp-v8r/chip.h b/arch/arm64/src/fvp-v8r/chip.h new file mode 100644 index 0000000000..627275df9e --- /dev/null +++ b/arch/arm64/src/fvp-v8r/chip.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * arch/arm64/src/fvp-v8r/chip.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_FVP_V8R_CHIP_H +#define __ARCH_ARM64_SRC_FVP_V8R_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Macro Definitions + ****************************************************************************/ + +#endif /* __ARCH_ARM64_SRC_FVP_V8R_CHIP_H */ diff --git a/arch/arm64/src/fvp-v8r/fvp_boot.c b/arch/arm64/src/fvp-v8r/fvp_boot.c new file mode 100644 index 0000000000..bc82b27cab --- /dev/null +++ b/arch/arm64/src/fvp-v8r/fvp_boot.c @@ -0,0 +1,205 @@ +/**************************************************************************** + * arch/arm64/src/fvp-v8r/fvp_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 + +#include +#include +#include + +#include + +#ifdef CONFIG_SMP +#include "arm64_smp.h" +#endif + +#include "arm64_arch.h" +#include "arm64_internal.h" +#include "arm64_mpu.h" +#include "chip.h" +#include "fvp_boot.h" +#include "serial_pl011.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct arm64_mpu_region g_mpu_regions[] = +{ + /* Region 0 NuttX text */ + + MPU_REGION_ENTRY("nx_code", + (uint64_t)_stext, + (uint64_t)_etext, + REGION_RAM_TEXT_ATTR), + + /* Region 1 NuttX rodata */ + + MPU_REGION_ENTRY("nx_rodata", + (uint64_t)_srodata, + (uint64_t)_erodata, + REGION_RAM_RO_ATTR), + + /* Region 2 NuttX data */ + + MPU_REGION_ENTRY("nx_data", + (uint64_t)_sdata, + (uint64_t)CONFIG_RAMBANK_END, + REGION_RAM_ATTR), + + /* Region 3 device region */ + + MPU_REGION_ENTRY("DEVICE1", + (uint64_t)CONFIG_DEVICEIO1_BASEADDR, + (uint64_t)CONFIG_DEVICEIO1_END, + REGION_DEVICE_ATTR), + + /* Region 4 device region */ + + MPU_REGION_ENTRY("DEVICE2", + (uint64_t)CONFIG_DEVICEIO2_BASEADDR, + (uint64_t)CONFIG_DEVICEIO2_END, + REGION_DEVICE_ATTR) +}; + +const struct arm64_mpu_config g_mpu_config = +{ + .num_regions = nitems(g_mpu_regions), + .mpu_regions = g_mpu_regions, +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm64_el_init + * + * Description: + * The function called from arm64_head.S at very early stage for these + * platform, it's use to: + * - Handling special hardware initialize routine which is need to + * run at high ELs + * - Initialize system software such as hypervisor or security firmware + * which is need to run at high ELs + * + ****************************************************************************/ + +void arm64_el_init(void) +{ + write_sysreg(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, cntfrq_el0); + + ARM64_ISB(); +} + +#ifdef CONFIG_SMP + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_cpu_index + * + * Description: + * Return an index in the range of 0 through (CONFIG_SMP_NCPUS-1) that + * corresponds to the currently executing CPU. + * + * If TLS is enabled, then the RTOS can get this information from the TLS + * info structure. Otherwise, the MCU-specific logic must provide some + * mechanism to provide the CPU index. + * + * Input Parameters: + * None + * + * Returned Value: + * An integer index in the range of 0 through (CONFIG_SMP_NCPUS-1) that + * corresponds to the currently executing CPU. + * + ****************************************************************************/ + +int up_cpu_index(void) +{ + /* Read the Multiprocessor Affinity Register (MPIDR) + * And return the CPU ID field + */ + + return MPID_TO_CORE(GET_MPIDR(), 0); +} + +/**************************************************************************** + * Name: arm64_get_mpid + * + * Description: + * The function from cpu index to get cpu mpid which is reading + * from mpidr_el1 register. Different ARM64 Core will use different + * Affn define, the mpidr_el1 value is not CPU number, So we need + * to change CPU number to mpid and vice versa + * + ****************************************************************************/ + +uint64_t arm64_get_mpid(int cpu) +{ + return CORE_TO_MPID(cpu, 0); +} + +#endif /* CONFIG_SMP */ + +/**************************************************************************** + * Name: arm64_chip_boot + * + * Description: + * Complete boot operations started in arm64_head.S + * + ****************************************************************************/ + +void arm64_chip_boot(void) +{ + /* MAP IO and DRAM, enable MMU. */ + + uint64_t cpumpid; + cpumpid = read_sysreg(mpidr_el1); + + sinfo("Main CPU 0x%-16"PRIx64"", cpumpid); + + arm64_mpu_init(true); + +#if defined(CONFIG_SMP) && defined(CONFIG_ARCH_HAVE_PCSI) + arm64_psci_init("smc"); +#endif + + /* Perform board-specific device initialization. This would include + * configuration of board specific resources such as GPIOs, LEDs, etc. + */ + + fvp_board_initialize(); + +#ifdef USE_EARLYSERIALINIT + /* Perform early serial initialization if we are going to use the serial + * driver. + */ + + fvp_earlyserialinit(); +#endif +} diff --git a/arch/arm64/src/fvp-v8r/fvp_boot.h b/arch/arm64/src/fvp-v8r/fvp_boot.h new file mode 100644 index 0000000000..cf05afe5c6 --- /dev/null +++ b/arch/arm64/src/fvp-v8r/fvp_boot.h @@ -0,0 +1,85 @@ +/**************************************************************************** + * arch/arm64/src/fvp-v8r/fvp_boot.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_FVP_V8R_FVP_BOOT_H +#define __ARCH_ARM64_SRC_FVP_V8R_FVP_BOOT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "arm64_internal.h" +#include "arm64_arch.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +#define CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC 100000000 + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: fvp_board_initialize + * + * Description: + * All fvp architectures must provide the following entry point. This + * entry point is called in the initialization phase -- after + * imx_memory_initialize and after all memory has been configured and + * mapped but before any devices have been initialized. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void fvp_board_initialize(void); + +void up_lowputc(char c); +void up_low_flush(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM64_SRC_FVP_V8R_FVP_BOOT_H */ diff --git a/arch/arm64/src/fvp-v8r/fvp_lowputc.S b/arch/arm64/src/fvp-v8r/fvp_lowputc.S new file mode 100644 index 0000000000..7922dd35db --- /dev/null +++ b/arch/arm64/src/fvp-v8r/fvp_lowputc.S @@ -0,0 +1,101 @@ +/**************************************************************************** + * arch/arm64/src/fvp-v8r/fvp_lowputc.S + * + * 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. + * + **************************************************************************** + * + * DESCRIPTION + * Wrapper for early printk + * + ***************************************************************************/ + +#include + +#include "arm64_macro.inc" +#include "serial_pl011.h" + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + .file "fvp_lowputc.S" + +/**************************************************************************** + * Assembly Macros + ****************************************************************************/ + + /* 32-bit register definition for qemu pl011 uart */ + +#define EARLY_UART_PL011_BAUD_RATE 115200 + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* PL011 UART initialization + * xb: register which contains the UART base address + * c: scratch register number + */ + +GTEXT(up_earlyserialinit) +SECTION_FUNC(text, up_earlyserialinit) + ldr x15, =CONFIG_UART0_BASE + mov x0, #(7372800 / EARLY_UART_PL011_BAUD_RATE % 16) + strh w0, [x15, #0x28] /* -> UARTFBRD (Baud divisor fraction) */ + mov x0, #(7372800 / EARLY_UART_PL011_BAUD_RATE / 16) + strh w0, [x15, #0x24] /* -> UARTIBRD (Baud divisor integer) */ + mov x0, #0x60 /* 8n1 */ + str w0, [x15, #0x2C] /* -> UARTLCR_H (Line control) */ + ldr x0, =0x00000301 /* RXE | TXE | UARTEN */ + str w0, [x15, #0x30] /* -> UARTCR (Control Register) */ + ret + +/* PL011 UART wait UART to be ready to transmit + * xb: register which contains the UART base address + * c: scratch register number + */ + +.macro early_uart_ready xb, wt +1: + ldrh \wt, [\xb, #0x18] /* <- UARTFR (Flag register) */ + tst \wt, #0x8 /* Check BUSY bit */ + b.ne 1b /* Wait for the UART to be ready */ +.endm + +/* PL011 UART transmit character + * xb: register which contains the UART base address + * wt: register which contains the character to transmit + */ + +.macro early_uart_transmit xb, wt + strb \wt, [\xb] /* -> UARTDR (Data Register) */ +.endm + +/* Print a character on the UART - this function is called by C + * x0: character to print + */ + +GTEXT(up_lowputc) +SECTION_FUNC(text, up_lowputc) + ldr x15, =CONFIG_UART0_BASE + early_uart_ready x15, w2 + early_uart_transmit x15, w0 + ret diff --git a/arch/arm64/src/fvp-v8r/serial_pl011.c b/arch/arm64/src/fvp-v8r/serial_pl011.c new file mode 100644 index 0000000000..68f615ea96 --- /dev/null +++ b/arch/arm64/src/fvp-v8r/serial_pl011.c @@ -0,0 +1,881 @@ +/*************************************************************************** + * arch/arm64/src/fvp-v8r/serial_pl011.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 +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_SERIAL_TERMIOS +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "arm64_arch.h" +#include "arm64_internal.h" +#include "serial_pl011.h" +#include "arm64_arch_timer.h" +#include "fvp_boot.h" +#include "arm64_gic.h" +#include "chip.h" + +#ifdef USE_SERIALDRIVER + +/*************************************************************************** + * Pre-processor Definitions + ***************************************************************************/ + +/* Which UART with be tty0/console and which tty1-4? The console will + * always be ttyS0. If there is no console then will use the lowest + * numbered UART. + */ + +/* First pick the console and ttys0. This could be any of UART1-5 */ + +#if defined(CONFIG_UART1_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart1port /* UART1 is console */ +# define TTYS0_DEV g_uart1port /* UART1 is ttyS0 */ +# define UART1_ASSIGNED 1 +#endif + +#define PL011_BIT_MASK(x, y) (((2 << (x)) - 1) << (y)) + +/* PL011 Uart Flags Register */ +#define PL011_FR_CTS BIT(0) /* clear to send - inverted */ +#define PL011_FR_DSR BIT(1) /* data set ready - inverted + */ +#define PL011_FR_DCD BIT(2) /* data carrier detect - + * inverted */ +#define PL011_FR_BUSY BIT(3) /* busy transmitting data */ +#define PL011_FR_RXFE BIT(4) /* receive FIFO empty */ +#define PL011_FR_TXFF BIT(5) /* transmit FIFO full */ +#define PL011_FR_RXFF BIT(6) /* receive FIFO full */ +#define PL011_FR_TXFE BIT(7) /* transmit FIFO empty */ +#define PL011_FR_RI BIT(8) /* ring indicator - inverted */ + +/* PL011 Integer baud rate register */ +#define PL011_IBRD_BAUD_DIVINT_MASK 0xff /* 16 bits of divider */ + +/* PL011 Fractional baud rate register */ +#define PL011_FBRD_BAUD_DIVFRAC 0x3f +#define PL011_FBRD_WIDTH 6u + +/* PL011 Receive status register / error clear register */ +#define PL011_RSR_ECR_FE BIT(0) /* framing error */ +#define PL011_RSR_ECR_PE BIT(1) /* parity error */ +#define PL011_RSR_ECR_BE BIT(2) /* break error */ +#define PL011_RSR_ECR_OE BIT(3) /* overrun error */ + +#define PL011_RSR_ERROR_MASK (PL011_RSR_ECR_FE | PL011_RSR_ECR_PE | \ + PL011_RSR_ECR_BE | PL011_RSR_ECR_OE) + +/* PL011 Line Control Register */ +#define PL011_LCRH_BRK BIT(0) /* send break */ +#define PL011_LCRH_PEN BIT(1) /* enable parity */ +#define PL011_LCRH_EPS BIT(2) /* select even parity */ +#define PL011_LCRH_STP2 BIT(3) /* select two stop bits */ +#define PL011_LCRH_FEN BIT(4) /* enable FIFOs */ +#define PL011_LCRH_WLEN_SHIFT 5 /* word length */ +#define PL011_LCRH_WLEN_WIDTH 2 +#define PL011_LCRH_SPS BIT(7) /* stick parity bit */ + +#define PL011_LCRH_WLEN_SIZE(x) ((x) - 5) + +#define PL011_LCRH_FORMAT_MASK (PL011_LCRH_PEN | PL011_LCRH_EPS | \ + PL011_LCRH_SPS | \ + PL011_BIT_MASK(PL011_LCRH_WLEN_WIDTH, \ + PL011_LCRH_WLEN_SHIFT)) + +#define PL011_LCRH_PARTIY_EVEN (PL011_LCRH_PEN | PL011_LCRH_EPS) +#define PL011_LCRH_PARITY_ODD (PL011_LCRH_PEN) +#define PL011_LCRH_PARITY_NONE (0) + +/* PL011 Control Register */ +#define PL011_CR_UARTEN BIT(0) /* enable uart operations */ +#define PL011_CR_SIREN BIT(1) /* enable IrDA SIR */ +#define PL011_CR_SIRLP BIT(2) /* IrDA SIR low power mode */ +#define PL011_CR_LBE BIT(7) /* loop back enable */ +#define PL011_CR_TXE BIT(8) /* transmit enable */ +#define PL011_CR_RXE BIT(9) /* receive enable */ +#define PL011_CR_DTR BIT(10) /* data transmit ready */ +#define PL011_CR_RTS BIT(11) /* request to send */ +#define PL011_CR_Out1 BIT(12) +#define PL011_CR_Out2 BIT(13) +#define PL011_CR_RTSEn BIT(14) /* RTS hw flow control enable + */ +#define PL011_CR_CTSEn BIT(15) /* CTS hw flow control enable + */ + +/* PL011 Interrupt Fifo Level Select Register */ +#define PL011_IFLS_TXIFLSEL_SHIFT 0 /* bits 2:0 */ +#define PL011_IFLS_TXIFLSEL_WIDTH 3 +#define PL011_IFLS_RXIFLSEL_SHIFT 3 /* bits 5:3 */ +#define PL011_IFLS_RXIFLSEL_WIDTH 3 + +/* PL011 Interrupt Mask Set/Clear Register */ +#define PL011_IMSC_RIMIM BIT(0) /* RTR modem interrupt mask */ +#define PL011_IMSC_CTSMIM BIT(1) /* CTS modem interrupt mask */ +#define PL011_IMSC_DCDMIM BIT(2) /* DCD modem interrupt mask */ +#define PL011_IMSC_DSRMIM BIT(3) /* DSR modem interrupt mask */ +#define PL011_IMSC_RXIM BIT(4) /* receive interrupt mask */ +#define PL011_IMSC_TXIM BIT(5) /* transmit interrupt mask */ +#define PL011_IMSC_RTIM BIT(6) /* receive timeout interrupt + * mask */ +#define PL011_IMSC_FEIM BIT(7) /* framing error interrupt + * mask */ +#define PL011_IMSC_PEIM BIT(8) /* parity error interrupt mask + */ +#define PL011_IMSC_BEIM BIT(9) /* break error interrupt mask + */ +#define PL011_IMSC_OEIM BIT(10) /* overrun error interrupt + * mask */ + +#define PL011_IMSC_ERROR_MASK (PL011_IMSC_FEIM | \ + PL011_IMSC_PEIM | PL011_IMSC_BEIM | \ + PL011_IMSC_OEIM) + +#define PL011_IMSC_MASK_ALL (PL011_IMSC_OEIM | PL011_IMSC_BEIM | \ + PL011_IMSC_PEIM | PL011_IMSC_FEIM | \ + PL011_IMSC_RIMIM | \ + PL011_IMSC_CTSMIM | \ + PL011_IMSC_DCDMIM | \ + PL011_IMSC_DSRMIM | \ + PL011_IMSC_RXIM | PL011_IMSC_TXIM | \ + PL011_IMSC_RTIM) + +/*************************************************************************** + * Private Types + ***************************************************************************/ + +/* UART PL011 register map structure */ + +struct pl011_regs +{ + uint32_t dr; /* data register */ + union + { + uint32_t rsr; + uint32_t ecr; + }; + + uint32_t reserved_0[4]; + uint32_t fr; /* flags register */ + uint32_t reserved_1; + uint32_t ilpr; + uint32_t ibrd; + uint32_t fbrd; + uint32_t lcr_h; + uint32_t cr; + uint32_t ifls; + uint32_t imsc; + uint32_t ris; + uint32_t mis; + uint32_t icr; + uint32_t dmacr; +}; + +struct pl011_config +{ + volatile struct pl011_regs *uart; + uint32_t sys_clk_freq; +}; + +/* Device data structure */ + +struct pl011_data +{ + uint32_t baud_rate; + bool sbsa; +}; + +struct pl011_uart_port_s +{ + struct pl011_data data; + struct pl011_config config; + unsigned int irq_num; + bool is_console; +}; + +/*************************************************************************** + * Private Functions + ***************************************************************************/ + +static void pl011_enable(const struct pl011_uart_port_s *sport) +{ + const struct pl011_config *config = &sport->config; + + config->uart->cr |= PL011_CR_UARTEN; +} + +static void pl011_disable(const struct pl011_uart_port_s *sport) +{ + const struct pl011_config *config = &sport->config; + + config->uart->cr &= ~PL011_CR_UARTEN; +} + +static void pl011_enable_fifo(const struct pl011_uart_port_s *sport) +{ + const struct pl011_config *config = &sport->config; + + config->uart->lcr_h |= PL011_LCRH_FEN; +} + +static void pl011_disable_fifo(const struct pl011_uart_port_s *sport) +{ + const struct pl011_config *config = &sport->config; + + config->uart->lcr_h &= ~PL011_LCRH_FEN; +} + +static int pl011_set_baudrate(const struct pl011_uart_port_s *sport, + uint32_t clk, uint32_t baudrate) +{ + const struct pl011_config *config = &sport->config; + + /* Avoiding float calculations, bauddiv is left shifted by 6 */ + + uint64_t bauddiv = + (((uint64_t)clk) << PL011_FBRD_WIDTH) / (baudrate * 16U); + + /* Valid bauddiv value + * uart_clk (min) >= 16 x baud_rate (max) + * uart_clk (max) <= 16 x 65535 x baud_rate (min) + */ + + if ((bauddiv < (1U << PL011_FBRD_WIDTH)) || + (bauddiv > (65535U << PL011_FBRD_WIDTH))) + { + return -EINVAL; + } + + config->uart->ibrd = bauddiv >> PL011_FBRD_WIDTH; + config->uart->fbrd = bauddiv & ((1U << PL011_FBRD_WIDTH) - 1U); + + ARM64_DMB(); + + /* In order to internally update the contents of ibrd or fbrd, a + * lcr_h write must always be performed at the end + * ARM DDI 0183F, Pg 3-13 + */ + + config->uart->lcr_h = config->uart->lcr_h; + + return 0; +} + +static void pl011_irq_tx_enable(const struct pl011_uart_port_s *sport) +{ + const struct pl011_config *config = &sport->config; + + config->uart->imsc |= PL011_IMSC_TXIM; +} + +static void pl011_irq_tx_disable(const struct pl011_uart_port_s *sport) +{ + const struct pl011_config *config = &sport->config; + + config->uart->imsc &= ~PL011_IMSC_TXIM; +} + +static void pl011_irq_rx_enable(const struct pl011_uart_port_s *sport) +{ + const struct pl011_config *config = &sport->config; + + config->uart->imsc |= PL011_IMSC_RXIM | PL011_IMSC_RTIM; +} + +static void pl011_irq_rx_disable(const struct pl011_uart_port_s *sport) +{ + const struct pl011_config *config = &sport->config; + + config->uart->imsc &= ~(PL011_IMSC_RXIM | PL011_IMSC_RTIM); +} + +static int pl011_irq_tx_complete(const struct pl011_uart_port_s *sport) +{ + const struct pl011_config *config = &sport->config; + + /* check for TX FIFO empty */ + + return config->uart->fr & PL011_FR_TXFE; +} + +static int pl011_irq_rx_ready(const struct pl011_uart_port_s *sport) +{ + const struct pl011_config *config = &sport->config; + const struct pl011_data *data = &sport->data; + + if (!data->sbsa && !(config->uart->cr & PL011_CR_RXE)) + { + return false; + } + + return (config->uart->imsc & PL011_IMSC_RXIM) && + (!(config->uart->fr & PL011_FR_RXFE)); +} + +/*************************************************************************** + * Name: pl011_txready + * + * Description: + * Return true if the tranmsit fifo is not full + * + ***************************************************************************/ + +static bool pl011_txready(struct uart_dev_s *dev) +{ + struct pl011_uart_port_s *sport = (struct pl011_uart_port_s *)dev->priv; + const struct pl011_config *config = &sport->config; + struct pl011_data *data = &sport->data; + + if (!data->sbsa && !(config->uart->cr & PL011_CR_TXE)) + { + return false; + } + + return (config->uart->imsc & PL011_IMSC_TXIM) && + pl011_irq_tx_complete(sport); +} + +/*************************************************************************** + * Name: pl011_txempty + * + * Description: + * Return true if the transmit fifo is empty + * + ***************************************************************************/ + +static bool pl011_txempty(struct uart_dev_s *dev) +{ + struct pl011_uart_port_s *sport = (struct pl011_uart_port_s *)dev->priv; + + return pl011_irq_tx_complete(sport); +} + +/*************************************************************************** + * Name: pl011_send + * + * Description: + * This method will send one byte on the UART + * + ***************************************************************************/ + +static void pl011_send(struct uart_dev_s *dev, int ch) +{ + struct pl011_uart_port_s *sport = (struct pl011_uart_port_s *)dev->priv; + const struct pl011_config *config = &sport->config; + + config->uart->dr = ch; +} + +/*************************************************************************** + * Name: pl011_rxavailable + * + * Description: + * Return true if the receive fifo is not empty + * + ***************************************************************************/ + +static bool pl011_rxavailable(struct uart_dev_s *dev) +{ + struct pl011_uart_port_s *sport = (struct pl011_uart_port_s *)dev->priv; + const struct pl011_config *config = &sport->config; + struct pl011_data *data = &sport->data; + + if (!data->sbsa && + (!(config->uart->cr & PL011_CR_UARTEN) || + !(config->uart->cr & PL011_CR_RXE))) + { + return false; + } + + return (config->uart->fr & PL011_FR_RXFE) == 0U; +} + +/*************************************************************************** + * Name: pl011_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ***************************************************************************/ + +static void pl011_rxint(struct uart_dev_s *dev, bool enable) +{ + struct pl011_uart_port_s *sport = (struct pl011_uart_port_s *)dev->priv; + + if (enable) + { + pl011_irq_rx_enable(sport); + } + else + { + pl011_irq_rx_disable(sport); + } +} + +/*************************************************************************** + * Name: pl011_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ***************************************************************************/ + +static void pl011_txint(struct uart_dev_s *dev, bool enable) +{ + struct pl011_uart_port_s *sport = (struct pl011_uart_port_s *)dev->priv; + irqstate_t flags; + + flags = enter_critical_section(); + + if (enable) + { + pl011_irq_tx_enable(sport); + + /* Fake a TX interrupt here by just calling uart_xmitchars() with + * interrupts disabled (note this may recurse). + */ + + uart_xmitchars(dev); + } + else + { + pl011_irq_tx_disable(sport); + } + + leave_critical_section(flags); +} + +/*************************************************************************** + * Name: pl011_receive + * + * Description: + * Called (usually) from the interrupt level to receive one + * character from the UART. Error bits associated with the + * receipt are provided in the return 'status'. + * + ***************************************************************************/ + +static int pl011_receive(struct uart_dev_s *dev, unsigned int *status) +{ + struct pl011_uart_port_s *sport = (struct pl011_uart_port_s *)dev->priv; + const struct pl011_config *config = &sport->config; + unsigned int rx; + + rx = config->uart->dr; + + *status = 0; + + return rx; +} + +/*************************************************************************** + * Name: pl011_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * for current qemu configure, + * + ***************************************************************************/ + +static int pl011_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + int ret = OK; + UNUSED(filep); + UNUSED(arg); + + switch (cmd) + { + case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */ + case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */ + default: + { + ret = -ENOTTY; + break; + } + } + + return ret; +} + +/*************************************************************************** + * Name: pl011_irq_handler (and front-ends) + * + * Description: + * This is the common UART interrupt handler. It should cal + * uart_transmitchars or uart_receivechar to perform the appropriate data + * transfers. + * + ***************************************************************************/ + +static int pl011_irq_handler(int irq, void *context, void *arg) +{ + struct uart_dev_s *dev = (struct uart_dev_s *)arg; + struct pl011_uart_port_s *sport; + UNUSED(irq); + UNUSED(context); + + DEBUGASSERT(dev != NULL && dev->priv != NULL); + sport = (struct pl011_uart_port_s *)dev->priv; + + if (pl011_irq_rx_ready(sport)) + { + uart_recvchars(dev); + } + + if (pl011_txready(dev)) + { + uart_xmitchars(dev); + } + + return OK; +} + +/*************************************************************************** + * Name: pl011_detach + * + * Description: + * Detach UART interrupts. This method is called when the serial port is + * closed normally just before the shutdown method is called. The + * exception is the serial console which is never shutdown. + * + ***************************************************************************/ + +static void pl011_detach(struct uart_dev_s *dev) +{ + struct pl011_uart_port_s *sport = (struct pl011_uart_port_s *)dev->priv; + + up_disable_irq(sport->irq_num); + irq_detach(sport->irq_num); +} + +/*************************************************************************** + * Name: pl011_attach + * + * Description: + * Configure the UART to operation in interrupt driven mode. + * This method is called when the serial port is opened. + * Normally, this is just after the setup() method is called, + * however, the serial console may operate in + * a non-interrupt driven mode during the boot phase. + * + * RX and TX interrupts are not enabled when by the attach method + * (unless the hardware supports multiple levels of interrupt + * enabling). The RX and TX interrupts are not enabled until + * the txint() and rxint() methods are called. + * + ***************************************************************************/ + +static int pl011_attach(struct uart_dev_s *dev) +{ + struct pl011_uart_port_s *sport; + struct pl011_data *data; + int ret; + + sport = (struct pl011_uart_port_s *)dev->priv; + data = &sport->data; + + ret = irq_attach(sport->irq_num, pl011_irq_handler, dev); + + if (ret == OK) + { + up_enable_irq(sport->irq_num); + } + else + { + sinfo("error ret=%d\n", ret); + } + + if (!data->sbsa) + { + pl011_enable(sport); + } + + return ret; +} + +/*************************************************************************** + * Name: pl011_shutdown + * + * Description: + * Disable the UART. This method is called when the serial + * port is closed + * + ***************************************************************************/ + +static void pl011_shutdown(struct uart_dev_s *dev) +{ + UNUSED(dev); + sinfo("%s: call unexpected\n", __func__); +} + +static int pl011_setup(struct uart_dev_s *dev) +{ + struct pl011_uart_port_s *sport = (struct pl011_uart_port_s *)dev->priv; + const struct pl011_config *config = &sport->config; + struct pl011_data *data = &sport->data; + int ret; + uint32_t lcrh; + irqstate_t i_flags; + + i_flags = up_irq_save(); + + /* If working in SBSA mode, we assume that UART is already configured, + * or does not require configuration at all (if UART is emulated by + * virtualization software). + */ + + if (!data->sbsa) + { + /* disable the uart */ + + pl011_disable(sport); + pl011_disable_fifo(sport); + + /* Set baud rate */ + + ret = pl011_set_baudrate(sport, config->sys_clk_freq, + data->baud_rate); + if (ret != 0) + { + up_irq_restore(i_flags); + return ret; + } + + /* Setting the default character format */ + + lcrh = config->uart->lcr_h & ~(PL011_LCRH_FORMAT_MASK); + lcrh &= ~(BIT(0) | BIT(7)); + lcrh |= PL011_LCRH_WLEN_SIZE(8) << PL011_LCRH_WLEN_SHIFT; + config->uart->lcr_h = lcrh; + + /* Enabling the FIFOs */ + + pl011_enable_fifo(sport); + } + + /* initialize all IRQs as masked */ + + config->uart->imsc = 0U; + config->uart->icr = PL011_IMSC_MASK_ALL; + + if (!data->sbsa) + { + config->uart->dmacr = 0U; + ARM64_ISB(); + config->uart->cr &= ~(BIT(14) | BIT(15) | BIT(1)); + config->uart->cr |= PL011_CR_RXE | PL011_CR_TXE; + ARM64_ISB(); + } + + up_irq_restore(i_flags); + + return 0; +} + +/*************************************************************************** + * Private Data + ***************************************************************************/ + +/* Serial driver UART operations */ + +static const struct uart_ops_s g_uart_ops = +{ + .setup = pl011_setup, + .shutdown = pl011_shutdown, + .attach = pl011_attach, + .detach = pl011_detach, + .ioctl = pl011_ioctl, + .receive = pl011_receive, + .rxint = pl011_rxint, + .rxavailable = pl011_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = NULL, +#endif + .send = pl011_send, + .txint = pl011_txint, + .txready = pl011_txready, + .txempty = pl011_txempty, +}; + +/* This describes the state of the uart1 port. */ + +static struct pl011_uart_port_s g_uart1priv = +{ + .data = + { + .baud_rate = CONFIG_UART1_BAUD, + .sbsa = false, + }, + + .config = + { + .uart = (volatile struct pl011_regs *)CONFIG_UART1_BASE, + .sys_clk_freq = 24000000, + }, + + .irq_num = CONFIG_UART1_IRQ, + .is_console = 1, +}; + +/* I/O buffers */ + +static char g_uart1rxbuffer[CONFIG_UART1_RXBUFSIZE]; +static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE]; + +static struct uart_dev_s g_uart1port = +{ + .recv = + { + .size = CONFIG_UART1_RXBUFSIZE, + .buffer = g_uart1rxbuffer, + }, + + .xmit = + { + .size = CONFIG_UART1_TXBUFSIZE, + .buffer = g_uart1txbuffer, + }, + + .ops = &g_uart_ops, + .priv = &g_uart1priv, +}; + +/*************************************************************************** + * Public Functions + ***************************************************************************/ + +/*************************************************************************** + * Name: qemu_earlyserialinit + * + * Description: + * Performs the low level UART initialization early in + * debug so that the serial console will be available + * during bootup. This must be called before arm_serialinit. + * + ***************************************************************************/ + +void fvp_earlyserialinit(void) +{ + /* NOTE: This function assumes that low level hardware configuration + * -- including all clocking and pin configuration -- was performed by the + * function imx8_lowsetup() earlier in the boot sequence. + */ + + /* Enable the console UART. The other UARTs will be initialized if and + * when they are first opened. + */ +#ifdef CONSOLE_DEV + CONSOLE_DEV.isconsole = true; + pl011_setup(&CONSOLE_DEV); +#endif +} + +/*************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug + * writes + * + ***************************************************************************/ + +int up_putc(int ch) +{ + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + up_lowputc('\r'); + } + + up_lowputc((uint8_t)ch); + return ch; +} + +/*************************************************************************** + * Name: arm64_serialinit + * + * Description: + * Register serial console and serial ports. This assumes + * that imx_earlyserialinit was called previously. + * + ***************************************************************************/ + +void arm64_serialinit(void) +{ + int ret; + + ret = uart_register("/dev/console", &CONSOLE_DEV); + if (ret < 0) + { + sinfo("error at register dev/console, ret =%d\n", ret); + } + + ret = uart_register("/dev/ttyS0", &TTYS0_DEV); + + if (ret < 0) + { + sinfo("error at register dev/ttyS0, ret =%d\n", ret); + } +} + +#else /* USE_SERIALDRIVER */ + +/*************************************************************************** + * Public Functions + ***************************************************************************/ + +int up_putc(int ch) +{ + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + up_lowputc('\r'); + } + + up_lowputc((uint8_t)ch); + return ch; +} + +#endif /* USE_SERIALDRIVER */ diff --git a/arch/arm64/src/fvp-v8r/serial_pl011.h b/arch/arm64/src/fvp-v8r/serial_pl011.h new file mode 100644 index 0000000000..73aee757bc --- /dev/null +++ b/arch/arm64/src/fvp-v8r/serial_pl011.h @@ -0,0 +1,82 @@ +/**************************************************************************** + * arch/arm64/src/fvp-v8r/serial_pl011.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_FVP_V8R_SERIAL_PL011_H +#define __ARCH_ARM64_SRC_FVP_V8R_SERIAL_PL011_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifdef CONFIG_FVP_UART_PL011 +#define CONFIG_UART0_BASE 0x9c090000 +#define CONFIG_UART0_IRQ (GIC_SPI_INT_BASE + 5) + +#define CONFIG_UART1_BASE 0x9c0a0000 +#define CONFIG_UART1_IRQ (GIC_SPI_INT_BASE + 6) + +#define CONFIG_UART2_BASE 0x9c0b0000 +#define CONFIG_UART2_IRQ (GIC_SPI_INT_BASE + 7) + +#define CONFIG_UART3_BASE 0x9c0c0000 +#define CONFIG_UART3_IRQ (GIC_SPI_INT_BASE + 8) + +#endif + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: fvp_earlyserialinit + * + * Description: + * Performs the low level UART initialization early in debug so that the + * serial console will be available during bootup. This must be called + * before arm_serialinit. + * + ****************************************************************************/ + +#ifdef USE_EARLYSERIALINIT +void fvp_earlyserialinit(void); +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM64_SRC_FVP_V8R_SERIAL_PL011_H */ diff --git a/arch/arm64/src/qemu/qemu_boot.c b/arch/arm64/src/qemu/qemu_boot.c index f2b0873988..a84e1b9803 100644 --- a/arch/arm64/src/qemu/qemu_boot.c +++ b/arch/arm64/src/qemu/qemu_boot.c @@ -49,7 +49,7 @@ * Private Data ****************************************************************************/ -static const struct arm_mmu_region mmu_regions[] = +static const struct arm_mmu_region g_mmu_regions[] = { MMU_REGION_FLAT_ENTRY("DEVICE_REGION", CONFIG_DEVICEIO_BASEADDR, CONFIG_DEVICEIO_SIZE, @@ -60,10 +60,10 @@ static const struct arm_mmu_region mmu_regions[] = MT_NORMAL | MT_RW | MT_SECURE), }; -const struct arm_mmu_config mmu_config = +const struct arm_mmu_config g_mmu_config = { - .num_regions = nitems(mmu_regions), - .mmu_regions = mmu_regions, + .num_regions = nitems(g_mmu_regions), + .mmu_regions = g_mmu_regions, }; /**************************************************************************** @@ -122,6 +122,7 @@ uint64_t arm64_get_mpid(int cpu) } #endif /* CONFIG_SMP */ + /**************************************************************************** * Name: arm64_el_init * diff --git a/boards/Kconfig b/boards/Kconfig index 76e31113fa..d35e86bd7d 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -1792,6 +1792,14 @@ config ARCH_BOARD_PINEPHONE This options selects support for NuttX on PINE64 PinePhone based on Allwinner A64 SoC with ARM Cortex-A53. +config ARCH_BOARD_FVP_ARMV8R + bool "FVP ARM-v8r CPUs board" + depends on ARCH_CHIP_FVP_ARMV8R + select ARCH_HAVE_IRQBUTTONS + ---help--- + This options selects support for NuttX on the Armv8-R AEM FVP + configure board with ARM Cortex-R82. + config ARCH_BOARD_SAMA5D2_XULT bool "Atmel SAMA5D2 Xplained Ultra development board" depends on ARCH_CHIP_ATSAMA5D27 @@ -2900,6 +2908,7 @@ config ARCH_BOARD default "sabre-6quad" if ARCH_BOARD_SABRE_6QUAD default "qemu-armv8a" if ARCH_BOARD_QEMU_ARMV8A default "pinephone" if ARCH_BOARD_PINEPHONE + default "fvp-armv8r" if ARCH_BOARD_FVP_ARMV8R default "sama5d2-xult" if ARCH_BOARD_SAMA5D2_XULT default "giant-board" if ARCH_BOARD_GIANT_BOARD default "jupiter-nano" if ARCH_BOARD_JUPITER_NANO @@ -3095,6 +3104,9 @@ endif if ARCH_BOARD_PINEPHONE source "boards/arm64/a64/pinephone/Kconfig" endif +if ARCH_BOARD_FVP_ARMV8R +source "boards/arm64/fvp-v8r/fvp-armv8r/Kconfig" +endif if ARCH_BOARD_IMXRT1020_EVK source "boards/arm/imxrt/imxrt1020-evk/Kconfig" endif diff --git a/boards/arm64/fvp-v8r/fvp-armv8r/Kconfig b/boards/arm64/fvp-v8r/fvp-armv8r/Kconfig new file mode 100644 index 0000000000..9debbeb247 --- /dev/null +++ b/boards/arm64/fvp-v8r/fvp-armv8r/Kconfig @@ -0,0 +1,7 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_BOARD_FVP_ARMV8R +endif diff --git a/boards/arm64/fvp-v8r/fvp-armv8r/README.txt b/boards/arm64/fvp-v8r/fvp-armv8r/README.txt new file mode 100644 index 0000000000..421256e853 --- /dev/null +++ b/boards/arm64/fvp-v8r/fvp-armv8r/README.txt @@ -0,0 +1,96 @@ +README.txt +========== + +This board configuration will use FVP_BaseR_AEMv8R to emulate +generic ARM64v8-R (Cotex-R82) series hardware platform and +provides support for these devices: + + - GICv3 interrupt controllers for ARMv8-r + - PL011 UART controller(FVP) + +Contents +======== + - Getting Started + - Status + - Platform Features + - References + +Getting Started +=============== + +1. Compile Toolchain + The FVP platform using same Compiler like qemu, read the following + file for How to get the Tool: + https://github.com/apache/nuttx/tree/master/boards/arm64/qemu/qemu-armv8a + +Note: +1. My host environment is Ubuntu 22.04.1 LTS, Ubuntu 18.04 will work too +2. The newest GNU toolchain is 12.2, available from: + https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads + + +2. Getting Armv8-R AEM FVP + The Armv8-R AEM FVP is a free of charge Armv8-R Fixed Virtual Platform. + It supports the latest Armv8-R feature set. we can get it from: + https://developer.arm.com/downloads/-/arm-ecosystem-models + + Please select to download Armv8-R AEM FVP product, extract the tool package + the FVP tool is locate at: + AEMv8R_FVP/AEMv8R_base_pkg/models/Linux64_GCC-9.3/FVP_BaseR_AEMv8R + +3. Configuring and building + 3.1 Single Core + Configuring NuttX and compile: + $ ./tools/configure.sh -l fvp-armv8r:nsh + $ make + + 3.2 SMP + Configuring NuttX and compile: + $ ./tools/configure.sh -l fvp-armv8r:nsh_smp + $ make + +3. Running + Single Core + $ AEMv8R_FVP/AEMv8R_base_pkg/models/Linux64_GCC-9.3/FVP_BaseR_AEMv8R \ + -f boards/arm64/fvp-v8r/fvp-armv8r/scripts/fvp_cfg.txt \ + -a ./nuttx + SMP + $ AEMv8R_FVP/AEMv8R_base_pkg/models/Linux64_GCC-9.3/FVP_BaseR_AEMv8R \ + -f boards/arm64/fvp-v8r/fvp-armv8r/scripts/fvp_cfg_smp.txt \ + -a ./nuttx + +Status +====== + +2023-2-18: +1. Release the frist version for ARMv8-R, Single Core and SMP is supported + OS test is passed. + +Platform Features +================= + +The following hardware features are supported: ++--------------+------------+----------------------+ +| Interface | Controller | Driver/Component | ++==============+============+======================+ +| GICv3 | on-chip | interrupt controller | ++--------------+------------+----------------------+ +| PL011 UART | on-chip | serial port | ++--------------+------------+----------------------+ +| ARM TIMER | on-chip | system clock | ++--------------+------------+----------------------+ + +References +=========== + +1. (ID050815) ARM® Cortex®-A Series - Programmer’s Guide for ARMv8-A +2. (ID020222) Arm® Architecture Reference Manual - for A profile architecture +3. (ARM062-948681440-3280) Armv8-A Instruction Set Architecture +4. AArch64 Exception and Interrupt Handling +5. AArch64 Programmer's Guides Generic Timer +6. Arm Generic Interrupt Controller v3 and v4 Overview +7. Arm® Generic Interrupt Controller Architecture Specification GIC architecture version 3 and version 4 +8. (DEN0022D.b) Arm Power State Coordination Interface Platform Design Document +9. Arm® Architecture Reference Manual Supplement, Armv8, for R-profile AArch64 architecture, + ARM DDI 0600B.a (ID062922) +10.Arm® Cortex®-R82 Processor Technical Reference Manual, Revision: r0p2 \ No newline at end of file diff --git a/boards/arm64/fvp-v8r/fvp-armv8r/configs/nsh/defconfig b/boards/arm64/fvp-v8r/fvp-armv8r/configs/nsh/defconfig new file mode 100644 index 0000000000..545d02c7ea --- /dev/null +++ b/boards/arm64/fvp-v8r/fvp-armv8r/configs/nsh/defconfig @@ -0,0 +1,66 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +CONFIG_ARCH="arm64" +CONFIG_ARCH_ARM64=y +CONFIG_ARCH_BOARD="fvp-armv8r" +CONFIG_ARCH_BOARD_FVP_ARMV8R=y +CONFIG_ARCH_CHIP="fvp-v8r" +CONFIG_ARCH_CHIP_FVP_ARMV8R=y +CONFIG_ARCH_CHIP_FVP_R82=y +CONFIG_ARCH_INTERRUPTSTACK=4096 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ERROR=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_SCHED=y +CONFIG_DEBUG_SCHED_ERROR=y +CONFIG_DEBUG_SCHED_INFO=y +CONFIG_DEBUG_SCHED_WARN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_WARN=y +CONFIG_DEFAULT_TASK_STACKSIZE=8192 +CONFIG_DEV_ZERO=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXPERIMENTAL=y +CONFIG_FS_PROCFS=y +CONFIG_FS_ROMFS=y +CONFIG_FVP_UART_PL011=y +CONFIG_IDLETHREAD_STACKSIZE=8192 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NSH_ROMFSETC=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PTHREAD_STACK_MIN=8192 +CONFIG_RAMLOG=y +CONFIG_RAM_SIZE=134217728 +CONFIG_RAM_START=0x0000000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=192 +CONFIG_SPINLOCK=y +CONFIG_STACK_COLORATION=y +CONFIG_START_MONTH=3 +CONFIG_START_YEAR=2022 +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSLOG_PROCESSID=y +CONFIG_SYSLOG_PROCESS_NAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_SYSTEM=y +CONFIG_SYSTEM_TIME64=y +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_UART1_SERIAL_CONSOLE=y +CONFIG_USEC_PER_TICK=1000 diff --git a/boards/arm64/fvp-v8r/fvp-armv8r/configs/nsh_smp/defconfig b/boards/arm64/fvp-v8r/fvp-armv8r/configs/nsh_smp/defconfig new file mode 100644 index 0000000000..76651deb51 --- /dev/null +++ b/boards/arm64/fvp-v8r/fvp-armv8r/configs/nsh_smp/defconfig @@ -0,0 +1,69 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +CONFIG_ARCH="arm64" +CONFIG_ARCH_ARM64=y +CONFIG_ARCH_BOARD="fvp-armv8r" +CONFIG_ARCH_BOARD_FVP_ARMV8R=y +CONFIG_ARCH_CHIP="fvp-v8r" +CONFIG_ARCH_CHIP_FVP_ARMV8R=y +CONFIG_ARCH_CHIP_FVP_R82=y +CONFIG_ARCH_INTERRUPTSTACK=4096 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ERROR=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_SCHED=y +CONFIG_DEBUG_SCHED_ERROR=y +CONFIG_DEBUG_SCHED_INFO=y +CONFIG_DEBUG_SCHED_WARN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_WARN=y +CONFIG_DEFAULT_TASK_STACKSIZE=8192 +CONFIG_DEV_ZERO=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXPERIMENTAL=y +CONFIG_FS_PROCFS=y +CONFIG_FS_ROMFS=y +CONFIG_FVP_UART_PL011=y +CONFIG_IDLETHREAD_STACKSIZE=8192 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NSH_ROMFSETC=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PTHREAD_STACK_MIN=8192 +CONFIG_RAMLOG=y +CONFIG_RAM_SIZE=134217728 +CONFIG_RAM_START=0x0000000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=192 +CONFIG_SMP=y +CONFIG_STACK_COLORATION=y +CONFIG_START_MONTH=3 +CONFIG_START_YEAR=2022 +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSLOG_BUFFER=y +CONFIG_SYSLOG_PROCESSID=y +CONFIG_SYSLOG_PROCESS_NAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_SYSTEM=y +CONFIG_SYSTEM_TASKSET=y +CONFIG_SYSTEM_TIME64=y +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_TESTING_SMP=y +CONFIG_UART1_SERIAL_CONSOLE=y +CONFIG_USEC_PER_TICK=1000 diff --git a/boards/arm64/fvp-v8r/fvp-armv8r/include/board.h b/boards/arm64/fvp-v8r/fvp-armv8r/include/board.h new file mode 100644 index 0000000000..fe6e5b3665 --- /dev/null +++ b/boards/arm64/fvp-v8r/fvp-armv8r/include/board.h @@ -0,0 +1,34 @@ +/**************************************************************************** + * boards/arm64/fvp-v8r/fvp-armv8r/include/board.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM64_FVP_V8R_FVP_ARMV8R_INCLUDE_BOARD_H +#define __BOARDS_ARM64_FVP_V8R_FVP_ARMV8R_INCLUDE_BOARD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#endif /* __BOARDS_ARM64_FVP_V8R_FVP_ARMV8R_INCLUDE_BOARD_H */ diff --git a/boards/arm64/fvp-v8r/fvp-armv8r/include/board_memorymap.h b/boards/arm64/fvp-v8r/fvp-armv8r/include/board_memorymap.h new file mode 100644 index 0000000000..b1b108922d --- /dev/null +++ b/boards/arm64/fvp-v8r/fvp-armv8r/include/board_memorymap.h @@ -0,0 +1,59 @@ +/**************************************************************************** + * boards/arm64/fvp-v8r/fvp-armv8r/include/board_memorymap.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM64_FVP_V8R_FVP_ARMV8R_INCLUDE_BOARD_MEMORYMAP_H +#define __BOARDS_ARM64_FVP_V8R_FVP_ARMV8R_INCLUDE_BOARD_MEMORYMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_ARM64_VDK_ARMV8R_BASE_INCLUDE_BOARD_MEMORYMAP_H */ diff --git a/boards/arm64/fvp-v8r/fvp-armv8r/scripts/Make.defs b/boards/arm64/fvp-v8r/fvp-armv8r/scripts/Make.defs new file mode 100644 index 0000000000..4241585fde --- /dev/null +++ b/boards/arm64/fvp-v8r/fvp-armv8r/scripts/Make.defs @@ -0,0 +1,48 @@ +############################################################################ +# boards/arm64/fvp-v8r/fvp-armv8r/scripts/Make.defs +# +# 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. +# +############################################################################ + +include $(TOPDIR)/.config +include $(TOPDIR)/tools/Config.mk +include $(TOPDIR)/arch/arm64/src/Toolchain.defs + +LDSCRIPT = dramboot.ld + +ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) + +CFLAGS := $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe +CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) +CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe +CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) +CPPFLAGS := $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) +AFLAGS := $(CFLAGS) -D__ASSEMBLY__ + +# NXFLAT module definitions + +NXFLATLDFLAGS1 = -r -d -warn-common +NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)$(DELIM)binfmt$(DELIM)libnxflat$(DELIM)gnu-nxflat-pcrel.ld -no-check-sections +LDNXFLATFLAGS = -e main -s 2048 + +# ELF module definitions + +CELFFLAGS = $(CFLAGS) -mlong-calls # --target1-abs +CXXELFFLAGS = $(CXXFLAGS) -mlong-calls # --target1-abs + +LDELFFLAGS = -r -e main +LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/binfmt/libelf/gnu-elf.ld) diff --git a/boards/arm64/fvp-v8r/fvp-armv8r/scripts/dramboot.ld b/boards/arm64/fvp-v8r/fvp-armv8r/scripts/dramboot.ld new file mode 100644 index 0000000000..397000b4b4 --- /dev/null +++ b/boards/arm64/fvp-v8r/fvp-armv8r/scripts/dramboot.ld @@ -0,0 +1,126 @@ +/**************************************************************************** + * boards/arm64/fvp-v8r/fvp-armv8r/scripts/dramboot.ld + * + * 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. + * + ****************************************************************************/ + +OUTPUT_ARCH(aarch64) + +ENTRY(__start) + +PHDRS +{ + text PT_LOAD ; +} + +SECTIONS +{ + . = 0x00000000; /* load address */ + _start = .; + .text : { + _stext = .; /* Text section */ + *(.text) + *(.text.cold) + *(.text.unlikely) + *(.fixup) + *(.gnu.warning) + } :text = 0x9090 + + . = ALIGN(4096); + + .init_section : { + _sinit = ABSOLUTE(.); + KEEP(*(.init_array .init_array.*)) + _einit = ABSOLUTE(.); + } + + . = ALIGN(4096); + + .vector : { + _vector_start = .; + KEEP(*(.exc_vector_table)) + KEEP(*(".exc_vector_table.*")) + KEEP(*(.vectors)) + _vector_end = .; + } :text + . = ALIGN(4096); + _etext = .; /* End_1 of .text */ + _sztext = _etext - _stext; + + . = ALIGN(4096); + .rodata : { + _srodata = .; /* Read-only data */ + *(.rodata) + *(.rodata.*) + *(.data.rel.ro) + *(.data.rel.ro.*) + } :text + . = ALIGN(4096); + _erodata = .; /* End of read-only data */ + _szrodata = _erodata - _srodata; + _eronly = .; /* End of read-only data */ + + . = ALIGN(4096); + .data : { /* Data */ + _sdata = .; + *(.data.page_aligned) + *(.data) + . = ALIGN(8); + *(.data.rel) + *(.data.rel.*) + CONSTRUCTORS + } :text + _edata = .; /* End+1 of .data */ + + .bss : { /* BSS */ + _sbss = .; + *(.bss) + . = ALIGN(1 << 3); + } :text + . = ALIGN(4096); + _ebss = .; + _szbss = _ebss - _sbss; + + .initstack : { /* INIT STACK */ + _s_initstack = .; + *(.initstack) + . = ALIGN(16); + } :text + . = ALIGN(4096); + _e_initstack = . ; + g_idle_topstack = . ; + + _szdata = _e_initstack - _sdata; + + /* Sections to be discarded */ + /DISCARD/ : { + *(.exit.text) + *(.exit.data) + *(.exitcall.exit) + *(.eh_frame) + } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } +} + diff --git a/boards/arm64/fvp-v8r/fvp-armv8r/scripts/fvp_cfg.txt b/boards/arm64/fvp-v8r/fvp-armv8r/scripts/fvp_cfg.txt new file mode 100644 index 0000000000..5c60eaa3cb --- /dev/null +++ b/boards/arm64/fvp-v8r/fvp-armv8r/scripts/fvp_cfg.txt @@ -0,0 +1,25 @@ +cluster0.has_aarch64=1 +cluster0.VMSA_supported=0 +cluster0.NUM_CORES=1 +cluster0.gicv3.cpuintf-mmap-access-level=2 +cluster0.gicv3.SRE-enable-action-on-mmap=2 +cluster0.gicv3.SRE-EL2-enable-RAO=1 +cluster0.gicv3.extended-interrupt-range-support=1 +gic_distributor.GICD_CTLR-DS-1-means-secure-only=1 +gic_distributor.has-two-security-states=0 +bp.refcounter.non_arch_start_at_default=1 +bp.pl011_uart0.out_file=- +bp.pl011_uart0.unbuffered_output=1 +bp.terminal_0.start_telnet=0 +bp.pl011_uart1.out_file=- +bp.pl011_uart1.unbuffered_output=1 +bp.terminal_1.start_telnet=0 +bp.pl011_uart2.out_file=- +bp.pl011_uart2.unbuffered_output=1 +bp.terminal_2.start_telnet=0 +bp.pl011_uart3.out_file=- +bp.pl011_uart3.unbuffered_output=1 +bp.terminal_3.start_telnet=0 +bp.vis.disable_visualisation=1 +bp.vis.rate_limit-enable=0 +cache_state_modelled=0 diff --git a/boards/arm64/fvp-v8r/fvp-armv8r/scripts/fvp_cfg_smp.txt b/boards/arm64/fvp-v8r/fvp-armv8r/scripts/fvp_cfg_smp.txt new file mode 100644 index 0000000000..3e3b1935e1 --- /dev/null +++ b/boards/arm64/fvp-v8r/fvp-armv8r/scripts/fvp_cfg_smp.txt @@ -0,0 +1,25 @@ +cluster0.has_aarch64=1 +cluster0.VMSA_supported=0 +cluster0.NUM_CORES=4 +cluster0.gicv3.cpuintf-mmap-access-level=2 +cluster0.gicv3.SRE-enable-action-on-mmap=2 +cluster0.gicv3.SRE-EL2-enable-RAO=1 +cluster0.gicv3.extended-interrupt-range-support=1 +gic_distributor.GICD_CTLR-DS-1-means-secure-only=1 +gic_distributor.has-two-security-states=0 +bp.refcounter.non_arch_start_at_default=1 +bp.pl011_uart0.out_file=- +bp.pl011_uart0.unbuffered_output=1 +bp.terminal_0.start_telnet=0 +bp.pl011_uart1.out_file=- +bp.pl011_uart1.unbuffered_output=1 +bp.terminal_1.start_telnet=0 +bp.pl011_uart2.out_file=- +bp.pl011_uart2.unbuffered_output=1 +bp.terminal_2.start_telnet=0 +bp.pl011_uart3.out_file=- +bp.pl011_uart3.unbuffered_output=1 +bp.terminal_3.start_telnet=0 +bp.vis.disable_visualisation=1 +bp.vis.rate_limit-enable=0 +cache_state_modelled=0 diff --git a/boards/arm64/fvp-v8r/fvp-armv8r/src/Makefile b/boards/arm64/fvp-v8r/fvp-armv8r/src/Makefile new file mode 100644 index 0000000000..376cec7da2 --- /dev/null +++ b/boards/arm64/fvp-v8r/fvp-armv8r/src/Makefile @@ -0,0 +1,29 @@ +############################################################################ +# boards/arm64/fvp-v8r/fvp-armv8r/src/Makefile +# +# 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. +# +############################################################################ + +include $(TOPDIR)/Make.defs + +CSRCS = fvp_boardinit.c fvp_bringup.c + +ifeq ($(CONFIG_BOARDCTL),y) +CSRCS += fvp_appinit.c +endif + +include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm64/fvp-v8r/fvp-armv8r/src/fvp-armv8r.h b/boards/arm64/fvp-v8r/fvp-armv8r/src/fvp-armv8r.h new file mode 100644 index 0000000000..0605d05b28 --- /dev/null +++ b/boards/arm64/fvp-v8r/fvp-armv8r/src/fvp-armv8r.h @@ -0,0 +1,59 @@ +/**************************************************************************** + * boards/arm64/fvp-v8r/fvp-armv8r/src/fvp-armv8r.h + * + * 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. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM64_VDK_ARMV8R_BASE_SRC_VDK_ARMV8R_H__ +#define __BOARDS_ARM64_VDK_ARMV8R_BASE_SRC_VDK_ARMV8R_H__ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Functions Definitions + ****************************************************************************/ + +/**************************************************************************** + * Name: vdk_bringup + * + * Description: + * Bring up board features + * + ****************************************************************************/ + +#if defined(CONFIG_BOARDCTL) || defined(CONFIG_BOARD_LATE_INITIALIZE) +int fvp_bringup(void); +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_ARM64_VDK_ARMV8R_BASE_SRC_VDK_ARMV8R_H__ */ diff --git a/boards/arm64/fvp-v8r/fvp-armv8r/src/fvp_appinit.c b/boards/arm64/fvp-v8r/fvp-armv8r/src/fvp_appinit.c new file mode 100644 index 0000000000..7a9be1b6c5 --- /dev/null +++ b/boards/arm64/fvp-v8r/fvp-armv8r/src/fvp_appinit.c @@ -0,0 +1,73 @@ +/**************************************************************************** + * boards/arm64/fvp-v8r/fvp-armv8r/src/fvp_appinit.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 +#include +#include +#include "fvp-armv8r.h" + +#ifdef CONFIG_BOARDCTL + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_app_initialize + * + * Description: + * Perform application specific initialization. This function is never + * called directly from application code, but only indirectly via the + * (non-standard) boardctl() interface using the command BOARDIOC_INIT. + * + * Input Parameters: + * arg - The boardctl() argument is passed to the board_app_initialize() + * implementation without modification. The argument has no + * meaning to NuttX; the meaning of the argument is a contract + * between the board-specific initialization logic and the + * matching application logic. The value could be such things as a + * mode enumeration value, a set of DIP switch switch settings, a + * pointer to configuration data read from a file or serial FLASH, + * or whatever you would like to do with it. Every implementation + * should accept zero/NULL as a default configuration. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + +int board_app_initialize(uintptr_t arg) +{ + UNUSED(arg); +#ifndef CONFIG_BOARD_LATE_INITIALIZE + /* Perform board initialization */ + + return fvp_bringup(); +#else + return OK; +#endif +} + +#endif /* CONFIG_BOARDCTL */ diff --git a/boards/arm64/fvp-v8r/fvp-armv8r/src/fvp_boardinit.c b/boards/arm64/fvp-v8r/fvp-armv8r/src/fvp_boardinit.c new file mode 100644 index 0000000000..470d7648da --- /dev/null +++ b/boards/arm64/fvp-v8r/fvp-armv8r/src/fvp_boardinit.c @@ -0,0 +1,113 @@ +/**************************************************************************** + * boards/arm64/fvp-v8r/fvp-armv8r/src/fvp_boardinit.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 +#include +#include +#include "fvp-armv8r.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fvp_memory_initialize + * + * Description: + * All vdk architectures must provide the following entry point. This + * entry point is called early in the initialization before memory has + * been configured. This board-specific function is responsible for + * configuring any on-board memories. + * + * Logic in vdk_memory_initialize must be careful to avoid using any + * global variables because those will be uninitialized at the time this + * function is called. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void fvp_memory_initialize(void) +{ + /* SDRAM was initialized by a bootloader in the supported configurations. */ +} + +/**************************************************************************** + * Name: vdk_board_initialize + * + * Description: + * All vdk architectures must provide the following entry point. This + * entry point is called in the initialization phase -- after + * vdk_memory_initialize and after all memory has been configured and + * mapped but before any devices have been initialized. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void fvp_board_initialize(void) +{ +#ifdef CONFIG_ARCH_LEDS + /* Configure on-board LEDs if LED support has been selected. */ + +#endif +} + +/**************************************************************************** + * Name: board_late_initialize + * + * Description: + * If CONFIG_BOARD_LATE_INITIALIZE is selected, then an additional + * initialization call will be performed in the boot-up sequence to a + * function called board_late_initialize(). board_late_initialize() will be + * called immediately after up_intitialize() is called and just before the + * initial application is started. This additional initialization phase + * may be used, for example, to initialize board-specific device drivers. + * + ****************************************************************************/ + +#ifdef CONFIG_BOARD_LATE_INITIALIZE +void board_late_initialize(void) +{ + /* Perform board initialization */ + + fvp_bringup(); +} +#endif /* CONFIG_BOARD_LATE_INITIALIZE */ diff --git a/boards/arm64/fvp-v8r/fvp-armv8r/src/fvp_bringup.c b/boards/arm64/fvp-v8r/fvp-armv8r/src/fvp_bringup.c new file mode 100644 index 0000000000..f4585b9308 --- /dev/null +++ b/boards/arm64/fvp-v8r/fvp-armv8r/src/fvp_bringup.c @@ -0,0 +1,60 @@ +/**************************************************************************** + * boards/arm64/fvp-v8r/fvp-armv8r/src/fvp_bringup.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 +#include +#include +#include + +#include "fvp-armv8r.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fvp_bringup + * + * Description: + * Bring up board features + * + ****************************************************************************/ + +int fvp_bringup(void) +{ + int ret; + +#ifdef CONFIG_FS_PROCFS + /* Mount the procfs file system */ + + ret = nx_mount(NULL, "/proc", "procfs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount procfs at /proc: %d\n", ret); + } +#endif + + UNUSED(ret); + return OK; +}