Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Calxeda Highbank SoC emulation |
| 3 | * |
| 4 | * Copyright (c) 2010-2012 Calxeda |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, |
| 8 | * version 2 or later, as published by the Free Software Foundation. |
| 9 | * |
| 10 | * This program is distributed in the hope it will be useful, but WITHOUT |
| 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 13 | * more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License along with |
| 16 | * this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * |
| 18 | */ |
| 19 | |
Paolo Bonzini | 83c9f4c | 2013-02-04 15:40:22 +0100 | [diff] [blame] | 20 | #include "hw/sysbus.h" |
Peter Maydell | bd2be15 | 2013-04-09 15:26:55 +0100 | [diff] [blame] | 21 | #include "hw/arm/arm.h" |
| 22 | #include "hw/devices.h" |
Paolo Bonzini | 83c9f4c | 2013-02-04 15:40:22 +0100 | [diff] [blame] | 23 | #include "hw/loader.h" |
Paolo Bonzini | 1422e32 | 2012-10-24 08:43:34 +0200 | [diff] [blame] | 24 | #include "net/net.h" |
Paolo Bonzini | 9c17d61 | 2012-12-17 18:20:04 +0100 | [diff] [blame] | 25 | #include "sysemu/sysemu.h" |
Paolo Bonzini | 83c9f4c | 2013-02-04 15:40:22 +0100 | [diff] [blame] | 26 | #include "hw/boards.h" |
Paolo Bonzini | 9c17d61 | 2012-12-17 18:20:04 +0100 | [diff] [blame] | 27 | #include "sysemu/blockdev.h" |
Paolo Bonzini | 022c62c | 2012-12-17 18:19:49 +0100 | [diff] [blame] | 28 | #include "exec/address-spaces.h" |
Peter Crosthwaite | f282f29 | 2013-12-17 19:42:28 +0000 | [diff] [blame] | 29 | #include "qemu/error-report.h" |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 30 | |
Peter Crosthwaite | e2cddee | 2013-12-17 19:42:29 +0000 | [diff] [blame] | 31 | #define SMP_BOOT_ADDR 0x100 |
| 32 | #define SMP_BOOT_REG 0x40 |
| 33 | #define MPCORE_PERIPHBASE 0xfff10000 |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 34 | |
Peter Crosthwaite | e2cddee | 2013-12-17 19:42:29 +0000 | [diff] [blame] | 35 | #define NIRQ_GIC 160 |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 36 | |
| 37 | /* Board init. */ |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 38 | |
Andreas Färber | 9543b0c | 2012-05-14 00:08:10 +0200 | [diff] [blame] | 39 | static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info) |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 40 | { |
| 41 | int n; |
| 42 | uint32_t smpboot[] = { |
| 43 | 0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 - read current core id */ |
| 44 | 0xe210000f, /* ands r0, r0, #0x0f */ |
| 45 | 0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */ |
| 46 | 0xe0830200, /* add r0, r3, r0, lsl #4 */ |
Peter Maydell | bf471f7 | 2012-12-11 11:30:37 +0000 | [diff] [blame] | 47 | 0xe59f2024, /* ldr r2, privbase */ |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 48 | 0xe3a01001, /* mov r1, #1 */ |
Peter Maydell | bf471f7 | 2012-12-11 11:30:37 +0000 | [diff] [blame] | 49 | 0xe5821100, /* str r1, [r2, #256] - set GICC_CTLR.Enable */ |
| 50 | 0xe3a010ff, /* mov r1, #0xff */ |
| 51 | 0xe5821104, /* str r1, [r2, #260] - set GICC_PMR.Priority to 0xff */ |
| 52 | 0xf57ff04f, /* dsb */ |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 53 | 0xe320f003, /* wfi */ |
| 54 | 0xe5901000, /* ldr r1, [r0] */ |
| 55 | 0xe1110001, /* tst r1, r1 */ |
| 56 | 0x0afffffb, /* beq <wfi> */ |
| 57 | 0xe12fff11, /* bx r1 */ |
Peter Crosthwaite | e2cddee | 2013-12-17 19:42:29 +0000 | [diff] [blame] | 58 | MPCORE_PERIPHBASE /* privbase: MPCore peripheral base address. */ |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 59 | }; |
| 60 | for (n = 0; n < ARRAY_SIZE(smpboot); n++) { |
| 61 | smpboot[n] = tswap32(smpboot[n]); |
| 62 | } |
| 63 | rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR); |
| 64 | } |
| 65 | |
Andreas Färber | 5d30932 | 2012-05-14 01:05:40 +0200 | [diff] [blame] | 66 | static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info) |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 67 | { |
Andreas Färber | 5d30932 | 2012-05-14 01:05:40 +0200 | [diff] [blame] | 68 | CPUARMState *env = &cpu->env; |
| 69 | |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 70 | switch (info->nb_cpus) { |
| 71 | case 4: |
Edgar E. Iglesias | 2198a12 | 2013-11-28 10:13:41 +0100 | [diff] [blame] | 72 | stl_phys_notdirty(&address_space_memory, SMP_BOOT_REG + 0x30, 0); |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 73 | case 3: |
Edgar E. Iglesias | 2198a12 | 2013-11-28 10:13:41 +0100 | [diff] [blame] | 74 | stl_phys_notdirty(&address_space_memory, SMP_BOOT_REG + 0x20, 0); |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 75 | case 2: |
Edgar E. Iglesias | 2198a12 | 2013-11-28 10:13:41 +0100 | [diff] [blame] | 76 | stl_phys_notdirty(&address_space_memory, SMP_BOOT_REG + 0x10, 0); |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 77 | env->regs[15] = SMP_BOOT_ADDR; |
| 78 | break; |
| 79 | default: |
| 80 | break; |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | #define NUM_REGS 0x200 |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 85 | static void hb_regs_write(void *opaque, hwaddr offset, |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 86 | uint64_t value, unsigned size) |
| 87 | { |
| 88 | uint32_t *regs = opaque; |
| 89 | |
| 90 | if (offset == 0xf00) { |
| 91 | if (value == 1 || value == 2) { |
| 92 | qemu_system_reset_request(); |
| 93 | } else if (value == 3) { |
| 94 | qemu_system_shutdown_request(); |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | regs[offset/4] = value; |
| 99 | } |
| 100 | |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 101 | static uint64_t hb_regs_read(void *opaque, hwaddr offset, |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 102 | unsigned size) |
| 103 | { |
| 104 | uint32_t *regs = opaque; |
| 105 | uint32_t value = regs[offset/4]; |
| 106 | |
| 107 | if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) { |
| 108 | value |= 0x30000000; |
| 109 | } |
| 110 | |
| 111 | return value; |
| 112 | } |
| 113 | |
| 114 | static const MemoryRegionOps hb_mem_ops = { |
| 115 | .read = hb_regs_read, |
| 116 | .write = hb_regs_write, |
| 117 | .endianness = DEVICE_NATIVE_ENDIAN, |
| 118 | }; |
| 119 | |
Andreas Färber | 426533f | 2013-07-24 00:52:40 +0200 | [diff] [blame] | 120 | #define TYPE_HIGHBANK_REGISTERS "highbank-regs" |
| 121 | #define HIGHBANK_REGISTERS(obj) \ |
| 122 | OBJECT_CHECK(HighbankRegsState, (obj), TYPE_HIGHBANK_REGISTERS) |
| 123 | |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 124 | typedef struct { |
Andreas Färber | 426533f | 2013-07-24 00:52:40 +0200 | [diff] [blame] | 125 | /*< private >*/ |
| 126 | SysBusDevice parent_obj; |
| 127 | /*< public >*/ |
| 128 | |
Stefan Weil | 112f2ac | 2013-12-06 19:43:30 +0100 | [diff] [blame] | 129 | MemoryRegion iomem; |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 130 | uint32_t regs[NUM_REGS]; |
| 131 | } HighbankRegsState; |
| 132 | |
| 133 | static VMStateDescription vmstate_highbank_regs = { |
| 134 | .name = "highbank-regs", |
| 135 | .version_id = 0, |
| 136 | .minimum_version_id = 0, |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 137 | .fields = (VMStateField[]) { |
| 138 | VMSTATE_UINT32_ARRAY(regs, HighbankRegsState, NUM_REGS), |
| 139 | VMSTATE_END_OF_LIST(), |
| 140 | }, |
| 141 | }; |
| 142 | |
| 143 | static void highbank_regs_reset(DeviceState *dev) |
| 144 | { |
Andreas Färber | 426533f | 2013-07-24 00:52:40 +0200 | [diff] [blame] | 145 | HighbankRegsState *s = HIGHBANK_REGISTERS(dev); |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 146 | |
| 147 | s->regs[0x40] = 0x05F20121; |
| 148 | s->regs[0x41] = 0x2; |
| 149 | s->regs[0x42] = 0x05F30121; |
| 150 | s->regs[0x43] = 0x05F40121; |
| 151 | } |
| 152 | |
| 153 | static int highbank_regs_init(SysBusDevice *dev) |
| 154 | { |
Andreas Färber | 426533f | 2013-07-24 00:52:40 +0200 | [diff] [blame] | 155 | HighbankRegsState *s = HIGHBANK_REGISTERS(dev); |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 156 | |
Stefan Weil | 112f2ac | 2013-12-06 19:43:30 +0100 | [diff] [blame] | 157 | memory_region_init_io(&s->iomem, OBJECT(s), &hb_mem_ops, s->regs, |
Paolo Bonzini | 64bde0f | 2013-06-06 21:25:08 -0400 | [diff] [blame] | 158 | "highbank_regs", 0x1000); |
Stefan Weil | 112f2ac | 2013-12-06 19:43:30 +0100 | [diff] [blame] | 159 | sysbus_init_mmio(dev, &s->iomem); |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 160 | |
| 161 | return 0; |
| 162 | } |
| 163 | |
Anthony Liguori | 999e12b | 2012-01-24 13:12:29 -0600 | [diff] [blame] | 164 | static void highbank_regs_class_init(ObjectClass *klass, void *data) |
| 165 | { |
| 166 | SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); |
Anthony Liguori | 39bffca | 2011-12-07 21:34:16 -0600 | [diff] [blame] | 167 | DeviceClass *dc = DEVICE_CLASS(klass); |
Anthony Liguori | 999e12b | 2012-01-24 13:12:29 -0600 | [diff] [blame] | 168 | |
| 169 | sbc->init = highbank_regs_init; |
Anthony Liguori | 39bffca | 2011-12-07 21:34:16 -0600 | [diff] [blame] | 170 | dc->desc = "Calxeda Highbank registers"; |
| 171 | dc->vmsd = &vmstate_highbank_regs; |
| 172 | dc->reset = highbank_regs_reset; |
Anthony Liguori | 999e12b | 2012-01-24 13:12:29 -0600 | [diff] [blame] | 173 | } |
| 174 | |
Andreas Färber | 8c43a6f | 2013-01-10 16:19:07 +0100 | [diff] [blame] | 175 | static const TypeInfo highbank_regs_info = { |
Andreas Färber | 426533f | 2013-07-24 00:52:40 +0200 | [diff] [blame] | 176 | .name = TYPE_HIGHBANK_REGISTERS, |
Anthony Liguori | 39bffca | 2011-12-07 21:34:16 -0600 | [diff] [blame] | 177 | .parent = TYPE_SYS_BUS_DEVICE, |
| 178 | .instance_size = sizeof(HighbankRegsState), |
| 179 | .class_init = highbank_regs_class_init, |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 180 | }; |
| 181 | |
Andreas Färber | 83f7d43 | 2012-02-09 15:20:55 +0100 | [diff] [blame] | 182 | static void highbank_regs_register_types(void) |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 183 | { |
Anthony Liguori | 39bffca | 2011-12-07 21:34:16 -0600 | [diff] [blame] | 184 | type_register_static(&highbank_regs_info); |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 185 | } |
| 186 | |
Andreas Färber | 83f7d43 | 2012-02-09 15:20:55 +0100 | [diff] [blame] | 187 | type_init(highbank_regs_register_types) |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 188 | |
| 189 | static struct arm_boot_info highbank_binfo; |
| 190 | |
Andre Przywara | 574f66b | 2013-07-05 14:21:36 +0200 | [diff] [blame] | 191 | enum cxmachines { |
| 192 | CALXEDA_HIGHBANK, |
Andre Przywara | b25a83f | 2013-07-05 14:21:37 +0200 | [diff] [blame] | 193 | CALXEDA_MIDWAY, |
Andre Przywara | 574f66b | 2013-07-05 14:21:36 +0200 | [diff] [blame] | 194 | }; |
| 195 | |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 196 | /* ram_size must be set to match the upper bound of memory in the |
| 197 | * device tree (linux/arch/arm/boot/dts/highbank.dts), which is |
| 198 | * normally 0xff900000 or -m 4089. When running this board on a |
| 199 | * 32-bit host, set the reg value of memory to 0xf7ff00000 in the |
| 200 | * device tree and pass -m 2047 to QEMU. |
| 201 | */ |
Andre Przywara | 574f66b | 2013-07-05 14:21:36 +0200 | [diff] [blame] | 202 | static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine) |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 203 | { |
Eduardo Habkost | 5f072e1 | 2012-10-15 17:22:02 -0300 | [diff] [blame] | 204 | ram_addr_t ram_size = args->ram_size; |
| 205 | const char *cpu_model = args->cpu_model; |
| 206 | const char *kernel_filename = args->kernel_filename; |
| 207 | const char *kernel_cmdline = args->kernel_cmdline; |
| 208 | const char *initrd_filename = args->initrd_filename; |
Andre Przywara | 574f66b | 2013-07-05 14:21:36 +0200 | [diff] [blame] | 209 | DeviceState *dev = NULL; |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 210 | SysBusDevice *busdev; |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 211 | qemu_irq pic[128]; |
| 212 | int n; |
| 213 | qemu_irq cpu_irq[4]; |
| 214 | MemoryRegion *sysram; |
| 215 | MemoryRegion *dram; |
| 216 | MemoryRegion *sysmem; |
| 217 | char *sysboot_filename; |
| 218 | |
| 219 | if (!cpu_model) { |
Andre Przywara | 574f66b | 2013-07-05 14:21:36 +0200 | [diff] [blame] | 220 | switch (machine) { |
| 221 | case CALXEDA_HIGHBANK: |
| 222 | cpu_model = "cortex-a9"; |
| 223 | break; |
Andre Przywara | b25a83f | 2013-07-05 14:21:37 +0200 | [diff] [blame] | 224 | case CALXEDA_MIDWAY: |
| 225 | cpu_model = "cortex-a15"; |
| 226 | break; |
Andre Przywara | 574f66b | 2013-07-05 14:21:36 +0200 | [diff] [blame] | 227 | } |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 228 | } |
| 229 | |
| 230 | for (n = 0; n < smp_cpus; n++) { |
Peter Crosthwaite | f282f29 | 2013-12-17 19:42:28 +0000 | [diff] [blame] | 231 | ObjectClass *oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model); |
Peter Maydell | d097696 | 2014-04-04 17:42:34 +0100 | [diff] [blame] | 232 | Object *cpuobj; |
Peter Maydell | c5fad12 | 2012-04-20 07:39:15 +0000 | [diff] [blame] | 233 | ARMCPU *cpu; |
Peter Crosthwaite | f282f29 | 2013-12-17 19:42:28 +0000 | [diff] [blame] | 234 | Error *err = NULL; |
| 235 | |
Peter Maydell | 3b418d0 | 2014-04-04 17:42:33 +0100 | [diff] [blame] | 236 | if (!oc) { |
| 237 | error_report("Unable to find CPU definition"); |
| 238 | exit(1); |
| 239 | } |
| 240 | |
Peter Maydell | d097696 | 2014-04-04 17:42:34 +0100 | [diff] [blame] | 241 | cpuobj = object_new(object_class_get_name(oc)); |
| 242 | cpu = ARM_CPU(cpuobj); |
Peter Crosthwaite | f282f29 | 2013-12-17 19:42:28 +0000 | [diff] [blame] | 243 | |
Rob Herring | f51c2c8 | 2014-05-22 21:30:09 -0500 | [diff] [blame] | 244 | object_property_set_int(cpuobj, QEMU_PSCI_METHOD_SMC, "psci-method", |
| 245 | &error_abort); |
| 246 | |
| 247 | /* Secondary CPUs start in PSCI powered-down state */ |
| 248 | if (n > 0) { |
| 249 | object_property_set_bool(cpuobj, true, "start-powered-off", |
| 250 | &error_abort); |
| 251 | } |
| 252 | |
Peter Maydell | d097696 | 2014-04-04 17:42:34 +0100 | [diff] [blame] | 253 | if (object_property_find(cpuobj, "reset-cbar", NULL)) { |
| 254 | object_property_set_int(cpuobj, MPCORE_PERIPHBASE, |
| 255 | "reset-cbar", &error_abort); |
Peter Crosthwaite | c0f1ead | 2013-12-17 19:42:28 +0000 | [diff] [blame] | 256 | } |
Peter Maydell | d097696 | 2014-04-04 17:42:34 +0100 | [diff] [blame] | 257 | object_property_set_bool(cpuobj, true, "realized", &err); |
Peter Crosthwaite | f282f29 | 2013-12-17 19:42:28 +0000 | [diff] [blame] | 258 | if (err) { |
| 259 | error_report("%s", error_get_pretty(err)); |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 260 | exit(1); |
| 261 | } |
Peter Maydell | 9188dbf | 2013-08-20 14:54:29 +0100 | [diff] [blame] | 262 | cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ); |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 263 | } |
| 264 | |
| 265 | sysmem = get_system_memory(); |
| 266 | dram = g_new(MemoryRegion, 1); |
Paolo Bonzini | 2c9b15c | 2013-06-06 05:41:28 -0400 | [diff] [blame] | 267 | memory_region_init_ram(dram, NULL, "highbank.dram", ram_size); |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 268 | /* SDRAM at address zero. */ |
| 269 | memory_region_add_subregion(sysmem, 0, dram); |
| 270 | |
| 271 | sysram = g_new(MemoryRegion, 1); |
Paolo Bonzini | 2c9b15c | 2013-06-06 05:41:28 -0400 | [diff] [blame] | 272 | memory_region_init_ram(sysram, NULL, "highbank.sysram", 0x8000); |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 273 | memory_region_add_subregion(sysmem, 0xfff88000, sysram); |
| 274 | if (bios_name != NULL) { |
| 275 | sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); |
| 276 | if (sysboot_filename != NULL) { |
| 277 | uint32_t filesize = get_image_size(sysboot_filename); |
| 278 | if (load_image_targphys("sysram.bin", 0xfff88000, filesize) < 0) { |
| 279 | hw_error("Unable to load %s\n", bios_name); |
| 280 | } |
| 281 | } else { |
| 282 | hw_error("Unable to find %s\n", bios_name); |
| 283 | } |
| 284 | } |
| 285 | |
Andre Przywara | 574f66b | 2013-07-05 14:21:36 +0200 | [diff] [blame] | 286 | switch (machine) { |
| 287 | case CALXEDA_HIGHBANK: |
Andre Przywara | b25a83f | 2013-07-05 14:21:37 +0200 | [diff] [blame] | 288 | dev = qdev_create(NULL, "l2x0"); |
| 289 | qdev_init_nofail(dev); |
| 290 | busdev = SYS_BUS_DEVICE(dev); |
| 291 | sysbus_mmio_map(busdev, 0, 0xfff12000); |
| 292 | |
Andre Przywara | 574f66b | 2013-07-05 14:21:36 +0200 | [diff] [blame] | 293 | dev = qdev_create(NULL, "a9mpcore_priv"); |
| 294 | break; |
Andre Przywara | b25a83f | 2013-07-05 14:21:37 +0200 | [diff] [blame] | 295 | case CALXEDA_MIDWAY: |
| 296 | dev = qdev_create(NULL, "a15mpcore_priv"); |
| 297 | break; |
Andre Przywara | 574f66b | 2013-07-05 14:21:36 +0200 | [diff] [blame] | 298 | } |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 299 | qdev_prop_set_uint32(dev, "num-cpu", smp_cpus); |
| 300 | qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC); |
| 301 | qdev_init_nofail(dev); |
Andreas Färber | 1356b98 | 2013-01-20 02:47:33 +0100 | [diff] [blame] | 302 | busdev = SYS_BUS_DEVICE(dev); |
Peter Crosthwaite | e2cddee | 2013-12-17 19:42:29 +0000 | [diff] [blame] | 303 | sysbus_mmio_map(busdev, 0, MPCORE_PERIPHBASE); |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 304 | for (n = 0; n < smp_cpus; n++) { |
| 305 | sysbus_connect_irq(busdev, n, cpu_irq[n]); |
| 306 | } |
| 307 | |
| 308 | for (n = 0; n < 128; n++) { |
| 309 | pic[n] = qdev_get_gpio_in(dev, n); |
| 310 | } |
| 311 | |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 312 | dev = qdev_create(NULL, "sp804"); |
| 313 | qdev_prop_set_uint32(dev, "freq0", 150000000); |
| 314 | qdev_prop_set_uint32(dev, "freq1", 150000000); |
| 315 | qdev_init_nofail(dev); |
Andreas Färber | 1356b98 | 2013-01-20 02:47:33 +0100 | [diff] [blame] | 316 | busdev = SYS_BUS_DEVICE(dev); |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 317 | sysbus_mmio_map(busdev, 0, 0xfff34000); |
| 318 | sysbus_connect_irq(busdev, 0, pic[18]); |
| 319 | sysbus_create_simple("pl011", 0xfff36000, pic[20]); |
| 320 | |
| 321 | dev = qdev_create(NULL, "highbank-regs"); |
| 322 | qdev_init_nofail(dev); |
Andreas Färber | 1356b98 | 2013-01-20 02:47:33 +0100 | [diff] [blame] | 323 | busdev = SYS_BUS_DEVICE(dev); |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 324 | sysbus_mmio_map(busdev, 0, 0xfff3c000); |
| 325 | |
| 326 | sysbus_create_simple("pl061", 0xfff30000, pic[14]); |
| 327 | sysbus_create_simple("pl061", 0xfff31000, pic[15]); |
| 328 | sysbus_create_simple("pl061", 0xfff32000, pic[16]); |
| 329 | sysbus_create_simple("pl061", 0xfff33000, pic[17]); |
| 330 | sysbus_create_simple("pl031", 0xfff35000, pic[19]); |
| 331 | sysbus_create_simple("pl022", 0xfff39000, pic[23]); |
| 332 | |
| 333 | sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]); |
| 334 | |
Stefan Hajnoczi | a005d07 | 2012-07-24 16:35:11 +0100 | [diff] [blame] | 335 | if (nd_table[0].used) { |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 336 | qemu_check_nic_model(&nd_table[0], "xgmac"); |
| 337 | dev = qdev_create(NULL, "xgmac"); |
| 338 | qdev_set_nic_properties(dev, &nd_table[0]); |
| 339 | qdev_init_nofail(dev); |
Andreas Färber | 1356b98 | 2013-01-20 02:47:33 +0100 | [diff] [blame] | 340 | sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff50000); |
| 341 | sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[77]); |
| 342 | sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[78]); |
| 343 | sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, pic[79]); |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 344 | |
| 345 | qemu_check_nic_model(&nd_table[1], "xgmac"); |
| 346 | dev = qdev_create(NULL, "xgmac"); |
| 347 | qdev_set_nic_properties(dev, &nd_table[1]); |
| 348 | qdev_init_nofail(dev); |
Andreas Färber | 1356b98 | 2013-01-20 02:47:33 +0100 | [diff] [blame] | 349 | sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff51000); |
| 350 | sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[80]); |
| 351 | sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[81]); |
| 352 | sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, pic[82]); |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 353 | } |
| 354 | |
| 355 | highbank_binfo.ram_size = ram_size; |
| 356 | highbank_binfo.kernel_filename = kernel_filename; |
| 357 | highbank_binfo.kernel_cmdline = kernel_cmdline; |
| 358 | highbank_binfo.initrd_filename = initrd_filename; |
| 359 | /* highbank requires a dtb in order to boot, and the dtb will override |
| 360 | * the board ID. The following value is ignored, so set it to -1 to be |
| 361 | * clear that the value is meaningless. |
| 362 | */ |
| 363 | highbank_binfo.board_id = -1; |
| 364 | highbank_binfo.nb_cpus = smp_cpus; |
| 365 | highbank_binfo.loader_start = 0; |
| 366 | highbank_binfo.write_secondary_boot = hb_write_secondary; |
| 367 | highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary; |
Andreas Färber | 182735e | 2013-05-29 22:29:20 +0200 | [diff] [blame] | 368 | arm_load_kernel(ARM_CPU(first_cpu), &highbank_binfo); |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 369 | } |
| 370 | |
Andre Przywara | 574f66b | 2013-07-05 14:21:36 +0200 | [diff] [blame] | 371 | static void highbank_init(QEMUMachineInitArgs *args) |
| 372 | { |
| 373 | calxeda_init(args, CALXEDA_HIGHBANK); |
| 374 | } |
| 375 | |
Andre Przywara | b25a83f | 2013-07-05 14:21:37 +0200 | [diff] [blame] | 376 | static void midway_init(QEMUMachineInitArgs *args) |
| 377 | { |
| 378 | calxeda_init(args, CALXEDA_MIDWAY); |
| 379 | } |
| 380 | |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 381 | static QEMUMachine highbank_machine = { |
| 382 | .name = "highbank", |
| 383 | .desc = "Calxeda Highbank (ECX-1000)", |
| 384 | .init = highbank_init, |
Christian Borntraeger | 2d0d283 | 2012-11-20 15:30:34 +0100 | [diff] [blame] | 385 | .block_default_type = IF_SCSI, |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 386 | .max_cpus = 4, |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 387 | }; |
| 388 | |
Andre Przywara | b25a83f | 2013-07-05 14:21:37 +0200 | [diff] [blame] | 389 | static QEMUMachine midway_machine = { |
| 390 | .name = "midway", |
| 391 | .desc = "Calxeda Midway (ECX-2000)", |
| 392 | .init = midway_init, |
| 393 | .block_default_type = IF_SCSI, |
| 394 | .max_cpus = 4, |
Andre Przywara | b25a83f | 2013-07-05 14:21:37 +0200 | [diff] [blame] | 395 | }; |
| 396 | |
Andre Przywara | 574f66b | 2013-07-05 14:21:36 +0200 | [diff] [blame] | 397 | static void calxeda_machines_init(void) |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 398 | { |
| 399 | qemu_register_machine(&highbank_machine); |
Andre Przywara | b25a83f | 2013-07-05 14:21:37 +0200 | [diff] [blame] | 400 | qemu_register_machine(&midway_machine); |
Rob Herring | 2488514 | 2012-01-26 11:43:49 +0000 | [diff] [blame] | 401 | } |
| 402 | |
Andre Przywara | 574f66b | 2013-07-05 14:21:36 +0200 | [diff] [blame] | 403 | machine_init(calxeda_machines_init); |