arm: qemu: override flash accessors to use virtualizable instructions
[platform/kernel/u-boot.git] / board / emulation / qemu-arm / qemu-arm.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2017 Tuomas Tynkkynen
4  */
5
6 #include <common.h>
7 #include <cpu_func.h>
8 #include <dm.h>
9 #include <fdtdec.h>
10 #include <init.h>
11 #include <log.h>
12 #include <virtio_types.h>
13 #include <virtio.h>
14
15 #ifdef CONFIG_ARM64
16 #include <asm/armv8/mmu.h>
17
18 static struct mm_region qemu_arm64_mem_map[] = {
19         {
20                 /* Flash */
21                 .virt = 0x00000000UL,
22                 .phys = 0x00000000UL,
23                 .size = 0x08000000UL,
24                 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
25                          PTE_BLOCK_INNER_SHARE
26         }, {
27                 /* Lowmem peripherals */
28                 .virt = 0x08000000UL,
29                 .phys = 0x08000000UL,
30                 .size = 0x38000000,
31                 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
32                          PTE_BLOCK_NON_SHARE |
33                          PTE_BLOCK_PXN | PTE_BLOCK_UXN
34         }, {
35                 /* RAM */
36                 .virt = 0x40000000UL,
37                 .phys = 0x40000000UL,
38                 .size = 255UL * SZ_1G,
39                 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
40                          PTE_BLOCK_INNER_SHARE
41         }, {
42                 /* Highmem PCI-E ECAM memory area */
43                 .virt = 0x4010000000ULL,
44                 .phys = 0x4010000000ULL,
45                 .size = 0x10000000,
46                 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
47                          PTE_BLOCK_NON_SHARE |
48                          PTE_BLOCK_PXN | PTE_BLOCK_UXN
49         }, {
50                 /* Highmem PCI-E MMIO memory area */
51                 .virt = 0x8000000000ULL,
52                 .phys = 0x8000000000ULL,
53                 .size = 0x8000000000ULL,
54                 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
55                          PTE_BLOCK_NON_SHARE |
56                          PTE_BLOCK_PXN | PTE_BLOCK_UXN
57         }, {
58                 /* List terminator */
59                 0,
60         }
61 };
62
63 struct mm_region *mem_map = qemu_arm64_mem_map;
64 #endif
65
66 int board_init(void)
67 {
68         /*
69          * Make sure virtio bus is enumerated so that peripherals
70          * on the virtio bus can be discovered by their drivers
71          */
72         virtio_init();
73
74         return 0;
75 }
76
77 int dram_init(void)
78 {
79         if (fdtdec_setup_mem_size_base() != 0)
80                 return -EINVAL;
81
82         return 0;
83 }
84
85 int dram_init_banksize(void)
86 {
87         fdtdec_setup_memory_banksize();
88
89         return 0;
90 }
91
92 void *board_fdt_blob_setup(void)
93 {
94         /* QEMU loads a generated DTB for us at the start of RAM. */
95         return (void *)CONFIG_SYS_SDRAM_BASE;
96 }
97
98 void enable_caches(void)
99 {
100          icache_enable();
101          dcache_enable();
102 }
103
104 #if defined(CONFIG_EFI_RNG_PROTOCOL)
105 #include <efi_loader.h>
106 #include <efi_rng.h>
107
108 #include <dm/device-internal.h>
109
110 efi_status_t platform_get_rng_device(struct udevice **dev)
111 {
112         int ret;
113         efi_status_t status = EFI_DEVICE_ERROR;
114         struct udevice *bus, *devp;
115
116         for (uclass_first_device(UCLASS_VIRTIO, &bus); bus;
117              uclass_next_device(&bus)) {
118                 for (device_find_first_child(bus, &devp); devp;
119                      device_find_next_child(&devp)) {
120                         if (device_get_uclass_id(devp) == UCLASS_RNG) {
121                                 *dev = devp;
122                                 status = EFI_SUCCESS;
123                                 break;
124                         }
125                 }
126         }
127
128         if (status != EFI_SUCCESS) {
129                 debug("No rng device found\n");
130                 return EFI_DEVICE_ERROR;
131         }
132
133         if (*dev) {
134                 ret = device_probe(*dev);
135                 if (ret)
136                         return EFI_DEVICE_ERROR;
137         } else {
138                 debug("Couldn't get child device\n");
139                 return EFI_DEVICE_ERROR;
140         }
141
142         return EFI_SUCCESS;
143 }
144 #endif /* CONFIG_EFI_RNG_PROTOCOL */
145
146 #ifdef CONFIG_ARM64
147 #define __W     "w"
148 #else
149 #define __W
150 #endif
151
152 u8 flash_read8(void *addr)
153 {
154         u8 ret;
155
156         asm("ldrb %" __W "0, %1" : "=r"(ret) : "m"(*(u8 *)addr));
157         return ret;
158 }
159
160 u16 flash_read16(void *addr)
161 {
162         u16 ret;
163
164         asm("ldrh %" __W "0, %1" : "=r"(ret) : "m"(*(u16 *)addr));
165         return ret;
166 }
167
168 u32 flash_read32(void *addr)
169 {
170         u32 ret;
171
172         asm("ldr %" __W "0, %1" : "=r"(ret) : "m"(*(u32 *)addr));
173         return ret;
174 }
175
176 void flash_write8(u8 value, void *addr)
177 {
178         asm("strb %" __W "1, %0" : "=m"(*(u8 *)addr) : "r"(value));
179 }
180
181 void flash_write16(u16 value, void *addr)
182 {
183         asm("strh %" __W "1, %0" : "=m"(*(u16 *)addr) : "r"(value));
184 }
185
186 void flash_write32(u32 value, void *addr)
187 {
188         asm("str %" __W "1, %0" : "=m"(*(u32 *)addr) : "r"(value));
189 }