| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | #include "sysbus.h" |
| 11 | #include "arm-misc.h" |
| 12 | #include "primecell.h" |
| 13 | #include "devices.h" |
| 14 | #include "pci.h" |
| 15 | #include "net.h" |
| 16 | #include "sysemu.h" |
| 17 | #include "boards.h" |
| 18 | #include "i2c.h" |
| 19 | #include "blockdev.h" |
| 20 | #include "exec-memory.h" |
| 21 | |
| 22 | #define SMP_BOOT_ADDR0xe0000000 0xe0000000 |
| 23 | #define SMP_BOOTREG_ADDR0x10000030 0x10000030 |
| 24 | |
| 25 | |
| 26 | |
| 27 | static struct arm_boot_info realview_binfo = { |
| 28 | .smp_loader_start = SMP_BOOT_ADDR0xe0000000, |
| 29 | .smp_bootreg_addr = SMP_BOOTREG_ADDR0x10000030, |
| 30 | }; |
| 31 | |
| 32 | |
| 33 | enum realview_board_type { |
| 34 | BOARD_EB, |
| 35 | BOARD_EB_MPCORE, |
| 36 | BOARD_PB_A8, |
| 37 | BOARD_PBX_A9, |
| 38 | }; |
| 39 | |
| 40 | static const int realview_board_id[] = { |
| 41 | 0x33b, |
| 42 | 0x33b, |
| 43 | 0x769, |
| 44 | 0x76d |
| 45 | }; |
| 46 | |
| 47 | static void realview_init(ram_addr_t ram_size, |
| 48 | const char *boot_device, |
| 49 | const char *kernel_filename, const char *kernel_cmdline, |
| 50 | const char *initrd_filename, const char *cpu_model, |
| 51 | enum realview_board_type board_type) |
| 52 | { |
| 53 | ARMCPU *cpu = NULL((void*)0); |
| 54 | CPUARMState *env; |
| 55 | MemoryRegion *sysmem = get_system_memory(); |
| 56 | MemoryRegion *ram_lo = g_new(MemoryRegion, 1)((MemoryRegion *) g_malloc_n ((1), sizeof (MemoryRegion))); |
| 57 | MemoryRegion *ram_hi = g_new(MemoryRegion, 1)((MemoryRegion *) g_malloc_n ((1), sizeof (MemoryRegion))); |
| 58 | MemoryRegion *ram_alias = g_new(MemoryRegion, 1)((MemoryRegion *) g_malloc_n ((1), sizeof (MemoryRegion))); |
| 59 | MemoryRegion *ram_hack = g_new(MemoryRegion, 1)((MemoryRegion *) g_malloc_n ((1), sizeof (MemoryRegion))); |
| 60 | DeviceState *dev, *sysctl, *gpio2, *pl041; |
| 61 | SysBusDevice *busdev; |
| 62 | qemu_irq *irqp; |
| 63 | qemu_irq pic[64]; |
| 64 | qemu_irq mmc_irq[2]; |
| 65 | PCIBus *pci_bus; |
| 66 | NICInfo *nd; |
| 67 | i2c_bus *i2c; |
| 68 | int n; |
| 69 | int done_nic = 0; |
| 70 | qemu_irq cpu_irq[4]; |
| 71 | int is_mpcore = 0; |
| 72 | int is_pb = 0; |
| 73 | uint32_t proc_id = 0; |
| 74 | uint32_t sys_id; |
| 75 | ram_addr_t low_ram_size; |
| 76 | |
| 77 | switch (board_type) { |
| 1 | 'Default' branch taken. Execution continues on line 91 |
|
| 78 | case BOARD_EB: |
| 79 | break; |
| 80 | case BOARD_EB_MPCORE: |
| 81 | is_mpcore = 1; |
| 82 | break; |
| 83 | case BOARD_PB_A8: |
| 84 | is_pb = 1; |
| 85 | break; |
| 86 | case BOARD_PBX_A9: |
| 87 | is_mpcore = 1; |
| 88 | is_pb = 1; |
| 89 | break; |
| 90 | } |
| 91 | for (n = 0; n < smp_cpus; n++) { |
| 2 | Loop condition is false. Execution continues on line 100 |
|
| 92 | cpu = cpu_arm_init(cpu_model); |
| 93 | if (!cpu) { |
| 94 | fprintf(stderrstderr, "Unable to find CPU definition\n"); |
| 95 | exit(1); |
| 96 | } |
| 97 | irqp = arm_pic_init_cpu(cpu); |
| 98 | cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ0]; |
| 99 | } |
| 100 | env = &cpu->env; |
| 101 | if (arm_feature(env, ARM_FEATURE_V7)) { |
| |
| 102 | if (is_mpcore) { |
| |
| 103 | proc_id = 0x0c000000; |
| 104 | } else { |
| 105 | proc_id = 0x0e000000; |
| 106 | } |
| 107 | } else if (arm_feature(env, ARM_FEATURE_V6K)) { |
| 108 | proc_id = 0x06000000; |
| 109 | } else if (arm_feature(env, ARM_FEATURE_V6)) { |
| 110 | proc_id = 0x04000000; |
| 111 | } else { |
| 112 | proc_id = 0x02000000; |
| 113 | } |
| 114 | |
| 115 | if (is_pb && ram_size > 0x20000000) { |
| |
| 116 | |
| 117 | low_ram_size = ram_size - 0x20000000; |
| 118 | ram_size = 0x20000000; |
| 119 | memory_region_init_ram(ram_lo, "realview.lowmem", low_ram_size); |
| 120 | vmstate_register_ram_global(ram_lo); |
| 121 | memory_region_add_subregion(sysmem, 0x20000000, ram_lo); |
| 122 | } |
| 123 | |
| 124 | memory_region_init_ram(ram_hi, "realview.highmem", ram_size); |
| 125 | vmstate_register_ram_global(ram_hi); |
| 126 | low_ram_size = ram_size; |
| 127 | if (low_ram_size > 0x10000000) |
| |
| 128 | low_ram_size = 0x10000000; |
| 129 | |
| 130 | memory_region_init_alias(ram_alias, "realview.alias", |
| 131 | ram_hi, 0, low_ram_size); |
| 132 | memory_region_add_subregion(sysmem, 0, ram_alias); |
| 133 | if (is_pb) { |
| |
| 134 | |
| 135 | memory_region_add_subregion(sysmem, 0x70000000, ram_hi); |
| 136 | } else { |
| 137 | ram_size = low_ram_size; |
| 138 | } |
| 139 | |
| 140 | sys_id = is_pb ? 0x01780500 : 0xc1400400; |
| |
| 141 | sysctl = qdev_create(NULL((void*)0), "realview_sysctl"); |
| 142 | qdev_prop_set_uint32(sysctl, "sys_id", sys_id); |
| 143 | qdev_prop_set_uint32(sysctl, "proc_id", proc_id); |
| 144 | qdev_init_nofail(sysctl); |
| 145 | sysbus_mmio_map(sysbus_from_qdev(sysctl)((SysBusDevice *)(sysctl)), 0, 0x10000000); |
| 146 | |
| 147 | if (is_mpcore) { |
| |
| 148 | target_phys_addr_t periphbase; |
| 149 | dev = qdev_create(NULL((void*)0), is_pb ? "a9mpcore_priv": "realview_mpcore"); |
| 150 | qdev_prop_set_uint32(dev, "num-cpu", smp_cpus); |
| 151 | qdev_init_nofail(dev); |
| 152 | busdev = sysbus_from_qdev(dev)((SysBusDevice *)(dev)); |
| 153 | if (is_pb) { |
| 154 | periphbase = 0x1f000000; |
| 155 | } else { |
| 156 | periphbase = 0x10100000; |
| 157 | } |
| 158 | sysbus_mmio_map(busdev, 0, periphbase); |
| 159 | for (n = 0; n < smp_cpus; n++) { |
| 160 | sysbus_connect_irq(busdev, n, cpu_irq[n]); |
| 161 | } |
| 162 | sysbus_create_varargs("l2x0", periphbase + 0x2000, NULL((void*)0)); |
| 163 | |
| 164 | realview_binfo.gic_cpu_if_addr = periphbase + 0x100; |
| 165 | } else { |
| 166 | uint32_t gic_addr = is_pb ? 0x1e000000 : 0x10040000; |
| |
| 167 | |
| 168 | dev = sysbus_create_simple("realview_gic", gic_addr, cpu_irq[0]); |
| 11 | Pass-by-value argument in function call is undefined |
|
| 169 | } |
| 170 | for (n = 0; n < 64; n++) { |
| 171 | pic[n] = qdev_get_gpio_in(dev, n); |
| 172 | } |
| 173 | |
| 174 | pl041 = qdev_create(NULL((void*)0), "pl041"); |
| 175 | qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512); |
| 176 | qdev_init_nofail(pl041); |
| 177 | sysbus_mmio_map(sysbus_from_qdev(pl041)((SysBusDevice *)(pl041)), 0, 0x10004000); |
| 178 | sysbus_connect_irq(sysbus_from_qdev(pl041)((SysBusDevice *)(pl041)), 0, pic[19]); |
| 179 | |
| 180 | sysbus_create_simple("pl050_keyboard", 0x10006000, pic[20]); |
| 181 | sysbus_create_simple("pl050_mouse", 0x10007000, pic[21]); |
| 182 | |
| 183 | sysbus_create_simple("pl011", 0x10009000, pic[12]); |
| 184 | sysbus_create_simple("pl011", 0x1000a000, pic[13]); |
| 185 | sysbus_create_simple("pl011", 0x1000b000, pic[14]); |
| 186 | sysbus_create_simple("pl011", 0x1000c000, pic[15]); |
| 187 | |
| 188 | |
| 189 | sysbus_create_simple("pl081", 0x10030000, pic[24]); |
| 190 | |
| 191 | sysbus_create_simple("sp804", 0x10011000, pic[4]); |
| 192 | sysbus_create_simple("sp804", 0x10012000, pic[5]); |
| 193 | |
| 194 | sysbus_create_simple("pl061", 0x10013000, pic[6]); |
| 195 | sysbus_create_simple("pl061", 0x10014000, pic[7]); |
| 196 | gpio2 = sysbus_create_simple("pl061", 0x10015000, pic[8]); |
| 197 | |
| 198 | sysbus_create_simple("pl111", 0x10020000, pic[23]); |
| 199 | |
| 200 | dev = sysbus_create_varargs("pl181", 0x10005000, pic[17], pic[18], NULL((void*)0)); |
| 201 | |
| 202 | |
| 203 | |
| 204 | |
| 205 | |
| 206 | |
| 207 | mmc_irq[0] = qemu_irq_split( |
| 208 | qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT0), |
| 209 | qdev_get_gpio_in(gpio2, 1)); |
| 210 | mmc_irq[1] = qemu_irq_split( |
| 211 | qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN1), |
| 212 | qemu_irq_invert(qdev_get_gpio_in(gpio2, 0))); |
| 213 | qdev_connect_gpio_out(dev, 0, mmc_irq[0]); |
| 214 | qdev_connect_gpio_out(dev, 1, mmc_irq[1]); |
| 215 | |
| 216 | sysbus_create_simple("pl031", 0x10017000, pic[10]); |
| 217 | |
| 218 | if (!is_pb) { |
| 219 | dev = qdev_create(NULL((void*)0), "realview_pci"); |
| 220 | busdev = sysbus_from_qdev(dev)((SysBusDevice *)(dev)); |
| 221 | qdev_init_nofail(dev); |
| 222 | sysbus_mmio_map(busdev, 0, 0x61000000); |
| 223 | sysbus_mmio_map(busdev, 1, 0x62000000); |
| 224 | sysbus_mmio_map(busdev, 2, 0x63000000); |
| 225 | sysbus_connect_irq(busdev, 0, pic[48]); |
| 226 | sysbus_connect_irq(busdev, 1, pic[49]); |
| 227 | sysbus_connect_irq(busdev, 2, pic[50]); |
| 228 | sysbus_connect_irq(busdev, 3, pic[51]); |
| 229 | pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci"); |
| 230 | if (usb_enabled) { |
| 231 | pci_create_simple(pci_bus, -1, "pci-ohci"); |
| 232 | } |
| 233 | n = drive_get_max_bus(IF_SCSI); |
| 234 | while (n >= 0) { |
| 235 | pci_create_simple(pci_bus, -1, "lsi53c895a"); |
| 236 | n--; |
| 237 | } |
| 238 | } |
| 239 | for(n = 0; n < nb_nics; n++) { |
| 240 | nd = &nd_table[n]; |
| 241 | |
| 242 | if (!done_nic && (!nd->model || |
| 243 | strcmp(nd->model, is_pb ? "lan9118" : "smc91c111") == 0)) { |
| 244 | if (is_pb) { |
| 245 | lan9118_init(nd, 0x4e000000, pic[28]); |
| 246 | } else { |
| 247 | smc91c111_init(nd, 0x4e000000, pic[28]); |
| 248 | } |
| 249 | done_nic = 1; |
| 250 | } else { |
| 251 | pci_nic_init_nofail(nd, "rtl8139", NULL((void*)0)); |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL((void*)0)); |
| 256 | i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c"); |
| 257 | i2c_create_slave(i2c, "ds1338", 0x68); |
| 258 | |
| 259 | |
| 260 | |
| 261 | |
| 262 | |
| 263 | |
| 264 | |
| 265 | |
| 266 | |
| 267 | |
| 268 | |
| 269 | |
| 270 | |
| 271 | |
| 272 | |
| 273 | |
| 274 | |
| 275 | |
| 276 | |
| 277 | |
| 278 | |
| 279 | |
| 280 | |
| 281 | |
| 282 | |
| 283 | |
| 284 | |
| 285 | |
| 286 | |
| 287 | |
| 288 | |
| 289 | |
| 290 | |
| 291 | |
| 292 | |
| 293 | |
| 294 | |
| 295 | |
| 296 | |
| 297 | |
| 298 | |
| 299 | |
| 300 | |
| 301 | |
| 302 | |
| 303 | |
| 304 | |
| 305 | |
| 306 | |
| 307 | |
| 308 | |
| 309 | |
| 310 | |
| 311 | |
| 312 | |
| 313 | |
| 314 | |
| 315 | |
| 316 | |
| 317 | |
| 318 | |
| 319 | memory_region_init_ram(ram_hack, "realview.hack", 0x1000); |
| 320 | vmstate_register_ram_global(ram_hack); |
| 321 | memory_region_add_subregion(sysmem, SMP_BOOT_ADDR0xe0000000, ram_hack); |
| 322 | |
| 323 | realview_binfo.ram_size = ram_size; |
| 324 | realview_binfo.kernel_filename = kernel_filename; |
| 325 | realview_binfo.kernel_cmdline = kernel_cmdline; |
| 326 | realview_binfo.initrd_filename = initrd_filename; |
| 327 | realview_binfo.nb_cpus = smp_cpus; |
| 328 | realview_binfo.board_id = realview_board_id[board_type]; |
| 329 | realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0); |
| 330 | arm_load_kernel(arm_env_get_cpu(first_cpu), &realview_binfo); |
| 331 | } |
| 332 | |
| 333 | static void realview_eb_init(ram_addr_t ram_size, |
| 334 | const char *boot_device, |
| 335 | const char *kernel_filename, const char *kernel_cmdline, |
| 336 | const char *initrd_filename, const char *cpu_model) |
| 337 | { |
| 338 | if (!cpu_model) { |
| 339 | cpu_model = "arm926"; |
| 340 | } |
| 341 | realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline, |
| 342 | initrd_filename, cpu_model, BOARD_EB); |
| 343 | } |
| 344 | |
| 345 | static void realview_eb_mpcore_init(ram_addr_t ram_size, |
| 346 | const char *boot_device, |
| 347 | const char *kernel_filename, const char *kernel_cmdline, |
| 348 | const char *initrd_filename, const char *cpu_model) |
| 349 | { |
| 350 | if (!cpu_model) { |
| 351 | cpu_model = "arm11mpcore"; |
| 352 | } |
| 353 | realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline, |
| 354 | initrd_filename, cpu_model, BOARD_EB_MPCORE); |
| 355 | } |
| 356 | |
| 357 | static void realview_pb_a8_init(ram_addr_t ram_size, |
| 358 | const char *boot_device, |
| 359 | const char *kernel_filename, const char *kernel_cmdline, |
| 360 | const char *initrd_filename, const char *cpu_model) |
| 361 | { |
| 362 | if (!cpu_model) { |
| 363 | cpu_model = "cortex-a8"; |
| 364 | } |
| 365 | realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline, |
| 366 | initrd_filename, cpu_model, BOARD_PB_A8); |
| 367 | } |
| 368 | |
| 369 | static void realview_pbx_a9_init(ram_addr_t ram_size, |
| 370 | const char *boot_device, |
| 371 | const char *kernel_filename, const char *kernel_cmdline, |
| 372 | const char *initrd_filename, const char *cpu_model) |
| 373 | { |
| 374 | if (!cpu_model) { |
| 375 | cpu_model = "cortex-a9"; |
| 376 | } |
| 377 | realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline, |
| 378 | initrd_filename, cpu_model, BOARD_PBX_A9); |
| 379 | } |
| 380 | |
| 381 | static QEMUMachine realview_eb_machine = { |
| 382 | .name = "realview-eb", |
| 383 | .desc = "ARM RealView Emulation Baseboard (ARM926EJ-S)", |
| 384 | .init = realview_eb_init, |
| 385 | .use_scsi = 1, |
| 386 | }; |
| 387 | |
| 388 | static QEMUMachine realview_eb_mpcore_machine = { |
| 389 | .name = "realview-eb-mpcore", |
| 390 | .desc = "ARM RealView Emulation Baseboard (ARM11MPCore)", |
| 391 | .init = realview_eb_mpcore_init, |
| 392 | .use_scsi = 1, |
| 393 | .max_cpus = 4, |
| 394 | }; |
| 395 | |
| 396 | static QEMUMachine realview_pb_a8_machine = { |
| 397 | .name = "realview-pb-a8", |
| 398 | .desc = "ARM RealView Platform Baseboard for Cortex-A8", |
| 399 | .init = realview_pb_a8_init, |
| 400 | }; |
| 401 | |
| 402 | static QEMUMachine realview_pbx_a9_machine = { |
| 403 | .name = "realview-pbx-a9", |
| 404 | .desc = "ARM RealView Platform Baseboard Explore for Cortex-A9", |
| 405 | .init = realview_pbx_a9_init, |
| 406 | .use_scsi = 1, |
| 407 | .max_cpus = 4, |
| 408 | }; |
| 409 | |
| 410 | static void realview_machine_init(void) |
| 411 | { |
| 412 | qemu_register_machine(&realview_eb_machine); |
| 413 | qemu_register_machine(&realview_eb_mpcore_machine); |
| 414 | qemu_register_machine(&realview_pb_a8_machine); |
| 415 | qemu_register_machine(&realview_pbx_a9_machine); |
| 416 | } |
| 417 | |
| 418 | machine_init(realview_machine_init)static void __attribute__((constructor)) do_qemu_init_realview_machine_init (void) { register_module_init(realview_machine_init, MODULE_INIT_MACHINE ); }; |