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