| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #define HAS_DEVICE_TREE 1 |
| #define USE_DEVICE_TREE_CPU_COUNT 1 |
| #define USE_DEVICE_TREE_GIC_VERSION 1 |
| |
| #define MAX_CPU_COUNT 100 |
| static size_t cpu_count = 0; |
| |
| static const zbi_mem_range_t mem_config[] = { |
| { |
| .type = ZBI_MEM_RANGE_RAM, |
| .paddr = 0x40000000, |
| .length = 0x08000000, // assume 512MB, FDT will provide the real number |
| }, |
| { |
| .type = ZBI_MEM_RANGE_PERIPHERAL, |
| .paddr = 0, |
| .length = 0x40000000, |
| }, |
| }; |
| |
| static const dcfg_simple_t uart_driver = { |
| .mmio_phys = 0x09000000, |
| .irq = 33, |
| }; |
| |
| static const dcfg_arm_gicv3_driver_t gicv3_driver = { |
| .mmio_phys = 0x08000000, |
| .gicd_offset = 0x00000, |
| .gicr_offset = 0xa0000, |
| .gicr_stride = 0x20000, |
| .ipi_base = 12, |
| .optional = true, |
| }; |
| |
| static const dcfg_arm_gicv2_driver_t gicv2_driver = { |
| .mmio_phys = 0x08000000, |
| .msi_frame_phys = 0x08020000, |
| .gicd_offset = 0x00000, |
| .gicc_offset = 0x10000, |
| .ipi_base = 12, |
| .optional = true, |
| .use_msi = true, |
| }; |
| |
| static const dcfg_arm_psci_driver_t psci_driver = { |
| .use_hvc = true, |
| }; |
| |
| static const dcfg_arm_generic_timer_driver_t timer_driver = { |
| .irq_phys = 30, |
| .irq_virt = 27, |
| }; |
| |
| static const zbi_platform_id_t platform_id = { |
| .vid = PDEV_VID_QEMU, |
| .pid = PDEV_PID_QEMU, |
| .board_name = "qemu", |
| }; |
| |
| static int saved_gic_version = -1; |
| |
| static void set_gic_version(int gic_version) { |
| saved_gic_version = gic_version; |
| } |
| |
| static void add_cpu_topology(zbi_header_t* zbi) { |
| zbi_topology_node_t nodes[MAX_CPU_COUNT]; |
| |
| for (size_t index = 0; index < cpu_count; index++) { |
| nodes[index] = (zbi_topology_node_t){ |
| .entity_type = ZBI_TOPOLOGY_ENTITY_PROCESSOR, |
| .parent_index = ZBI_TOPOLOGY_NO_PARENT, |
| .entity = { |
| .processor = { |
| .logical_ids = {index}, |
| .logical_id_count = 1, |
| .flags = ZBI_TOPOLOGY_PROCESSOR_PRIMARY, |
| .architecture = ZBI_TOPOLOGY_ARCH_ARM, |
| .architecture_info = { |
| .arm = { |
| .cpu_id = index, |
| .gic_id = index, |
| }}}}}; |
| } |
| |
| append_boot_item(zbi, ZBI_TYPE_CPU_TOPOLOGY, |
| sizeof(zbi_topology_node_t), // Extra |
| &nodes, sizeof(zbi_topology_node_t) * cpu_count); |
| } |
| |
| static void append_board_boot_item(zbi_header_t* bootdata) { |
| add_cpu_topology(bootdata); |
| |
| // add memory configuration |
| append_boot_item(bootdata, ZBI_TYPE_MEM_CONFIG, 0, &mem_config, |
| sizeof(zbi_mem_range_t) * countof(mem_config)); |
| |
| // add kernel drivers |
| append_boot_item(bootdata, ZBI_TYPE_KERNEL_DRIVER, KDRV_PL011_UART, &uart_driver, |
| sizeof(uart_driver)); |
| |
| // append the gic information for either the specific gic version we detected from the |
| // device tree, or both if we didn't detect either (-1) |
| if (saved_gic_version < 0 || saved_gic_version == 3) { |
| append_boot_item(bootdata, ZBI_TYPE_KERNEL_DRIVER, KDRV_ARM_GIC_V3, &gicv3_driver, |
| sizeof(gicv3_driver)); |
| } |
| if (saved_gic_version < 0 || saved_gic_version == 2) { |
| append_boot_item(bootdata, ZBI_TYPE_KERNEL_DRIVER, KDRV_ARM_GIC_V2, &gicv2_driver, |
| sizeof(gicv2_driver)); |
| } |
| |
| append_boot_item(bootdata, ZBI_TYPE_KERNEL_DRIVER, KDRV_ARM_PSCI, &psci_driver, |
| sizeof(psci_driver)); |
| append_boot_item(bootdata, ZBI_TYPE_KERNEL_DRIVER, KDRV_ARM_GENERIC_TIMER, &timer_driver, |
| sizeof(timer_driver)); |
| |
| // add platform ID |
| append_boot_item(bootdata, ZBI_TYPE_PLATFORM_ID, 0, &platform_id, sizeof(platform_id)); |
| } |
| |
| static void set_cpu_count(uint32_t new_count) { |
| if (new_count > 0) { |
| cpu_count = new_count; |
| } |
| } |