Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 1 | /* |
| 2 | * ARM Versatile Express emulation. |
| 3 | * |
| 4 | * Copyright (c) 2010 - 2011 B Labs Ltd. |
| 5 | * Copyright (c) 2011 Linaro Limited |
| 6 | * Written by Bahadir Balban, Amit Mahajan, Peter Maydell |
| 7 | * |
| 8 | * This program is free software; you can redistribute it and/or modify |
| 9 | * it under the terms of the GNU General Public License version 2 as |
| 10 | * published by the Free Software Foundation. |
| 11 | * |
| 12 | * This program is distributed in the hope that it will be useful, |
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | * GNU General Public License for more details. |
| 16 | * |
| 17 | * You should have received a copy of the GNU General Public License along |
| 18 | * with this program; if not, see <http://www.gnu.org/licenses/>. |
Paolo Bonzini | 6b620ca | 2012-01-13 17:44:23 +0100 | [diff] [blame] | 19 | * |
| 20 | * Contributions after 2012-01-13 are licensed under the terms of the |
| 21 | * GNU GPL, version 2 or (at your option) any later version. |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 22 | */ |
| 23 | |
| 24 | #include "sysbus.h" |
| 25 | #include "arm-misc.h" |
| 26 | #include "primecell.h" |
| 27 | #include "devices.h" |
| 28 | #include "net.h" |
| 29 | #include "sysemu.h" |
| 30 | #include "boards.h" |
Avi Kivity | e6d17b0 | 2011-10-05 18:49:54 +0200 | [diff] [blame] | 31 | #include "exec-memory.h" |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 32 | |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 33 | #define VEXPRESS_BOARD_ID 0x8e0 |
| 34 | |
Peter Maydell | aac1e02 | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 35 | static struct arm_boot_info vexpress_binfo; |
Peter Maydell | 2558e0a | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 36 | |
| 37 | /* Address maps for peripherals: |
| 38 | * the Versatile Express motherboard has two possible maps, |
| 39 | * the "legacy" one (used for A9) and the "Cortex-A Series" |
| 40 | * map (used for newer cores). |
| 41 | * Individual daughterboards can also have different maps for |
| 42 | * their peripherals. |
| 43 | */ |
| 44 | |
| 45 | enum { |
| 46 | VE_SYSREGS, |
| 47 | VE_SP810, |
| 48 | VE_SERIALPCI, |
| 49 | VE_PL041, |
| 50 | VE_MMCI, |
| 51 | VE_KMI0, |
| 52 | VE_KMI1, |
| 53 | VE_UART0, |
| 54 | VE_UART1, |
| 55 | VE_UART2, |
| 56 | VE_UART3, |
| 57 | VE_WDT, |
| 58 | VE_TIMER01, |
| 59 | VE_TIMER23, |
| 60 | VE_SERIALDVI, |
| 61 | VE_RTC, |
| 62 | VE_COMPACTFLASH, |
| 63 | VE_CLCD, |
| 64 | VE_NORFLASH0, |
| 65 | VE_NORFLASH0ALIAS, |
| 66 | VE_NORFLASH1, |
| 67 | VE_SRAM, |
| 68 | VE_VIDEORAM, |
| 69 | VE_ETHERNET, |
| 70 | VE_USB, |
| 71 | VE_DAPROM, |
| 72 | }; |
| 73 | |
| 74 | static target_phys_addr_t motherboard_legacy_map[] = { |
| 75 | /* CS7: 0x10000000 .. 0x10020000 */ |
| 76 | [VE_SYSREGS] = 0x10000000, |
| 77 | [VE_SP810] = 0x10001000, |
| 78 | [VE_SERIALPCI] = 0x10002000, |
| 79 | [VE_PL041] = 0x10004000, |
| 80 | [VE_MMCI] = 0x10005000, |
| 81 | [VE_KMI0] = 0x10006000, |
| 82 | [VE_KMI1] = 0x10007000, |
| 83 | [VE_UART0] = 0x10009000, |
| 84 | [VE_UART1] = 0x1000a000, |
| 85 | [VE_UART2] = 0x1000b000, |
| 86 | [VE_UART3] = 0x1000c000, |
| 87 | [VE_WDT] = 0x1000f000, |
| 88 | [VE_TIMER01] = 0x10011000, |
| 89 | [VE_TIMER23] = 0x10012000, |
| 90 | [VE_SERIALDVI] = 0x10016000, |
| 91 | [VE_RTC] = 0x10017000, |
| 92 | [VE_COMPACTFLASH] = 0x1001a000, |
| 93 | [VE_CLCD] = 0x1001f000, |
| 94 | /* CS0: 0x40000000 .. 0x44000000 */ |
| 95 | [VE_NORFLASH0] = 0x40000000, |
| 96 | /* CS1: 0x44000000 .. 0x48000000 */ |
| 97 | [VE_NORFLASH1] = 0x44000000, |
| 98 | /* CS2: 0x48000000 .. 0x4a000000 */ |
| 99 | [VE_SRAM] = 0x48000000, |
| 100 | /* CS3: 0x4c000000 .. 0x50000000 */ |
| 101 | [VE_VIDEORAM] = 0x4c000000, |
| 102 | [VE_ETHERNET] = 0x4e000000, |
| 103 | [VE_USB] = 0x4f000000, |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 104 | }; |
| 105 | |
Peter Maydell | 961f195 | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 106 | static target_phys_addr_t motherboard_aseries_map[] = { |
| 107 | /* CS0: 0x00000000 .. 0x0c000000 */ |
| 108 | [VE_NORFLASH0] = 0x00000000, |
| 109 | [VE_NORFLASH0ALIAS] = 0x08000000, |
| 110 | /* CS4: 0x0c000000 .. 0x10000000 */ |
| 111 | [VE_NORFLASH1] = 0x0c000000, |
| 112 | /* CS5: 0x10000000 .. 0x14000000 */ |
| 113 | /* CS1: 0x14000000 .. 0x18000000 */ |
| 114 | [VE_SRAM] = 0x14000000, |
| 115 | /* CS2: 0x18000000 .. 0x1c000000 */ |
| 116 | [VE_VIDEORAM] = 0x18000000, |
| 117 | [VE_ETHERNET] = 0x1a000000, |
| 118 | [VE_USB] = 0x1b000000, |
| 119 | /* CS3: 0x1c000000 .. 0x20000000 */ |
| 120 | [VE_DAPROM] = 0x1c000000, |
| 121 | [VE_SYSREGS] = 0x1c010000, |
| 122 | [VE_SP810] = 0x1c020000, |
| 123 | [VE_SERIALPCI] = 0x1c030000, |
| 124 | [VE_PL041] = 0x1c040000, |
| 125 | [VE_MMCI] = 0x1c050000, |
| 126 | [VE_KMI0] = 0x1c060000, |
| 127 | [VE_KMI1] = 0x1c070000, |
| 128 | [VE_UART0] = 0x1c090000, |
| 129 | [VE_UART1] = 0x1c0a0000, |
| 130 | [VE_UART2] = 0x1c0b0000, |
| 131 | [VE_UART3] = 0x1c0c0000, |
| 132 | [VE_WDT] = 0x1c0f0000, |
| 133 | [VE_TIMER01] = 0x1c110000, |
| 134 | [VE_TIMER23] = 0x1c120000, |
| 135 | [VE_SERIALDVI] = 0x1c160000, |
| 136 | [VE_RTC] = 0x1c170000, |
| 137 | [VE_COMPACTFLASH] = 0x1c1a0000, |
| 138 | [VE_CLCD] = 0x1c1f0000, |
| 139 | }; |
| 140 | |
Peter Maydell | 4c3b29b | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 141 | /* Structure defining the peculiarities of a specific daughterboard */ |
| 142 | |
| 143 | typedef struct VEDBoardInfo VEDBoardInfo; |
| 144 | |
| 145 | typedef void DBoardInitFn(const VEDBoardInfo *daughterboard, |
| 146 | ram_addr_t ram_size, |
| 147 | const char *cpu_model, |
| 148 | qemu_irq *pic, uint32_t *proc_id); |
| 149 | |
| 150 | struct VEDBoardInfo { |
| 151 | const target_phys_addr_t *motherboard_map; |
| 152 | target_phys_addr_t loader_start; |
Peter Maydell | 96eacf6 | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 153 | const target_phys_addr_t gic_cpu_if_addr; |
Peter Maydell | 4c3b29b | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 154 | DBoardInitFn *init; |
| 155 | }; |
| 156 | |
| 157 | static void a9_daughterboard_init(const VEDBoardInfo *daughterboard, |
| 158 | ram_addr_t ram_size, |
| 159 | const char *cpu_model, |
| 160 | qemu_irq *pic, uint32_t *proc_id) |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 161 | { |
Andreas Färber | 5ae9330 | 2012-03-14 01:38:23 +0100 | [diff] [blame] | 162 | CPUARMState *env = NULL; |
Avi Kivity | e6d17b0 | 2011-10-05 18:49:54 +0200 | [diff] [blame] | 163 | MemoryRegion *sysmem = get_system_memory(); |
| 164 | MemoryRegion *ram = g_new(MemoryRegion, 1); |
| 165 | MemoryRegion *lowram = g_new(MemoryRegion, 1); |
Peter Maydell | 4c3b29b | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 166 | DeviceState *dev; |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 167 | SysBusDevice *busdev; |
| 168 | qemu_irq *irqp; |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 169 | int n; |
| 170 | qemu_irq cpu_irq[4]; |
Peter Maydell | 4c3b29b | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 171 | ram_addr_t low_ram_size; |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 172 | |
| 173 | if (!cpu_model) { |
| 174 | cpu_model = "cortex-a9"; |
| 175 | } |
| 176 | |
Peter Maydell | 4c3b29b | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 177 | *proc_id = 0x0c000191; |
| 178 | |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 179 | for (n = 0; n < smp_cpus; n++) { |
| 180 | env = cpu_init(cpu_model); |
| 181 | if (!env) { |
| 182 | fprintf(stderr, "Unable to find CPU definition\n"); |
| 183 | exit(1); |
| 184 | } |
| 185 | irqp = arm_pic_init_cpu(env); |
| 186 | cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ]; |
| 187 | } |
| 188 | |
| 189 | if (ram_size > 0x40000000) { |
| 190 | /* 1GB is the maximum the address space permits */ |
Peter Maydell | 4c3b29b | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 191 | fprintf(stderr, "vexpress-a9: cannot model more than 1GB RAM\n"); |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 192 | exit(1); |
| 193 | } |
| 194 | |
Avi Kivity | c5705a7 | 2011-12-20 15:59:12 +0200 | [diff] [blame] | 195 | memory_region_init_ram(ram, "vexpress.highmem", ram_size); |
| 196 | vmstate_register_ram_global(ram); |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 197 | low_ram_size = ram_size; |
| 198 | if (low_ram_size > 0x4000000) { |
| 199 | low_ram_size = 0x4000000; |
| 200 | } |
| 201 | /* RAM is from 0x60000000 upwards. The bottom 64MB of the |
| 202 | * address space should in theory be remappable to various |
| 203 | * things including ROM or RAM; we always map the RAM there. |
| 204 | */ |
Avi Kivity | e6d17b0 | 2011-10-05 18:49:54 +0200 | [diff] [blame] | 205 | memory_region_init_alias(lowram, "vexpress.lowmem", ram, 0, low_ram_size); |
| 206 | memory_region_add_subregion(sysmem, 0x0, lowram); |
| 207 | memory_region_add_subregion(sysmem, 0x60000000, ram); |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 208 | |
| 209 | /* 0x1e000000 A9MPCore (SCU) private memory region */ |
| 210 | dev = qdev_create(NULL, "a9mpcore_priv"); |
| 211 | qdev_prop_set_uint32(dev, "num-cpu", smp_cpus); |
| 212 | qdev_init_nofail(dev); |
| 213 | busdev = sysbus_from_qdev(dev); |
Peter Maydell | 96eacf6 | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 214 | sysbus_mmio_map(busdev, 0, 0x1e000000); |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 215 | for (n = 0; n < smp_cpus; n++) { |
| 216 | sysbus_connect_irq(busdev, n, cpu_irq[n]); |
| 217 | } |
| 218 | /* Interrupts [42:0] are from the motherboard; |
| 219 | * [47:43] are reserved; [63:48] are daughterboard |
| 220 | * peripherals. Note that some documentation numbers |
| 221 | * external interrupts starting from 32 (because the |
| 222 | * A9MP has internal interrupts 0..31). |
| 223 | */ |
| 224 | for (n = 0; n < 64; n++) { |
| 225 | pic[n] = qdev_get_gpio_in(dev, n); |
| 226 | } |
| 227 | |
Peter Maydell | 4c3b29b | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 228 | /* Daughterboard peripherals : 0x10020000 .. 0x20000000 */ |
| 229 | |
| 230 | /* 0x10020000 PL111 CLCD (daughterboard) */ |
| 231 | sysbus_create_simple("pl111", 0x10020000, pic[44]); |
| 232 | |
| 233 | /* 0x10060000 AXI RAM */ |
| 234 | /* 0x100e0000 PL341 Dynamic Memory Controller */ |
| 235 | /* 0x100e1000 PL354 Static Memory Controller */ |
| 236 | /* 0x100e2000 System Configuration Controller */ |
| 237 | |
| 238 | sysbus_create_simple("sp804", 0x100e4000, pic[48]); |
| 239 | /* 0x100e5000 SP805 Watchdog module */ |
| 240 | /* 0x100e6000 BP147 TrustZone Protection Controller */ |
| 241 | /* 0x100e9000 PL301 'Fast' AXI matrix */ |
| 242 | /* 0x100ea000 PL301 'Slow' AXI matrix */ |
| 243 | /* 0x100ec000 TrustZone Address Space Controller */ |
| 244 | /* 0x10200000 CoreSight debug APB */ |
| 245 | /* 0x1e00a000 PL310 L2 Cache Controller */ |
| 246 | sysbus_create_varargs("l2x0", 0x1e00a000, NULL); |
| 247 | } |
| 248 | |
| 249 | static const VEDBoardInfo a9_daughterboard = { |
| 250 | .motherboard_map = motherboard_legacy_map, |
| 251 | .loader_start = 0x60000000, |
Peter Maydell | 96eacf6 | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 252 | .gic_cpu_if_addr = 0x1e000100, |
Peter Maydell | 4c3b29b | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 253 | .init = a9_daughterboard_init, |
| 254 | }; |
| 255 | |
Peter Maydell | 961f195 | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 256 | static void a15_daughterboard_init(const VEDBoardInfo *daughterboard, |
| 257 | ram_addr_t ram_size, |
| 258 | const char *cpu_model, |
| 259 | qemu_irq *pic, uint32_t *proc_id) |
| 260 | { |
| 261 | int n; |
Andreas Färber | 5ae9330 | 2012-03-14 01:38:23 +0100 | [diff] [blame] | 262 | CPUARMState *env = NULL; |
Peter Maydell | 961f195 | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 263 | MemoryRegion *sysmem = get_system_memory(); |
| 264 | MemoryRegion *ram = g_new(MemoryRegion, 1); |
| 265 | MemoryRegion *sram = g_new(MemoryRegion, 1); |
| 266 | qemu_irq cpu_irq[4]; |
| 267 | DeviceState *dev; |
| 268 | SysBusDevice *busdev; |
| 269 | |
| 270 | if (!cpu_model) { |
| 271 | cpu_model = "cortex-a15"; |
| 272 | } |
| 273 | |
| 274 | *proc_id = 0x14000217; |
| 275 | |
| 276 | for (n = 0; n < smp_cpus; n++) { |
| 277 | qemu_irq *irqp; |
| 278 | env = cpu_init(cpu_model); |
| 279 | if (!env) { |
| 280 | fprintf(stderr, "Unable to find CPU definition\n"); |
| 281 | exit(1); |
| 282 | } |
| 283 | irqp = arm_pic_init_cpu(env); |
| 284 | cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ]; |
| 285 | } |
| 286 | |
| 287 | if (ram_size > 0x80000000) { |
| 288 | fprintf(stderr, "vexpress-a15: cannot model more than 2GB RAM\n"); |
| 289 | exit(1); |
| 290 | } |
| 291 | |
| 292 | memory_region_init_ram(ram, "vexpress.highmem", ram_size); |
| 293 | vmstate_register_ram_global(ram); |
| 294 | /* RAM is from 0x80000000 upwards; there is no low-memory alias for it. */ |
| 295 | memory_region_add_subregion(sysmem, 0x80000000, ram); |
| 296 | |
| 297 | /* 0x2c000000 A15MPCore private memory region (GIC) */ |
| 298 | dev = qdev_create(NULL, "a15mpcore_priv"); |
| 299 | qdev_prop_set_uint32(dev, "num-cpu", smp_cpus); |
| 300 | qdev_init_nofail(dev); |
| 301 | busdev = sysbus_from_qdev(dev); |
| 302 | sysbus_mmio_map(busdev, 0, 0x2c000000); |
| 303 | for (n = 0; n < smp_cpus; n++) { |
| 304 | sysbus_connect_irq(busdev, n, cpu_irq[n]); |
| 305 | } |
| 306 | /* Interrupts [42:0] are from the motherboard; |
| 307 | * [47:43] are reserved; [63:48] are daughterboard |
| 308 | * peripherals. Note that some documentation numbers |
| 309 | * external interrupts starting from 32 (because there |
| 310 | * are internal interrupts 0..31). |
| 311 | */ |
| 312 | for (n = 0; n < 64; n++) { |
| 313 | pic[n] = qdev_get_gpio_in(dev, n); |
| 314 | } |
| 315 | |
| 316 | /* A15 daughterboard peripherals: */ |
| 317 | |
| 318 | /* 0x20000000: CoreSight interfaces: not modelled */ |
| 319 | /* 0x2a000000: PL301 AXI interconnect: not modelled */ |
| 320 | /* 0x2a420000: SCC: not modelled */ |
| 321 | /* 0x2a430000: system counter: not modelled */ |
| 322 | /* 0x2b000000: HDLCD controller: not modelled */ |
| 323 | /* 0x2b060000: SP805 watchdog: not modelled */ |
| 324 | /* 0x2b0a0000: PL341 dynamic memory controller: not modelled */ |
| 325 | /* 0x2e000000: system SRAM */ |
| 326 | memory_region_init_ram(sram, "vexpress.a15sram", 0x10000); |
| 327 | vmstate_register_ram_global(sram); |
| 328 | memory_region_add_subregion(sysmem, 0x2e000000, sram); |
| 329 | |
| 330 | /* 0x7ffb0000: DMA330 DMA controller: not modelled */ |
| 331 | /* 0x7ffd0000: PL354 static memory controller: not modelled */ |
| 332 | } |
| 333 | |
| 334 | static const VEDBoardInfo a15_daughterboard = { |
| 335 | .motherboard_map = motherboard_aseries_map, |
| 336 | .loader_start = 0x80000000, |
| 337 | .gic_cpu_if_addr = 0x2c002000, |
| 338 | .init = a15_daughterboard_init, |
| 339 | }; |
| 340 | |
Peter Maydell | 4c3b29b | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 341 | static void vexpress_common_init(const VEDBoardInfo *daughterboard, |
| 342 | ram_addr_t ram_size, |
| 343 | const char *boot_device, |
| 344 | const char *kernel_filename, |
| 345 | const char *kernel_cmdline, |
| 346 | const char *initrd_filename, |
| 347 | const char *cpu_model) |
| 348 | { |
| 349 | DeviceState *dev, *sysctl, *pl041; |
| 350 | qemu_irq pic[64]; |
| 351 | uint32_t proc_id; |
| 352 | uint32_t sys_id; |
| 353 | ram_addr_t vram_size, sram_size; |
| 354 | MemoryRegion *sysmem = get_system_memory(); |
| 355 | MemoryRegion *vram = g_new(MemoryRegion, 1); |
| 356 | MemoryRegion *sram = g_new(MemoryRegion, 1); |
| 357 | const target_phys_addr_t *map = daughterboard->motherboard_map; |
| 358 | |
| 359 | daughterboard->init(daughterboard, ram_size, cpu_model, pic, &proc_id); |
| 360 | |
Peter Maydell | 2558e0a | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 361 | /* Motherboard peripherals: the wiring is the same but the |
| 362 | * addresses vary between the legacy and A-Series memory maps. |
| 363 | */ |
| 364 | |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 365 | sys_id = 0x1190f500; |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 366 | |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 367 | sysctl = qdev_create(NULL, "realview_sysctl"); |
| 368 | qdev_prop_set_uint32(sysctl, "sys_id", sys_id); |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 369 | qdev_prop_set_uint32(sysctl, "proc_id", proc_id); |
Peter Maydell | 7a65c8c | 2012-02-09 06:11:16 +0000 | [diff] [blame] | 370 | qdev_init_nofail(sysctl); |
Peter Maydell | 2558e0a | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 371 | sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, map[VE_SYSREGS]); |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 372 | |
Peter Maydell | 2558e0a | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 373 | /* VE_SP810: not modelled */ |
| 374 | /* VE_SERIALPCI: not modelled */ |
| 375 | |
Peter Maydell | 03a0e94 | 2011-10-28 10:55:38 +0100 | [diff] [blame] | 376 | pl041 = qdev_create(NULL, "pl041"); |
| 377 | qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512); |
| 378 | qdev_init_nofail(pl041); |
Peter Maydell | 2558e0a | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 379 | sysbus_mmio_map(sysbus_from_qdev(pl041), 0, map[VE_PL041]); |
Peter Maydell | 03a0e94 | 2011-10-28 10:55:38 +0100 | [diff] [blame] | 380 | sysbus_connect_irq(sysbus_from_qdev(pl041), 0, pic[11]); |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 381 | |
Peter Maydell | 2558e0a | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 382 | dev = sysbus_create_varargs("pl181", map[VE_MMCI], pic[9], pic[10], NULL); |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 383 | /* Wire up MMC card detect and read-only signals */ |
| 384 | qdev_connect_gpio_out(dev, 0, |
| 385 | qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT)); |
| 386 | qdev_connect_gpio_out(dev, 1, |
| 387 | qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN)); |
| 388 | |
Peter Maydell | 2558e0a | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 389 | sysbus_create_simple("pl050_keyboard", map[VE_KMI0], pic[12]); |
| 390 | sysbus_create_simple("pl050_mouse", map[VE_KMI1], pic[13]); |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 391 | |
Peter Maydell | 2558e0a | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 392 | sysbus_create_simple("pl011", map[VE_UART0], pic[5]); |
| 393 | sysbus_create_simple("pl011", map[VE_UART1], pic[6]); |
| 394 | sysbus_create_simple("pl011", map[VE_UART2], pic[7]); |
| 395 | sysbus_create_simple("pl011", map[VE_UART3], pic[8]); |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 396 | |
Peter Maydell | 2558e0a | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 397 | sysbus_create_simple("sp804", map[VE_TIMER01], pic[2]); |
| 398 | sysbus_create_simple("sp804", map[VE_TIMER23], pic[3]); |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 399 | |
Peter Maydell | 2558e0a | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 400 | /* VE_SERIALDVI: not modelled */ |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 401 | |
Peter Maydell | 2558e0a | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 402 | sysbus_create_simple("pl031", map[VE_RTC], pic[4]); /* RTC */ |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 403 | |
Peter Maydell | 2558e0a | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 404 | /* VE_COMPACTFLASH: not modelled */ |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 405 | |
Peter Maydell | b720687 | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 406 | sysbus_create_simple("pl111", map[VE_CLCD], pic[14]); |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 407 | |
Peter Maydell | 2558e0a | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 408 | /* VE_NORFLASH0: not modelled */ |
| 409 | /* VE_NORFLASH0ALIAS: not modelled */ |
| 410 | /* VE_NORFLASH1: not modelled */ |
| 411 | |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 412 | sram_size = 0x2000000; |
Avi Kivity | c5705a7 | 2011-12-20 15:59:12 +0200 | [diff] [blame] | 413 | memory_region_init_ram(sram, "vexpress.sram", sram_size); |
| 414 | vmstate_register_ram_global(sram); |
Peter Maydell | 2558e0a | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 415 | memory_region_add_subregion(sysmem, map[VE_SRAM], sram); |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 416 | |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 417 | vram_size = 0x800000; |
Avi Kivity | c5705a7 | 2011-12-20 15:59:12 +0200 | [diff] [blame] | 418 | memory_region_init_ram(vram, "vexpress.vram", vram_size); |
| 419 | vmstate_register_ram_global(vram); |
Peter Maydell | 2558e0a | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 420 | memory_region_add_subregion(sysmem, map[VE_VIDEORAM], vram); |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 421 | |
| 422 | /* 0x4e000000 LAN9118 Ethernet */ |
| 423 | if (nd_table[0].vlan) { |
Peter Maydell | 2558e0a | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 424 | lan9118_init(&nd_table[0], map[VE_ETHERNET], pic[15]); |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 425 | } |
| 426 | |
Peter Maydell | 2558e0a | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 427 | /* VE_USB: not modelled */ |
| 428 | |
| 429 | /* VE_DAPROM: not modelled */ |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 430 | |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 431 | vexpress_binfo.ram_size = ram_size; |
| 432 | vexpress_binfo.kernel_filename = kernel_filename; |
| 433 | vexpress_binfo.kernel_cmdline = kernel_cmdline; |
| 434 | vexpress_binfo.initrd_filename = initrd_filename; |
| 435 | vexpress_binfo.nb_cpus = smp_cpus; |
| 436 | vexpress_binfo.board_id = VEXPRESS_BOARD_ID; |
Peter Maydell | 4c3b29b | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 437 | vexpress_binfo.loader_start = daughterboard->loader_start; |
Peter Maydell | aac1e02 | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 438 | vexpress_binfo.smp_loader_start = map[VE_SRAM]; |
Peter Maydell | 2558e0a | 2012-02-16 09:56:08 +0000 | [diff] [blame] | 439 | vexpress_binfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30; |
Peter Maydell | 96eacf6 | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 440 | vexpress_binfo.gic_cpu_if_addr = daughterboard->gic_cpu_if_addr; |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 441 | arm_load_kernel(first_cpu, &vexpress_binfo); |
| 442 | } |
| 443 | |
Peter Maydell | 4c3b29b | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 444 | static void vexpress_a9_init(ram_addr_t ram_size, |
| 445 | const char *boot_device, |
| 446 | const char *kernel_filename, |
| 447 | const char *kernel_cmdline, |
| 448 | const char *initrd_filename, |
| 449 | const char *cpu_model) |
| 450 | { |
| 451 | vexpress_common_init(&a9_daughterboard, |
| 452 | ram_size, boot_device, kernel_filename, |
| 453 | kernel_cmdline, initrd_filename, cpu_model); |
| 454 | } |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 455 | |
Peter Maydell | 961f195 | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 456 | static void vexpress_a15_init(ram_addr_t ram_size, |
| 457 | const char *boot_device, |
| 458 | const char *kernel_filename, |
| 459 | const char *kernel_cmdline, |
| 460 | const char *initrd_filename, |
| 461 | const char *cpu_model) |
| 462 | { |
| 463 | vexpress_common_init(&a15_daughterboard, |
| 464 | ram_size, boot_device, kernel_filename, |
| 465 | kernel_cmdline, initrd_filename, cpu_model); |
| 466 | } |
| 467 | |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 468 | static QEMUMachine vexpress_a9_machine = { |
| 469 | .name = "vexpress-a9", |
| 470 | .desc = "ARM Versatile Express for Cortex-A9", |
| 471 | .init = vexpress_a9_init, |
| 472 | .use_scsi = 1, |
| 473 | .max_cpus = 4, |
| 474 | }; |
| 475 | |
Peter Maydell | 961f195 | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 476 | static QEMUMachine vexpress_a15_machine = { |
| 477 | .name = "vexpress-a15", |
| 478 | .desc = "ARM Versatile Express for Cortex-A15", |
| 479 | .init = vexpress_a15_init, |
| 480 | .use_scsi = 1, |
| 481 | .max_cpus = 4, |
| 482 | }; |
| 483 | |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 484 | static void vexpress_machine_init(void) |
| 485 | { |
| 486 | qemu_register_machine(&vexpress_a9_machine); |
Peter Maydell | 961f195 | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 487 | qemu_register_machine(&vexpress_a15_machine); |
Peter Maydell | 2055283 | 2011-03-07 11:10:32 +0000 | [diff] [blame] | 488 | } |
| 489 | |
| 490 | machine_init(vexpress_machine_init); |