ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 1 | /* |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 2 | * ARM RealView Baseboard System emulation. |
| 3 | * |
pbrook | a1bb27b | 2007-04-06 16:49:48 +0000 | [diff] [blame] | 4 | * Copyright (c) 2006-2007 CodeSourcery. |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 5 | * Written by Paul Brook |
| 6 | * |
Matthew Fernandez | 8e31bf3 | 2011-06-26 12:21:35 +1000 | [diff] [blame] | 7 | * This code is licensed under the GPL. |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 8 | */ |
| 9 | |
Paul Brook | 2e9bdce | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 10 | #include "sysbus.h" |
pbrook | 87ecb68 | 2007-11-17 17:14:51 +0000 | [diff] [blame] | 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" |
Oskar Andero | d1157ca | 2012-04-20 15:38:52 +0000 | [diff] [blame] | 18 | #include "i2c.h" |
Blue Swirl | 2446333 | 2010-08-24 15:22:24 +0000 | [diff] [blame] | 19 | #include "blockdev.h" |
Avi Kivity | 35e8782 | 2011-10-02 17:04:26 +0200 | [diff] [blame] | 20 | #include "exec-memory.h" |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 21 | |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 22 | #define SMP_BOOT_ADDR 0xe0000000 |
Evgeny Voevodin | 078758d | 2012-01-13 20:52:40 +0000 | [diff] [blame] | 23 | #define SMP_BOOTREG_ADDR 0x10000030 |
Paul Brook | eee4850 | 2009-11-20 00:45:54 +0000 | [diff] [blame] | 24 | |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 25 | /* Board init. */ |
| 26 | |
balrog | f93eb9f | 2008-04-14 20:27:51 +0000 | [diff] [blame] | 27 | static struct arm_boot_info realview_binfo = { |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 28 | .smp_loader_start = SMP_BOOT_ADDR, |
Evgeny Voevodin | 078758d | 2012-01-13 20:52:40 +0000 | [diff] [blame] | 29 | .smp_bootreg_addr = SMP_BOOTREG_ADDR, |
balrog | f93eb9f | 2008-04-14 20:27:51 +0000 | [diff] [blame] | 30 | }; |
| 31 | |
Paul Brook | f7c7032 | 2009-11-19 16:45:21 +0000 | [diff] [blame] | 32 | /* The following two lists must be consistent. */ |
Paul Brook | c988bfa | 2009-11-13 04:31:22 +0000 | [diff] [blame] | 33 | enum realview_board_type { |
| 34 | BOARD_EB, |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 35 | BOARD_EB_MPCORE, |
Paul Brook | f7c7032 | 2009-11-19 16:45:21 +0000 | [diff] [blame] | 36 | BOARD_PB_A8, |
| 37 | BOARD_PBX_A9, |
| 38 | }; |
| 39 | |
Blue Swirl | d05ac8f | 2009-12-04 20:44:44 +0000 | [diff] [blame] | 40 | static const int realview_board_id[] = { |
Paul Brook | f7c7032 | 2009-11-19 16:45:21 +0000 | [diff] [blame] | 41 | 0x33b, |
| 42 | 0x33b, |
| 43 | 0x769, |
| 44 | 0x76d |
Paul Brook | c988bfa | 2009-11-13 04:31:22 +0000 | [diff] [blame] | 45 | }; |
| 46 | |
Anthony Liguori | c227f09 | 2009-10-01 16:12:16 -0500 | [diff] [blame] | 47 | static void realview_init(ram_addr_t ram_size, |
aliguori | 3023f332 | 2009-01-16 19:04:14 +0000 | [diff] [blame] | 48 | const char *boot_device, |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 49 | const char *kernel_filename, const char *kernel_cmdline, |
Paul Brook | c988bfa | 2009-11-13 04:31:22 +0000 | [diff] [blame] | 50 | const char *initrd_filename, const char *cpu_model, |
| 51 | enum realview_board_type board_type) |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 52 | { |
Andreas Färber | 9077f01 | 2012-05-14 03:50:56 +0200 | [diff] [blame] | 53 | ARMCPU *cpu = NULL; |
| 54 | CPUARMState *env; |
Avi Kivity | 35e8782 | 2011-10-02 17:04:26 +0200 | [diff] [blame] | 55 | MemoryRegion *sysmem = get_system_memory(); |
| 56 | MemoryRegion *ram_lo = g_new(MemoryRegion, 1); |
| 57 | MemoryRegion *ram_hi = g_new(MemoryRegion, 1); |
| 58 | MemoryRegion *ram_alias = g_new(MemoryRegion, 1); |
| 59 | MemoryRegion *ram_hack = g_new(MemoryRegion, 1); |
Peter Maydell | 03a0e94 | 2011-10-28 10:55:38 +0100 | [diff] [blame] | 60 | DeviceState *dev, *sysctl, *gpio2, *pl041; |
Paul Brook | c988bfa | 2009-11-13 04:31:22 +0000 | [diff] [blame] | 61 | SysBusDevice *busdev; |
Paul Brook | fe7e875 | 2009-05-14 22:35:08 +0100 | [diff] [blame] | 62 | qemu_irq *irqp; |
| 63 | qemu_irq pic[64]; |
Peter Maydell | 26883c6 | 2011-02-21 20:57:53 +0000 | [diff] [blame] | 64 | qemu_irq mmc_irq[2]; |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 65 | PCIBus *pci_bus; |
| 66 | NICInfo *nd; |
Paul Brook | eee4850 | 2009-11-20 00:45:54 +0000 | [diff] [blame] | 67 | i2c_bus *i2c; |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 68 | int n; |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 69 | int done_nic = 0; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 70 | qemu_irq cpu_irq[4]; |
Paul Brook | f7c7032 | 2009-11-19 16:45:21 +0000 | [diff] [blame] | 71 | int is_mpcore = 0; |
| 72 | int is_pb = 0; |
Paul Brook | 26e92f6 | 2009-11-13 03:30:33 +0000 | [diff] [blame] | 73 | uint32_t proc_id = 0; |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 74 | uint32_t sys_id; |
| 75 | ram_addr_t low_ram_size; |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 76 | |
Paul Brook | f7c7032 | 2009-11-19 16:45:21 +0000 | [diff] [blame] | 77 | switch (board_type) { |
| 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 | } |
Paul Brook | c988bfa | 2009-11-13 04:31:22 +0000 | [diff] [blame] | 91 | for (n = 0; n < smp_cpus; n++) { |
Andreas Färber | 9077f01 | 2012-05-14 03:50:56 +0200 | [diff] [blame] | 92 | cpu = cpu_arm_init(cpu_model); |
| 93 | if (!cpu) { |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 94 | fprintf(stderr, "Unable to find CPU definition\n"); |
| 95 | exit(1); |
| 96 | } |
Andreas Färber | 4bd7466 | 2012-05-14 04:21:52 +0200 | [diff] [blame] | 97 | irqp = arm_pic_init_cpu(cpu); |
Paul Brook | fe7e875 | 2009-05-14 22:35:08 +0100 | [diff] [blame] | 98 | cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ]; |
bellard | aaed909 | 2007-11-10 15:15:54 +0000 | [diff] [blame] | 99 | } |
Andreas Färber | 9077f01 | 2012-05-14 03:50:56 +0200 | [diff] [blame] | 100 | env = &cpu->env; |
Paul Brook | 26e92f6 | 2009-11-13 03:30:33 +0000 | [diff] [blame] | 101 | if (arm_feature(env, ARM_FEATURE_V7)) { |
Paul Brook | f7c7032 | 2009-11-19 16:45:21 +0000 | [diff] [blame] | 102 | if (is_mpcore) { |
| 103 | proc_id = 0x0c000000; |
| 104 | } else { |
| 105 | proc_id = 0x0e000000; |
| 106 | } |
Paul Brook | 26e92f6 | 2009-11-13 03:30:33 +0000 | [diff] [blame] | 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 | } |
bellard | aaed909 | 2007-11-10 15:15:54 +0000 | [diff] [blame] | 114 | |
Paul Brook | 21a8894 | 2009-12-21 20:19:12 +0000 | [diff] [blame] | 115 | if (is_pb && ram_size > 0x20000000) { |
| 116 | /* Core tile RAM. */ |
| 117 | low_ram_size = ram_size - 0x20000000; |
| 118 | ram_size = 0x20000000; |
Avi Kivity | c5705a7 | 2011-12-20 15:59:12 +0200 | [diff] [blame] | 119 | memory_region_init_ram(ram_lo, "realview.lowmem", low_ram_size); |
| 120 | vmstate_register_ram_global(ram_lo); |
Avi Kivity | 35e8782 | 2011-10-02 17:04:26 +0200 | [diff] [blame] | 121 | memory_region_add_subregion(sysmem, 0x20000000, ram_lo); |
Paul Brook | 21a8894 | 2009-12-21 20:19:12 +0000 | [diff] [blame] | 122 | } |
| 123 | |
Avi Kivity | c5705a7 | 2011-12-20 15:59:12 +0200 | [diff] [blame] | 124 | memory_region_init_ram(ram_hi, "realview.highmem", ram_size); |
| 125 | vmstate_register_ram_global(ram_hi); |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 126 | low_ram_size = ram_size; |
| 127 | if (low_ram_size > 0x10000000) |
| 128 | low_ram_size = 0x10000000; |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 129 | /* SDRAM at address zero. */ |
Avi Kivity | 35e8782 | 2011-10-02 17:04:26 +0200 | [diff] [blame] | 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); |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 133 | if (is_pb) { |
| 134 | /* And again at a high address. */ |
Avi Kivity | 35e8782 | 2011-10-02 17:04:26 +0200 | [diff] [blame] | 135 | memory_region_add_subregion(sysmem, 0x70000000, ram_hi); |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 136 | } else { |
| 137 | ram_size = low_ram_size; |
| 138 | } |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 139 | |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 140 | sys_id = is_pb ? 0x01780500 : 0xc1400400; |
Peter Maydell | 26883c6 | 2011-02-21 20:57:53 +0000 | [diff] [blame] | 141 | sysctl = qdev_create(NULL, "realview_sysctl"); |
| 142 | qdev_prop_set_uint32(sysctl, "sys_id", sys_id); |
Peter Maydell | 26883c6 | 2011-02-21 20:57:53 +0000 | [diff] [blame] | 143 | qdev_prop_set_uint32(sysctl, "proc_id", proc_id); |
Peter Maydell | 7a65c8c | 2012-02-09 06:11:16 +0000 | [diff] [blame] | 144 | qdev_init_nofail(sysctl); |
Peter Maydell | 26883c6 | 2011-02-21 20:57:53 +0000 | [diff] [blame] | 145 | sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, 0x10000000); |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 146 | |
Paul Brook | c988bfa | 2009-11-13 04:31:22 +0000 | [diff] [blame] | 147 | if (is_mpcore) { |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 148 | hwaddr periphbase; |
Paul Brook | f7c7032 | 2009-11-19 16:45:21 +0000 | [diff] [blame] | 149 | dev = qdev_create(NULL, is_pb ? "a9mpcore_priv": "realview_mpcore"); |
Paul Brook | c988bfa | 2009-11-13 04:31:22 +0000 | [diff] [blame] | 150 | qdev_prop_set_uint32(dev, "num-cpu", smp_cpus); |
| 151 | qdev_init_nofail(dev); |
| 152 | busdev = sysbus_from_qdev(dev); |
Paul Brook | f7c7032 | 2009-11-19 16:45:21 +0000 | [diff] [blame] | 153 | if (is_pb) { |
Peter Maydell | 96eacf6 | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 154 | periphbase = 0x1f000000; |
Paul Brook | f7c7032 | 2009-11-19 16:45:21 +0000 | [diff] [blame] | 155 | } else { |
Peter Maydell | 96eacf6 | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 156 | periphbase = 0x10100000; |
Paul Brook | f7c7032 | 2009-11-19 16:45:21 +0000 | [diff] [blame] | 157 | } |
Peter Maydell | 96eacf6 | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 158 | sysbus_mmio_map(busdev, 0, periphbase); |
Paul Brook | c988bfa | 2009-11-13 04:31:22 +0000 | [diff] [blame] | 159 | for (n = 0; n < smp_cpus; n++) { |
| 160 | sysbus_connect_irq(busdev, n, cpu_irq[n]); |
| 161 | } |
Peter Maydell | 96eacf6 | 2012-02-16 09:56:09 +0000 | [diff] [blame] | 162 | sysbus_create_varargs("l2x0", periphbase + 0x2000, NULL); |
| 163 | /* Both A9 and 11MPCore put the GIC CPU i/f at base + 0x100 */ |
| 164 | realview_binfo.gic_cpu_if_addr = periphbase + 0x100; |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 165 | } else { |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 166 | uint32_t gic_addr = is_pb ? 0x1e000000 : 0x10040000; |
| 167 | /* For now just create the nIRQ GIC, and ignore the others. */ |
| 168 | dev = sysbus_create_simple("realview_gic", gic_addr, cpu_irq[0]); |
Paul Brook | fe7e875 | 2009-05-14 22:35:08 +0100 | [diff] [blame] | 169 | } |
| 170 | for (n = 0; n < 64; n++) { |
Paul Brook | 067a3dd | 2009-05-26 14:56:11 +0100 | [diff] [blame] | 171 | pic[n] = qdev_get_gpio_in(dev, n); |
pbrook | 9ee6e8b | 2007-11-11 00:04:49 +0000 | [diff] [blame] | 172 | } |
| 173 | |
Peter Maydell | 03a0e94 | 2011-10-28 10:55:38 +0100 | [diff] [blame] | 174 | pl041 = qdev_create(NULL, "pl041"); |
| 175 | qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512); |
| 176 | qdev_init_nofail(pl041); |
| 177 | sysbus_mmio_map(sysbus_from_qdev(pl041), 0, 0x10004000); |
| 178 | sysbus_connect_irq(sysbus_from_qdev(pl041), 0, pic[19]); |
| 179 | |
Paul Brook | 86394e9 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 180 | sysbus_create_simple("pl050_keyboard", 0x10006000, pic[20]); |
| 181 | sysbus_create_simple("pl050_mouse", 0x10007000, pic[21]); |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 182 | |
Paul Brook | a7d518a | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 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]); |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 187 | |
| 188 | /* DMA controller is optional, apparently. */ |
Paul Brook | b4496b1 | 2009-05-14 22:35:08 +0100 | [diff] [blame] | 189 | sysbus_create_simple("pl081", 0x10030000, pic[24]); |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 190 | |
Paul Brook | 6a824ec | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 191 | sysbus_create_simple("sp804", 0x10011000, pic[4]); |
| 192 | sysbus_create_simple("sp804", 0x10012000, pic[5]); |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 193 | |
Peter Maydell | 26883c6 | 2011-02-21 20:57:53 +0000 | [diff] [blame] | 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 | |
Peter Maydell | acb9b72 | 2011-07-22 15:36:54 +0000 | [diff] [blame] | 198 | sysbus_create_simple("pl111", 0x10020000, pic[23]); |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 199 | |
Peter Maydell | 26883c6 | 2011-02-21 20:57:53 +0000 | [diff] [blame] | 200 | dev = sysbus_create_varargs("pl181", 0x10005000, pic[17], pic[18], NULL); |
| 201 | /* Wire up MMC card detect and read-only signals. These have |
| 202 | * to go to both the PL061 GPIO and the sysctl register. |
| 203 | * Note that the PL181 orders these lines (readonly,inserted) |
| 204 | * and the PL061 has them the other way about. Also the card |
| 205 | * detect line is inverted. |
| 206 | */ |
| 207 | mmc_irq[0] = qemu_irq_split( |
| 208 | qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT), |
| 209 | qdev_get_gpio_in(gpio2, 1)); |
| 210 | mmc_irq[1] = qemu_irq_split( |
| 211 | qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN), |
| 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]); |
pbrook | a1bb27b | 2007-04-06 16:49:48 +0000 | [diff] [blame] | 215 | |
Paul Brook | a63bdb3 | 2009-05-14 22:35:07 +0100 | [diff] [blame] | 216 | sysbus_create_simple("pl031", 0x10017000, pic[10]); |
pbrook | 7e1543c | 2007-06-30 17:32:17 +0000 | [diff] [blame] | 217 | |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 218 | if (!is_pb) { |
Peter Maydell | 7d6e771 | 2011-09-01 18:36:53 +0100 | [diff] [blame] | 219 | dev = qdev_create(NULL, "realview_pci"); |
| 220 | busdev = sysbus_from_qdev(dev); |
| 221 | qdev_init_nofail(dev); |
| 222 | sysbus_mmio_map(busdev, 0, 0x61000000); /* PCI self-config */ |
| 223 | sysbus_mmio_map(busdev, 1, 0x62000000); /* PCI config */ |
| 224 | sysbus_mmio_map(busdev, 2, 0x63000000); /* PCI I/O */ |
| 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]); |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 229 | pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci"); |
| 230 | if (usb_enabled) { |
Gerd Hoffmann | afb9a60 | 2012-03-07 15:06:32 +0100 | [diff] [blame] | 231 | pci_create_simple(pci_bus, -1, "pci-ohci"); |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 232 | } |
| 233 | n = drive_get_max_bus(IF_SCSI); |
| 234 | while (n >= 0) { |
| 235 | pci_create_simple(pci_bus, -1, "lsi53c895a"); |
| 236 | n--; |
| 237 | } |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 238 | } |
| 239 | for(n = 0; n < nb_nics; n++) { |
| 240 | nd = &nd_table[n]; |
aliguori | 0ae18ce | 2009-01-13 19:39:36 +0000 | [diff] [blame] | 241 | |
Peter Maydell | e6b3c8c | 2011-03-22 18:21:58 +0000 | [diff] [blame] | 242 | if (!done_nic && (!nd->model || |
| 243 | strcmp(nd->model, is_pb ? "lan9118" : "smc91c111") == 0)) { |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 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; |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 250 | } else { |
Markus Armbruster | 07caea3 | 2009-09-25 03:53:51 +0200 | [diff] [blame] | 251 | pci_nic_init_nofail(nd, "rtl8139", NULL); |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 252 | } |
| 253 | } |
| 254 | |
Oskar Andero | d1157ca | 2012-04-20 15:38:52 +0000 | [diff] [blame] | 255 | dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL); |
Paul Brook | eee4850 | 2009-11-20 00:45:54 +0000 | [diff] [blame] | 256 | i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c"); |
| 257 | i2c_create_slave(i2c, "ds1338", 0x68); |
| 258 | |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 259 | /* Memory map for RealView Emulation Baseboard: */ |
| 260 | /* 0x10000000 System registers. */ |
| 261 | /* 0x10001000 System controller. */ |
Paul Brook | eee4850 | 2009-11-20 00:45:54 +0000 | [diff] [blame] | 262 | /* 0x10002000 Two-Wire Serial Bus. */ |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 263 | /* 0x10003000 Reserved. */ |
| 264 | /* 0x10004000 AACI. */ |
| 265 | /* 0x10005000 MCI. */ |
| 266 | /* 0x10006000 KMI0. */ |
| 267 | /* 0x10007000 KMI1. */ |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 268 | /* 0x10008000 Character LCD. (EB) */ |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 269 | /* 0x10009000 UART0. */ |
| 270 | /* 0x1000a000 UART1. */ |
| 271 | /* 0x1000b000 UART2. */ |
| 272 | /* 0x1000c000 UART3. */ |
| 273 | /* 0x1000d000 SSPI. */ |
| 274 | /* 0x1000e000 SCI. */ |
| 275 | /* 0x1000f000 Reserved. */ |
| 276 | /* 0x10010000 Watchdog. */ |
| 277 | /* 0x10011000 Timer 0+1. */ |
| 278 | /* 0x10012000 Timer 2+3. */ |
| 279 | /* 0x10013000 GPIO 0. */ |
| 280 | /* 0x10014000 GPIO 1. */ |
| 281 | /* 0x10015000 GPIO 2. */ |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 282 | /* 0x10002000 Two-Wire Serial Bus - DVI. (PB) */ |
pbrook | 7e1543c | 2007-06-30 17:32:17 +0000 | [diff] [blame] | 283 | /* 0x10017000 RTC. */ |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 284 | /* 0x10018000 DMC. */ |
| 285 | /* 0x10019000 PCI controller config. */ |
| 286 | /* 0x10020000 CLCD. */ |
| 287 | /* 0x10030000 DMA Controller. */ |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 288 | /* 0x10040000 GIC1. (EB) */ |
| 289 | /* 0x10050000 GIC2. (EB) */ |
| 290 | /* 0x10060000 GIC3. (EB) */ |
| 291 | /* 0x10070000 GIC4. (EB) */ |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 292 | /* 0x10080000 SMC. */ |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 293 | /* 0x1e000000 GIC1. (PB) */ |
| 294 | /* 0x1e001000 GIC2. (PB) */ |
| 295 | /* 0x1e002000 GIC3. (PB) */ |
| 296 | /* 0x1e003000 GIC4. (PB) */ |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 297 | /* 0x40000000 NOR flash. */ |
| 298 | /* 0x44000000 DoC flash. */ |
| 299 | /* 0x48000000 SRAM. */ |
| 300 | /* 0x4c000000 Configuration flash. */ |
| 301 | /* 0x4e000000 Ethernet. */ |
| 302 | /* 0x4f000000 USB. */ |
| 303 | /* 0x50000000 PISMO. */ |
| 304 | /* 0x54000000 PISMO. */ |
| 305 | /* 0x58000000 PISMO. */ |
| 306 | /* 0x5c000000 PISMO. */ |
| 307 | /* 0x60000000 PCI. */ |
| 308 | /* 0x61000000 PCI Self Config. */ |
| 309 | /* 0x62000000 PCI Config. */ |
| 310 | /* 0x63000000 PCI IO. */ |
| 311 | /* 0x64000000 PCI mem 0. */ |
| 312 | /* 0x68000000 PCI mem 1. */ |
| 313 | /* 0x6c000000 PCI mem 2. */ |
| 314 | |
pbrook | 7ffab4d | 2009-04-09 17:15:18 +0000 | [diff] [blame] | 315 | /* ??? Hack to map an additional page of ram for the secondary CPU |
| 316 | startup code. I guess this works on real hardware because the |
| 317 | BootROM happens to be in ROM/flash or in memory that isn't clobbered |
| 318 | until after Linux boots the secondary CPUs. */ |
Avi Kivity | c5705a7 | 2011-12-20 15:59:12 +0200 | [diff] [blame] | 319 | memory_region_init_ram(ram_hack, "realview.hack", 0x1000); |
| 320 | vmstate_register_ram_global(ram_hack); |
Avi Kivity | 35e8782 | 2011-10-02 17:04:26 +0200 | [diff] [blame] | 321 | memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack); |
pbrook | 7ffab4d | 2009-04-09 17:15:18 +0000 | [diff] [blame] | 322 | |
balrog | f93eb9f | 2008-04-14 20:27:51 +0000 | [diff] [blame] | 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; |
Paul Brook | c988bfa | 2009-11-13 04:31:22 +0000 | [diff] [blame] | 327 | realview_binfo.nb_cpus = smp_cpus; |
Paul Brook | f7c7032 | 2009-11-19 16:45:21 +0000 | [diff] [blame] | 328 | realview_binfo.board_id = realview_board_id[board_type]; |
Paul Brook | 21a8894 | 2009-12-21 20:19:12 +0000 | [diff] [blame] | 329 | realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0); |
Andreas Färber | 3aaa8df | 2012-05-14 02:39:57 +0200 | [diff] [blame] | 330 | arm_load_kernel(arm_env_get_cpu(first_cpu), &realview_binfo); |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 331 | } |
| 332 | |
Eduardo Habkost | 5f072e1 | 2012-10-15 17:22:02 -0300 | [diff] [blame] | 333 | static void realview_eb_init(QEMUMachineInitArgs *args) |
Paul Brook | c988bfa | 2009-11-13 04:31:22 +0000 | [diff] [blame] | 334 | { |
Eduardo Habkost | 5f072e1 | 2012-10-15 17:22:02 -0300 | [diff] [blame] | 335 | ram_addr_t ram_size = args->ram_size; |
| 336 | const char *cpu_model = args->cpu_model; |
| 337 | const char *kernel_filename = args->kernel_filename; |
| 338 | const char *kernel_cmdline = args->kernel_cmdline; |
| 339 | const char *initrd_filename = args->initrd_filename; |
| 340 | const char *boot_device = args->boot_device; |
Paul Brook | c988bfa | 2009-11-13 04:31:22 +0000 | [diff] [blame] | 341 | if (!cpu_model) { |
| 342 | cpu_model = "arm926"; |
| 343 | } |
| 344 | realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline, |
| 345 | initrd_filename, cpu_model, BOARD_EB); |
| 346 | } |
| 347 | |
Eduardo Habkost | 5f072e1 | 2012-10-15 17:22:02 -0300 | [diff] [blame] | 348 | static void realview_eb_mpcore_init(QEMUMachineInitArgs *args) |
Paul Brook | c988bfa | 2009-11-13 04:31:22 +0000 | [diff] [blame] | 349 | { |
Eduardo Habkost | 5f072e1 | 2012-10-15 17:22:02 -0300 | [diff] [blame] | 350 | ram_addr_t ram_size = args->ram_size; |
| 351 | const char *cpu_model = args->cpu_model; |
| 352 | const char *kernel_filename = args->kernel_filename; |
| 353 | const char *kernel_cmdline = args->kernel_cmdline; |
| 354 | const char *initrd_filename = args->initrd_filename; |
| 355 | const char *boot_device = args->boot_device; |
Paul Brook | c988bfa | 2009-11-13 04:31:22 +0000 | [diff] [blame] | 356 | if (!cpu_model) { |
| 357 | cpu_model = "arm11mpcore"; |
| 358 | } |
| 359 | realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline, |
| 360 | initrd_filename, cpu_model, BOARD_EB_MPCORE); |
| 361 | } |
| 362 | |
Eduardo Habkost | 5f072e1 | 2012-10-15 17:22:02 -0300 | [diff] [blame] | 363 | static void realview_pb_a8_init(QEMUMachineInitArgs *args) |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 364 | { |
Eduardo Habkost | 5f072e1 | 2012-10-15 17:22:02 -0300 | [diff] [blame] | 365 | ram_addr_t ram_size = args->ram_size; |
| 366 | const char *cpu_model = args->cpu_model; |
| 367 | const char *kernel_filename = args->kernel_filename; |
| 368 | const char *kernel_cmdline = args->kernel_cmdline; |
| 369 | const char *initrd_filename = args->initrd_filename; |
| 370 | const char *boot_device = args->boot_device; |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 371 | if (!cpu_model) { |
| 372 | cpu_model = "cortex-a8"; |
| 373 | } |
| 374 | realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline, |
| 375 | initrd_filename, cpu_model, BOARD_PB_A8); |
| 376 | } |
| 377 | |
Eduardo Habkost | 5f072e1 | 2012-10-15 17:22:02 -0300 | [diff] [blame] | 378 | static void realview_pbx_a9_init(QEMUMachineInitArgs *args) |
Paul Brook | f7c7032 | 2009-11-19 16:45:21 +0000 | [diff] [blame] | 379 | { |
Eduardo Habkost | 5f072e1 | 2012-10-15 17:22:02 -0300 | [diff] [blame] | 380 | ram_addr_t ram_size = args->ram_size; |
| 381 | const char *cpu_model = args->cpu_model; |
| 382 | const char *kernel_filename = args->kernel_filename; |
| 383 | const char *kernel_cmdline = args->kernel_cmdline; |
| 384 | const char *initrd_filename = args->initrd_filename; |
| 385 | const char *boot_device = args->boot_device; |
Paul Brook | f7c7032 | 2009-11-19 16:45:21 +0000 | [diff] [blame] | 386 | if (!cpu_model) { |
| 387 | cpu_model = "cortex-a9"; |
| 388 | } |
| 389 | realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline, |
| 390 | initrd_filename, cpu_model, BOARD_PBX_A9); |
| 391 | } |
| 392 | |
Paul Brook | c988bfa | 2009-11-13 04:31:22 +0000 | [diff] [blame] | 393 | static QEMUMachine realview_eb_machine = { |
| 394 | .name = "realview-eb", |
blueswir1 | c9b1ae2 | 2008-09-28 18:55:17 +0000 | [diff] [blame] | 395 | .desc = "ARM RealView Emulation Baseboard (ARM926EJ-S)", |
Paul Brook | c988bfa | 2009-11-13 04:31:22 +0000 | [diff] [blame] | 396 | .init = realview_eb_init, |
blueswir1 | c9b1ae2 | 2008-09-28 18:55:17 +0000 | [diff] [blame] | 397 | .use_scsi = 1, |
pbrook | e69954b | 2006-09-23 17:40:58 +0000 | [diff] [blame] | 398 | }; |
Anthony Liguori | f80f9ec | 2009-05-20 18:38:09 -0500 | [diff] [blame] | 399 | |
Paul Brook | c988bfa | 2009-11-13 04:31:22 +0000 | [diff] [blame] | 400 | static QEMUMachine realview_eb_mpcore_machine = { |
| 401 | .name = "realview-eb-mpcore", |
| 402 | .desc = "ARM RealView Emulation Baseboard (ARM11MPCore)", |
| 403 | .init = realview_eb_mpcore_init, |
| 404 | .use_scsi = 1, |
| 405 | .max_cpus = 4, |
| 406 | }; |
| 407 | |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 408 | static QEMUMachine realview_pb_a8_machine = { |
| 409 | .name = "realview-pb-a8", |
| 410 | .desc = "ARM RealView Platform Baseboard for Cortex-A8", |
| 411 | .init = realview_pb_a8_init, |
Paul Brook | f7c7032 | 2009-11-19 16:45:21 +0000 | [diff] [blame] | 412 | }; |
| 413 | |
| 414 | static QEMUMachine realview_pbx_a9_machine = { |
| 415 | .name = "realview-pbx-a9", |
| 416 | .desc = "ARM RealView Platform Baseboard Explore for Cortex-A9", |
| 417 | .init = realview_pbx_a9_init, |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 418 | .use_scsi = 1, |
Paul Brook | f7c7032 | 2009-11-19 16:45:21 +0000 | [diff] [blame] | 419 | .max_cpus = 4, |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 420 | }; |
| 421 | |
Anthony Liguori | f80f9ec | 2009-05-20 18:38:09 -0500 | [diff] [blame] | 422 | static void realview_machine_init(void) |
| 423 | { |
Paul Brook | c988bfa | 2009-11-13 04:31:22 +0000 | [diff] [blame] | 424 | qemu_register_machine(&realview_eb_machine); |
| 425 | qemu_register_machine(&realview_eb_mpcore_machine); |
Paul Brook | 0ef849d | 2009-11-16 17:06:43 +0000 | [diff] [blame] | 426 | qemu_register_machine(&realview_pb_a8_machine); |
Paul Brook | f7c7032 | 2009-11-19 16:45:21 +0000 | [diff] [blame] | 427 | qemu_register_machine(&realview_pbx_a9_machine); |
Anthony Liguori | f80f9ec | 2009-05-20 18:38:09 -0500 | [diff] [blame] | 428 | } |
| 429 | |
| 430 | machine_init(realview_machine_init); |