Peter Maydell | 2eb5578 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 1 | /* |
| 2 | * ARM V2M MPS2 board emulation. |
| 3 | * |
| 4 | * Copyright (c) 2017 Linaro Limited |
| 5 | * Written by Peter Maydell |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License version 2 or |
| 9 | * (at your option) any later version. |
| 10 | */ |
| 11 | |
| 12 | /* The MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger |
| 13 | * FPGA but is otherwise the same as the 2). Since the CPU itself |
| 14 | * and most of the devices are in the FPGA, the details of the board |
| 15 | * as seen by the guest depend significantly on the FPGA image. |
| 16 | * We model the following FPGA images: |
| 17 | * "mps2-an385" -- Cortex-M3 as documented in ARM Application Note AN385 |
| 18 | * "mps2-an511" -- Cortex-M3 'DesignStart' as documented in AN511 |
| 19 | * |
| 20 | * Links to the TRM for the board itself and to the various Application |
| 21 | * Notes which document the FPGA images can be found here: |
| 22 | * https://developer.arm.com/products/system-design/development-boards/cortex-m-prototyping-system |
| 23 | */ |
| 24 | |
| 25 | #include "qemu/osdep.h" |
Philippe Mathieu-Daudé | eba5999 | 2019-10-22 16:50:37 +0100 | [diff] [blame] | 26 | #include "qemu/units.h" |
Peter Maydell | 2eb5578 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 27 | #include "qapi/error.h" |
| 28 | #include "qemu/error-report.h" |
Peter Maydell | 12ec8bd | 2019-05-23 14:47:43 +0100 | [diff] [blame] | 29 | #include "hw/arm/boot.h" |
Peter Maydell | 2eb5578 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 30 | #include "hw/arm/armv7m.h" |
Peter Maydell | 977a15f | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 31 | #include "hw/or-irq.h" |
Peter Maydell | 2eb5578 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 32 | #include "hw/boards.h" |
| 33 | #include "exec/address-spaces.h" |
Peter Maydell | 977a15f | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 34 | #include "sysemu/sysemu.h" |
Peter Maydell | 2eb5578 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 35 | #include "hw/misc/unimp.h" |
Peter Maydell | 977a15f | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 36 | #include "hw/char/cmsdk-apb-uart.h" |
Peter Maydell | 3d53904 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 37 | #include "hw/timer/cmsdk-apb-timer.h" |
Peter Maydell | 595c786 | 2018-08-24 13:17:42 +0100 | [diff] [blame] | 38 | #include "hw/timer/cmsdk-apb-dualtimer.h" |
Peter Maydell | 6dbdf4e | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 39 | #include "hw/misc/mps2-scc.h" |
Philippe Mathieu-Daudé | 66b03dc | 2019-04-12 18:54:13 +0200 | [diff] [blame] | 40 | #include "hw/net/lan9118.h" |
Peter Maydell | 3587393 | 2017-07-17 13:36:09 +0100 | [diff] [blame] | 41 | #include "net/net.h" |
Peter Maydell | 2eb5578 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 42 | |
| 43 | typedef enum MPS2FPGAType { |
| 44 | FPGA_AN385, |
| 45 | FPGA_AN511, |
| 46 | } MPS2FPGAType; |
| 47 | |
| 48 | typedef struct { |
| 49 | MachineClass parent; |
| 50 | MPS2FPGAType fpga_type; |
Peter Maydell | 6dbdf4e | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 51 | uint32_t scc_id; |
Peter Maydell | 2eb5578 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 52 | } MPS2MachineClass; |
| 53 | |
| 54 | typedef struct { |
| 55 | MachineState parent; |
| 56 | |
| 57 | ARMv7MState armv7m; |
| 58 | MemoryRegion psram; |
| 59 | MemoryRegion ssram1; |
| 60 | MemoryRegion ssram1_m; |
| 61 | MemoryRegion ssram23; |
| 62 | MemoryRegion ssram23_m; |
| 63 | MemoryRegion blockram; |
| 64 | MemoryRegion blockram_m1; |
| 65 | MemoryRegion blockram_m2; |
| 66 | MemoryRegion blockram_m3; |
| 67 | MemoryRegion sram; |
Peter Maydell | 6dbdf4e | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 68 | MPS2SCC scc; |
Peter Maydell | 595c786 | 2018-08-24 13:17:42 +0100 | [diff] [blame] | 69 | CMSDKAPBDualTimer dualtimer; |
Peter Maydell | 2eb5578 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 70 | } MPS2MachineState; |
| 71 | |
| 72 | #define TYPE_MPS2_MACHINE "mps2" |
| 73 | #define TYPE_MPS2_AN385_MACHINE MACHINE_TYPE_NAME("mps2-an385") |
| 74 | #define TYPE_MPS2_AN511_MACHINE MACHINE_TYPE_NAME("mps2-an511") |
| 75 | |
| 76 | #define MPS2_MACHINE(obj) \ |
| 77 | OBJECT_CHECK(MPS2MachineState, obj, TYPE_MPS2_MACHINE) |
| 78 | #define MPS2_MACHINE_GET_CLASS(obj) \ |
| 79 | OBJECT_GET_CLASS(MPS2MachineClass, obj, TYPE_MPS2_MACHINE) |
| 80 | #define MPS2_MACHINE_CLASS(klass) \ |
| 81 | OBJECT_CLASS_CHECK(MPS2MachineClass, klass, TYPE_MPS2_MACHINE) |
| 82 | |
| 83 | /* Main SYSCLK frequency in Hz */ |
| 84 | #define SYSCLK_FRQ 25000000 |
| 85 | |
| 86 | /* Initialize the auxiliary RAM region @mr and map it into |
| 87 | * the memory map at @base. |
| 88 | */ |
| 89 | static void make_ram(MemoryRegion *mr, const char *name, |
| 90 | hwaddr base, hwaddr size) |
| 91 | { |
| 92 | memory_region_init_ram(mr, NULL, name, size, &error_fatal); |
| 93 | memory_region_add_subregion(get_system_memory(), base, mr); |
| 94 | } |
| 95 | |
| 96 | /* Create an alias of an entire original MemoryRegion @orig |
| 97 | * located at @base in the memory map. |
| 98 | */ |
| 99 | static void make_ram_alias(MemoryRegion *mr, const char *name, |
| 100 | MemoryRegion *orig, hwaddr base) |
| 101 | { |
| 102 | memory_region_init_alias(mr, NULL, name, orig, 0, |
| 103 | memory_region_size(orig)); |
| 104 | memory_region_add_subregion(get_system_memory(), base, mr); |
| 105 | } |
| 106 | |
| 107 | static void mps2_common_init(MachineState *machine) |
| 108 | { |
| 109 | MPS2MachineState *mms = MPS2_MACHINE(machine); |
| 110 | MPS2MachineClass *mmc = MPS2_MACHINE_GET_CLASS(machine); |
| 111 | MemoryRegion *system_memory = get_system_memory(); |
Igor Mammedov | ba1ba5c | 2017-09-13 18:04:57 +0200 | [diff] [blame] | 112 | MachineClass *mc = MACHINE_GET_CLASS(machine); |
Peter Maydell | 6dbdf4e | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 113 | DeviceState *armv7m, *sccdev; |
Peter Maydell | 2eb5578 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 114 | |
Igor Mammedov | ba1ba5c | 2017-09-13 18:04:57 +0200 | [diff] [blame] | 115 | if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) { |
| 116 | error_report("This board can only be used with CPU %s", |
| 117 | mc->default_cpu_type); |
Peter Maydell | 2eb5578 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 118 | exit(1); |
| 119 | } |
| 120 | |
| 121 | /* The FPGA images have an odd combination of different RAMs, |
| 122 | * because in hardware they are different implementations and |
| 123 | * connected to different buses, giving varying performance/size |
| 124 | * tradeoffs. For QEMU they're all just RAM, though. We arbitrarily |
| 125 | * call the 16MB our "system memory", as it's the largest lump. |
| 126 | * |
| 127 | * Common to both boards: |
| 128 | * 0x21000000..0x21ffffff : PSRAM (16MB) |
| 129 | * AN385 only: |
| 130 | * 0x00000000 .. 0x003fffff : ZBT SSRAM1 |
| 131 | * 0x00400000 .. 0x007fffff : mirror of ZBT SSRAM1 |
| 132 | * 0x20000000 .. 0x203fffff : ZBT SSRAM 2&3 |
| 133 | * 0x20400000 .. 0x207fffff : mirror of ZBT SSRAM 2&3 |
| 134 | * 0x01000000 .. 0x01003fff : block RAM (16K) |
| 135 | * 0x01004000 .. 0x01007fff : mirror of above |
| 136 | * 0x01008000 .. 0x0100bfff : mirror of above |
| 137 | * 0x0100c000 .. 0x0100ffff : mirror of above |
| 138 | * AN511 only: |
| 139 | * 0x00000000 .. 0x0003ffff : FPGA block RAM |
| 140 | * 0x00400000 .. 0x007fffff : ZBT SSRAM1 |
| 141 | * 0x20000000 .. 0x2001ffff : SRAM |
| 142 | * 0x20400000 .. 0x207fffff : ZBT SSRAM 2&3 |
| 143 | * |
| 144 | * The AN385 has a feature where the lowest 16K can be mapped |
| 145 | * either to the bottom of the ZBT SSRAM1 or to the block RAM. |
| 146 | * This is of no use for QEMU so we don't implement it (as if |
| 147 | * zbt_boot_ctrl is always zero). |
| 148 | */ |
| 149 | memory_region_allocate_system_memory(&mms->psram, |
Philippe Mathieu-Daudé | eba5999 | 2019-10-22 16:50:37 +0100 | [diff] [blame] | 150 | NULL, "mps.ram", 16 * MiB); |
Peter Maydell | 2eb5578 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 151 | memory_region_add_subregion(system_memory, 0x21000000, &mms->psram); |
| 152 | |
| 153 | switch (mmc->fpga_type) { |
| 154 | case FPGA_AN385: |
| 155 | make_ram(&mms->ssram1, "mps.ssram1", 0x0, 0x400000); |
| 156 | make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x400000); |
| 157 | make_ram(&mms->ssram23, "mps.ssram23", 0x20000000, 0x400000); |
| 158 | make_ram_alias(&mms->ssram23_m, "mps.ssram23_m", |
| 159 | &mms->ssram23, 0x20400000); |
| 160 | make_ram(&mms->blockram, "mps.blockram", 0x01000000, 0x4000); |
| 161 | make_ram_alias(&mms->blockram_m1, "mps.blockram_m1", |
| 162 | &mms->blockram, 0x01004000); |
| 163 | make_ram_alias(&mms->blockram_m2, "mps.blockram_m2", |
| 164 | &mms->blockram, 0x01008000); |
| 165 | make_ram_alias(&mms->blockram_m3, "mps.blockram_m3", |
| 166 | &mms->blockram, 0x0100c000); |
| 167 | break; |
| 168 | case FPGA_AN511: |
| 169 | make_ram(&mms->blockram, "mps.blockram", 0x0, 0x40000); |
| 170 | make_ram(&mms->ssram1, "mps.ssram1", 0x00400000, 0x00800000); |
| 171 | make_ram(&mms->sram, "mps.sram", 0x20000000, 0x20000); |
| 172 | make_ram(&mms->ssram23, "mps.ssram23", 0x20400000, 0x400000); |
| 173 | break; |
| 174 | default: |
| 175 | g_assert_not_reached(); |
| 176 | } |
| 177 | |
Philippe Mathieu-Daudé | f9e8032 | 2019-05-07 18:34:15 +0200 | [diff] [blame] | 178 | sysbus_init_child_obj(OBJECT(mms), "armv7m", &mms->armv7m, |
| 179 | sizeof(mms->armv7m), TYPE_ARMV7M); |
Peter Maydell | 2eb5578 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 180 | armv7m = DEVICE(&mms->armv7m); |
Peter Maydell | 2eb5578 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 181 | switch (mmc->fpga_type) { |
| 182 | case FPGA_AN385: |
| 183 | qdev_prop_set_uint32(armv7m, "num-irq", 32); |
| 184 | break; |
| 185 | case FPGA_AN511: |
| 186 | qdev_prop_set_uint32(armv7m, "num-irq", 64); |
| 187 | break; |
| 188 | default: |
| 189 | g_assert_not_reached(); |
| 190 | } |
Igor Mammedov | ba1ba5c | 2017-09-13 18:04:57 +0200 | [diff] [blame] | 191 | qdev_prop_set_string(armv7m, "cpu-type", machine->cpu_type); |
Stefan Hajnoczi | a1c5a06 | 2018-08-16 14:05:28 +0100 | [diff] [blame] | 192 | qdev_prop_set_bit(armv7m, "enable-bitband", true); |
Peter Maydell | 2eb5578 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 193 | object_property_set_link(OBJECT(&mms->armv7m), OBJECT(system_memory), |
| 194 | "memory", &error_abort); |
| 195 | object_property_set_bool(OBJECT(&mms->armv7m), true, "realized", |
| 196 | &error_fatal); |
| 197 | |
| 198 | create_unimplemented_device("zbtsmram mirror", 0x00400000, 0x00400000); |
| 199 | create_unimplemented_device("RESERVED 1", 0x00800000, 0x00800000); |
| 200 | create_unimplemented_device("Block RAM", 0x01000000, 0x00010000); |
| 201 | create_unimplemented_device("RESERVED 2", 0x01010000, 0x1EFF0000); |
| 202 | create_unimplemented_device("RESERVED 3", 0x20800000, 0x00800000); |
| 203 | create_unimplemented_device("PSRAM", 0x21000000, 0x01000000); |
| 204 | /* These three ranges all cover multiple devices; we may implement |
| 205 | * some of them below (in which case the real device takes precedence |
| 206 | * over the unimplemented-region mapping). |
| 207 | */ |
| 208 | create_unimplemented_device("CMSDK APB peripheral region @0x40000000", |
| 209 | 0x40000000, 0x00010000); |
| 210 | create_unimplemented_device("CMSDK peripheral region @0x40010000", |
| 211 | 0x40010000, 0x00010000); |
| 212 | create_unimplemented_device("Extra peripheral region @0x40020000", |
| 213 | 0x40020000, 0x00010000); |
| 214 | create_unimplemented_device("RESERVED 4", 0x40030000, 0x001D0000); |
Peter Maydell | 2eb5578 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 215 | create_unimplemented_device("VGA", 0x41000000, 0x0200000); |
| 216 | |
Peter Maydell | 977a15f | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 217 | switch (mmc->fpga_type) { |
| 218 | case FPGA_AN385: |
| 219 | { |
| 220 | /* The overflow IRQs for UARTs 0, 1 and 2 are ORed together. |
| 221 | * Overflow for UARTs 4 and 5 doesn't trigger any interrupt. |
| 222 | */ |
| 223 | Object *orgate; |
| 224 | DeviceState *orgate_dev; |
| 225 | int i; |
| 226 | |
| 227 | orgate = object_new(TYPE_OR_IRQ); |
| 228 | object_property_set_int(orgate, 6, "num-lines", &error_fatal); |
| 229 | object_property_set_bool(orgate, true, "realized", &error_fatal); |
| 230 | orgate_dev = DEVICE(orgate); |
| 231 | qdev_connect_gpio_out(orgate_dev, 0, qdev_get_gpio_in(armv7m, 12)); |
| 232 | |
| 233 | for (i = 0; i < 5; i++) { |
| 234 | static const hwaddr uartbase[] = {0x40004000, 0x40005000, |
| 235 | 0x40006000, 0x40007000, |
| 236 | 0x40009000}; |
Peter Maydell | 977a15f | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 237 | /* RX irq number; TX irq is always one greater */ |
| 238 | static const int uartirq[] = {0, 2, 4, 18, 20}; |
| 239 | qemu_irq txovrint = NULL, rxovrint = NULL; |
| 240 | |
| 241 | if (i < 3) { |
| 242 | txovrint = qdev_get_gpio_in(orgate_dev, i * 2); |
| 243 | rxovrint = qdev_get_gpio_in(orgate_dev, i * 2 + 1); |
| 244 | } |
| 245 | |
| 246 | cmsdk_apb_uart_create(uartbase[i], |
| 247 | qdev_get_gpio_in(armv7m, uartirq[i] + 1), |
| 248 | qdev_get_gpio_in(armv7m, uartirq[i]), |
| 249 | txovrint, rxovrint, |
| 250 | NULL, |
Peter Maydell | fc38a11 | 2018-04-20 15:52:44 +0100 | [diff] [blame] | 251 | serial_hd(i), SYSCLK_FRQ); |
Peter Maydell | 977a15f | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 252 | } |
| 253 | break; |
| 254 | } |
| 255 | case FPGA_AN511: |
| 256 | { |
| 257 | /* The overflow IRQs for all UARTs are ORed together. |
| 258 | * Tx and Rx IRQs for each UART are ORed together. |
| 259 | */ |
| 260 | Object *orgate; |
| 261 | DeviceState *orgate_dev; |
| 262 | int i; |
| 263 | |
| 264 | orgate = object_new(TYPE_OR_IRQ); |
| 265 | object_property_set_int(orgate, 10, "num-lines", &error_fatal); |
| 266 | object_property_set_bool(orgate, true, "realized", &error_fatal); |
| 267 | orgate_dev = DEVICE(orgate); |
| 268 | qdev_connect_gpio_out(orgate_dev, 0, qdev_get_gpio_in(armv7m, 12)); |
| 269 | |
| 270 | for (i = 0; i < 5; i++) { |
| 271 | /* system irq numbers for the combined tx/rx for each UART */ |
| 272 | static const int uart_txrx_irqno[] = {0, 2, 45, 46, 56}; |
| 273 | static const hwaddr uartbase[] = {0x40004000, 0x40005000, |
| 274 | 0x4002c000, 0x4002d000, |
| 275 | 0x4002e000}; |
Peter Maydell | 977a15f | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 276 | Object *txrx_orgate; |
| 277 | DeviceState *txrx_orgate_dev; |
| 278 | |
| 279 | txrx_orgate = object_new(TYPE_OR_IRQ); |
| 280 | object_property_set_int(txrx_orgate, 2, "num-lines", &error_fatal); |
| 281 | object_property_set_bool(txrx_orgate, true, "realized", |
| 282 | &error_fatal); |
| 283 | txrx_orgate_dev = DEVICE(txrx_orgate); |
| 284 | qdev_connect_gpio_out(txrx_orgate_dev, 0, |
| 285 | qdev_get_gpio_in(armv7m, uart_txrx_irqno[i])); |
| 286 | cmsdk_apb_uart_create(uartbase[i], |
| 287 | qdev_get_gpio_in(txrx_orgate_dev, 0), |
| 288 | qdev_get_gpio_in(txrx_orgate_dev, 1), |
Peter Maydell | ce3bc11 | 2017-09-14 18:43:19 +0100 | [diff] [blame] | 289 | qdev_get_gpio_in(orgate_dev, i * 2), |
| 290 | qdev_get_gpio_in(orgate_dev, i * 2 + 1), |
Peter Maydell | 977a15f | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 291 | NULL, |
Peter Maydell | fc38a11 | 2018-04-20 15:52:44 +0100 | [diff] [blame] | 292 | serial_hd(i), SYSCLK_FRQ); |
Peter Maydell | 977a15f | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 293 | } |
| 294 | break; |
| 295 | } |
| 296 | default: |
| 297 | g_assert_not_reached(); |
| 298 | } |
| 299 | |
Peter Maydell | 3d53904 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 300 | cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ); |
| 301 | cmsdk_apb_timer_create(0x40001000, qdev_get_gpio_in(armv7m, 9), SYSCLK_FRQ); |
| 302 | |
Peter Maydell | 595c786 | 2018-08-24 13:17:42 +0100 | [diff] [blame] | 303 | sysbus_init_child_obj(OBJECT(mms), "dualtimer", &mms->dualtimer, |
| 304 | sizeof(mms->dualtimer), TYPE_CMSDK_APB_DUALTIMER); |
| 305 | qdev_prop_set_uint32(DEVICE(&mms->dualtimer), "pclk-frq", SYSCLK_FRQ); |
| 306 | object_property_set_bool(OBJECT(&mms->dualtimer), true, "realized", |
| 307 | &error_fatal); |
| 308 | sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 0, |
| 309 | qdev_get_gpio_in(armv7m, 10)); |
| 310 | sysbus_mmio_map(SYS_BUS_DEVICE(&mms->dualtimer), 0, 0x40002000); |
| 311 | |
Philippe Mathieu-Daudé | f9e8032 | 2019-05-07 18:34:15 +0200 | [diff] [blame] | 312 | sysbus_init_child_obj(OBJECT(mms), "scc", &mms->scc, |
| 313 | sizeof(mms->scc), TYPE_MPS2_SCC); |
Peter Maydell | 6dbdf4e | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 314 | sccdev = DEVICE(&mms->scc); |
Peter Maydell | 6dbdf4e | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 315 | qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2); |
Peter Maydell | 239cb6f | 2018-08-24 13:17:50 +0100 | [diff] [blame] | 316 | qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008); |
Peter Maydell | 6dbdf4e | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 317 | qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id); |
| 318 | object_property_set_bool(OBJECT(&mms->scc), true, "realized", |
| 319 | &error_fatal); |
| 320 | sysbus_mmio_map(SYS_BUS_DEVICE(sccdev), 0, 0x4002f000); |
| 321 | |
Peter Maydell | 3587393 | 2017-07-17 13:36:09 +0100 | [diff] [blame] | 322 | /* In hardware this is a LAN9220; the LAN9118 is software compatible |
| 323 | * except that it doesn't support the checksum-offload feature. |
| 324 | */ |
| 325 | lan9118_init(&nd_table[0], 0x40200000, |
| 326 | qdev_get_gpio_in(armv7m, |
| 327 | mmc->fpga_type == FPGA_AN385 ? 13 : 47)); |
| 328 | |
Peter Maydell | 2eb5578 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 329 | system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ; |
| 330 | |
| 331 | armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, |
| 332 | 0x400000); |
| 333 | } |
| 334 | |
| 335 | static void mps2_class_init(ObjectClass *oc, void *data) |
| 336 | { |
| 337 | MachineClass *mc = MACHINE_CLASS(oc); |
| 338 | |
| 339 | mc->init = mps2_common_init; |
| 340 | mc->max_cpus = 1; |
| 341 | } |
| 342 | |
| 343 | static void mps2_an385_class_init(ObjectClass *oc, void *data) |
| 344 | { |
| 345 | MachineClass *mc = MACHINE_CLASS(oc); |
| 346 | MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc); |
| 347 | |
| 348 | mc->desc = "ARM MPS2 with AN385 FPGA image for Cortex-M3"; |
| 349 | mmc->fpga_type = FPGA_AN385; |
Igor Mammedov | ba1ba5c | 2017-09-13 18:04:57 +0200 | [diff] [blame] | 350 | mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3"); |
Peter Maydell | 239cb6f | 2018-08-24 13:17:50 +0100 | [diff] [blame] | 351 | mmc->scc_id = 0x41043850; |
Peter Maydell | 2eb5578 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 352 | } |
| 353 | |
| 354 | static void mps2_an511_class_init(ObjectClass *oc, void *data) |
| 355 | { |
| 356 | MachineClass *mc = MACHINE_CLASS(oc); |
| 357 | MPS2MachineClass *mmc = MPS2_MACHINE_CLASS(oc); |
| 358 | |
| 359 | mc->desc = "ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3"; |
| 360 | mmc->fpga_type = FPGA_AN511; |
Igor Mammedov | ba1ba5c | 2017-09-13 18:04:57 +0200 | [diff] [blame] | 361 | mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3"); |
Peter Maydell | 239cb6f | 2018-08-24 13:17:50 +0100 | [diff] [blame] | 362 | mmc->scc_id = 0x41045110; |
Peter Maydell | 2eb5578 | 2017-07-17 13:36:08 +0100 | [diff] [blame] | 363 | } |
| 364 | |
| 365 | static const TypeInfo mps2_info = { |
| 366 | .name = TYPE_MPS2_MACHINE, |
| 367 | .parent = TYPE_MACHINE, |
| 368 | .abstract = true, |
| 369 | .instance_size = sizeof(MPS2MachineState), |
| 370 | .class_size = sizeof(MPS2MachineClass), |
| 371 | .class_init = mps2_class_init, |
| 372 | }; |
| 373 | |
| 374 | static const TypeInfo mps2_an385_info = { |
| 375 | .name = TYPE_MPS2_AN385_MACHINE, |
| 376 | .parent = TYPE_MPS2_MACHINE, |
| 377 | .class_init = mps2_an385_class_init, |
| 378 | }; |
| 379 | |
| 380 | static const TypeInfo mps2_an511_info = { |
| 381 | .name = TYPE_MPS2_AN511_MACHINE, |
| 382 | .parent = TYPE_MPS2_MACHINE, |
| 383 | .class_init = mps2_an511_class_init, |
| 384 | }; |
| 385 | |
| 386 | static void mps2_machine_init(void) |
| 387 | { |
| 388 | type_register_static(&mps2_info); |
| 389 | type_register_static(&mps2_an385_info); |
| 390 | type_register_static(&mps2_an511_info); |
| 391 | } |
| 392 | |
| 393 | type_init(mps2_machine_init); |