summaryrefslogtreecommitdiff
path: root/board/emulation/qemu-arm/qemu-arm.c
diff options
context:
space:
mode:
Diffstat (limited to 'board/emulation/qemu-arm/qemu-arm.c')
-rw-r--r--board/emulation/qemu-arm/qemu-arm.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/board/emulation/qemu-arm/qemu-arm.c b/board/emulation/qemu-arm/qemu-arm.c
new file mode 100644
index 00000000000..6095cb02b23
--- /dev/null
+++ b/board/emulation/qemu-arm/qemu-arm.c
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2017 Tuomas Tynkkynen
+ */
+
+#include <config.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <efi.h>
+#include <efi_loader.h>
+#include <fdtdec.h>
+#include <init.h>
+#include <log.h>
+#include <usb.h>
+#include <virtio_types.h>
+#include <virtio.h>
+
+#include <linux/kernel.h>
+#include <linux/sizes.h>
+
+/* GUIDs for capsule updatable firmware images */
+#define QEMU_ARM_UBOOT_IMAGE_GUID \
+ EFI_GUID(0xf885b085, 0x99f8, 0x45af, 0x84, 0x7d, \
+ 0xd5, 0x14, 0x10, 0x7a, 0x4a, 0x2c)
+
+#define QEMU_ARM64_UBOOT_IMAGE_GUID \
+ EFI_GUID(0x058b7d83, 0x50d5, 0x4c47, 0xa1, 0x95, \
+ 0x60, 0xd8, 0x6a, 0xd3, 0x41, 0xc4)
+
+#ifdef CONFIG_ARM64
+#include <asm/armv8/mmu.h>
+
+#if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)
+struct efi_fw_image fw_images[] = {
+#if defined(CONFIG_TARGET_QEMU_ARM_32BIT)
+ {
+ .image_type_id = QEMU_ARM_UBOOT_IMAGE_GUID,
+ .fw_name = u"Qemu-Arm-UBOOT",
+ .image_index = 1,
+ },
+#elif defined(CONFIG_TARGET_QEMU_ARM_64BIT)
+ {
+ .image_type_id = QEMU_ARM64_UBOOT_IMAGE_GUID,
+ .fw_name = u"Qemu-Arm-UBOOT",
+ .image_index = 1,
+ },
+#endif
+};
+
+struct efi_capsule_update_info update_info = {
+ .num_images = ARRAY_SIZE(fw_images)
+ .images = fw_images,
+};
+
+#endif /* EFI_HAVE_CAPSULE_SUPPORT */
+
+static struct mm_region qemu_arm64_mem_map[] = {
+ {
+ /* Flash */
+ .virt = 0x00000000UL,
+ .phys = 0x00000000UL,
+ .size = 0x08000000UL,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE
+ }, {
+ /* Lowmem peripherals */
+ .virt = 0x08000000UL,
+ .phys = 0x08000000UL,
+ .size = 0x38000000,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+ PTE_BLOCK_NON_SHARE |
+ PTE_BLOCK_PXN | PTE_BLOCK_UXN
+ }, {
+ /* RAM */
+ .virt = 0x40000000UL,
+ .phys = 0x40000000UL,
+ .size = 255UL * SZ_1G,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE
+ }, {
+ /* Highmem PCI-E ECAM memory area */
+ .virt = 0x4010000000ULL,
+ .phys = 0x4010000000ULL,
+ .size = 0x10000000,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+ PTE_BLOCK_NON_SHARE |
+ PTE_BLOCK_PXN | PTE_BLOCK_UXN
+ }, {
+ /* Highmem PCI-E MMIO memory area */
+ .virt = 0x8000000000ULL,
+ .phys = 0x8000000000ULL,
+ .size = 0x8000000000ULL,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+ PTE_BLOCK_NON_SHARE |
+ PTE_BLOCK_PXN | PTE_BLOCK_UXN
+ }, {
+ /* List terminator */
+ 0,
+ }
+};
+
+struct mm_region *mem_map = qemu_arm64_mem_map;
+#endif
+
+int board_init(void)
+{
+ return 0;
+}
+
+int board_late_init(void)
+{
+ /*
+ * Make sure virtio bus is enumerated so that peripherals
+ * on the virtio bus can be discovered by their drivers
+ */
+ virtio_init();
+
+ /* start usb so that usb keyboard can be used as input device */
+ if (CONFIG_IS_ENABLED(USB_KEYBOARD))
+ usb_init();
+
+ return 0;
+}
+
+int dram_init(void)
+{
+ if (fdtdec_setup_mem_size_base() != 0)
+ return -EINVAL;
+
+ /*
+ * When LPAE is enabled (ARMv7),
+ * 1:1 mapping is created using 2 MB blocks.
+ *
+ * In case amount of memory provided to QEMU
+ * is not multiple of 2 MB, round down the amount
+ * of available memory to avoid hang during MMU
+ * initialization.
+ */
+ if (CONFIG_IS_ENABLED(ARMV7_LPAE))
+ gd->ram_size -= (gd->ram_size % 0x200000);
+
+ return 0;
+}
+
+int dram_init_banksize(void)
+{
+ fdtdec_setup_memory_banksize();
+
+ return 0;
+}
+
+void *board_fdt_blob_setup(int *err)
+{
+ *err = 0;
+ /* QEMU loads a generated DTB for us at the start of RAM. */
+ return (void *)CFG_SYS_SDRAM_BASE;
+}
+
+void enable_caches(void)
+{
+ icache_enable();
+ dcache_enable();
+}
+
+#ifdef CONFIG_ARM64
+#define __W "w"
+#else
+#define __W
+#endif
+
+u8 flash_read8(void *addr)
+{
+ u8 ret;
+
+ asm("ldrb %" __W "0, %1" : "=r"(ret) : "m"(*(u8 *)addr));
+ return ret;
+}
+
+u16 flash_read16(void *addr)
+{
+ u16 ret;
+
+ asm("ldrh %" __W "0, %1" : "=r"(ret) : "m"(*(u16 *)addr));
+ return ret;
+}
+
+u32 flash_read32(void *addr)
+{
+ u32 ret;
+
+ asm("ldr %" __W "0, %1" : "=r"(ret) : "m"(*(u32 *)addr));
+ return ret;
+}
+
+void flash_write8(u8 value, void *addr)
+{
+ asm("strb %" __W "1, %0" : "=m"(*(u8 *)addr) : "r"(value));
+}
+
+void flash_write16(u16 value, void *addr)
+{
+ asm("strh %" __W "1, %0" : "=m"(*(u16 *)addr) : "r"(value));
+}
+
+void flash_write32(u32 value, void *addr)
+{
+ asm("str %" __W "1, %0" : "=m"(*(u32 *)addr) : "r"(value));
+}