Revision f7c70325

b/Makefile.target
270 270
obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o
271 271
obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
272 272
obj-arm-y += versatile_pci.o
273
obj-arm-y += realview_gic.o realview.o arm_sysctl.o mpcore.o
273
obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
274 274
obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
275 275
obj-arm-y += pl061.o
276 276
obj-arm-y += arm-semi.o
b/hw/a9mpcore.c
1
/*
2
 * Cortex-A9MPCore internal peripheral emulation.
3
 *
4
 * Copyright (c) 2009 CodeSourcery.
5
 * Written by Paul Brook
6
 *
7
 * This code is licenced under the GPL.
8
 */
9

  
10
/* 64 external IRQ lines.  */
11
#define GIC_NIRQ 96
12
#include "mpcore.c"
13

  
14
static SysBusDeviceInfo mpcore_priv_info = {
15
    .init = mpcore_priv_init,
16
    .qdev.name  = "a9mpcore_priv",
17
    .qdev.size  = sizeof(mpcore_priv_state),
18
    .qdev.props = (Property[]) {
19
        DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
20
        DEFINE_PROP_END_OF_LIST(),
21
    }
22
};
23

  
24
static void a9mpcore_register_devices(void)
25
{
26
    sysbus_register_withprop(&mpcore_priv_info);
27
}
28

  
29
device_init(a9mpcore_register_devices)
b/hw/arm-misc.h
28 28
    const char *initrd_filename;
29 29
    target_phys_addr_t loader_start;
30 30
    target_phys_addr_t smp_loader_start;
31
    target_phys_addr_t smp_priv_base;
31 32
    int nb_cpus;
32 33
    int board_id;
33 34
    int (*atag_board)(struct arm_boot_info *info, void *p);
b/hw/arm11mpcore.c
1
/*
2
 * ARM11MPCore internal peripheral emulation.
3
 *
4
 * Copyright (c) 2006-2007 CodeSourcery.
5
 * Written by Paul Brook
6
 *
7
 * This code is licenced under the GPL.
8
 */
9

  
10
/* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
11
   (+ 32 internal).  However my test chip only exposes/reports 32.
12
   More importantly Linux falls over if more than 32 are present!  */
13
#define GIC_NIRQ 64
14
#include "mpcore.c"
15

  
16
/* Dummy PIC to route IRQ lines.  The baseboard has 4 independent IRQ
17
   controllers.  The output of these, plus some of the raw input lines
18
   are fed into a single SMP-aware interrupt controller on the CPU.  */
19
typedef struct {
20
    SysBusDevice busdev;
21
    SysBusDevice *priv;
22
    qemu_irq cpuic[32];
23
    qemu_irq rvic[4][64];
24
    uint32_t num_cpu;
25
} mpcore_rirq_state;
26

  
27
/* Map baseboard IRQs onto CPU IRQ lines.  */
28
static const int mpcore_irq_map[32] = {
29
    -1, -1, -1, -1,  1,  2, -1, -1,
30
    -1, -1,  6, -1,  4,  5, -1, -1,
31
    -1, 14, 15,  0,  7,  8, -1, -1,
32
    -1, -1, -1, -1,  9,  3, -1, -1,
33
};
34

  
35
static void mpcore_rirq_set_irq(void *opaque, int irq, int level)
36
{
37
    mpcore_rirq_state *s = (mpcore_rirq_state *)opaque;
38
    int i;
39

  
40
    for (i = 0; i < 4; i++) {
41
        qemu_set_irq(s->rvic[i][irq], level);
42
    }
43
    if (irq < 32) {
44
        irq = mpcore_irq_map[irq];
45
        if (irq >= 0) {
46
            qemu_set_irq(s->cpuic[irq], level);
47
        }
48
    }
49
}
50

  
51
static void mpcore_rirq_map(SysBusDevice *dev, target_phys_addr_t base)
52
{
53
    mpcore_rirq_state *s = FROM_SYSBUS(mpcore_rirq_state, dev);
54
    sysbus_mmio_map(s->priv, 0, base);
55
}
56

  
57
static int realview_mpcore_init(SysBusDevice *dev)
58
{
59
    mpcore_rirq_state *s = FROM_SYSBUS(mpcore_rirq_state, dev);
60
    DeviceState *gic;
61
    DeviceState *priv;
62
    int n;
63
    int i;
64

  
65
    priv = qdev_create(NULL, "arm11mpcore_priv");
66
    qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu);
67
    qdev_init_nofail(priv);
68
    s->priv = sysbus_from_qdev(priv);
69
    sysbus_pass_irq(dev, s->priv);
70
    for (i = 0; i < 32; i++) {
71
        s->cpuic[i] = qdev_get_gpio_in(priv, i);
72
    }
73
    /* ??? IRQ routing is hardcoded to "normal" mode.  */
74
    for (n = 0; n < 4; n++) {
75
        gic = sysbus_create_simple("realview_gic", 0x10040000 + n * 0x10000,
76
                                   s->cpuic[10 + n]);
77
        for (i = 0; i < 64; i++) {
78
            s->rvic[n][i] = qdev_get_gpio_in(gic, i);
79
        }
80
    }
81
    qdev_init_gpio_in(&dev->qdev, mpcore_rirq_set_irq, 64);
82
    sysbus_init_mmio_cb(dev, 0x2000, mpcore_rirq_map);
83
    return 0;
84
}
85

  
86
static SysBusDeviceInfo mpcore_rirq_info = {
87
    .init = realview_mpcore_init,
88
    .qdev.name  = "realview_mpcore",
89
    .qdev.size  = sizeof(mpcore_rirq_state),
90
    .qdev.props = (Property[]) {
91
        DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1),
92
        DEFINE_PROP_END_OF_LIST(),
93
    }
94
};
95

  
96
static SysBusDeviceInfo mpcore_priv_info = {
97
    .init = mpcore_priv_init,
98
    .qdev.name  = "arm11mpcore_priv",
99
    .qdev.size  = sizeof(mpcore_priv_state),
100
    .qdev.props = (Property[]) {
101
        DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
102
        DEFINE_PROP_END_OF_LIST(),
103
    }
104
};
105

  
106
static void arm11mpcore_register_devices(void)
107
{
108
    sysbus_register_withprop(&mpcore_rirq_info);
109
    sysbus_register_withprop(&mpcore_priv_info);
110
}
111

  
112
device_init(arm11mpcore_register_devices)
b/hw/arm_boot.c
31 31
/* Entry point for secondary CPUs.  Enable interrupt controller and
32 32
   Issue WFI until start address is written to system controller.  */
33 33
static uint32_t smpboot[] = {
34
  0xe3a00201, /* mov     r0, #0x10000000 */
35
  0xe3800601, /* orr     r0, r0, #0x001000000 */
34
  0xe59f0020, /* ldr     r0, privbase */
36 35
  0xe3a01001, /* mov     r1, #1 */
37 36
  0xe5801100, /* str     r1, [r0, #0x100] */
38 37
  0xe3a00201, /* mov     r0, #0x10000000 */
......
41 40
  0xe5901000, /* ldr     r1, [r0] */
42 41
  0xe1110001, /* tst     r1, r1 */
43 42
  0x0afffffb, /* beq     <wfi> */
44
  0xe12fff11  /* bx      r1 */
43
  0xe12fff11, /* bx      r1 */
44
  0 /* privbase: Private memory region base address.  */
45 45
};
46 46

  
47 47
#define WRITE_WORD(p, value) do { \
......
268 268
        rom_add_blob_fixed("bootloader", bootloader, sizeof(bootloader),
269 269
                           info->loader_start);
270 270
        if (info->nb_cpus > 1) {
271
            smpboot[10] = info->smp_priv_base;
271 272
            for (n = 0; n < sizeof(smpboot) / 4; n++) {
272 273
                smpboot[n] = tswap32(smpboot[n]);
273 274
            }
b/hw/arm_gic.c
607 607
    switch (offset) {
608 608
    case 0x00: /* Control */
609 609
        s->cpu_enabled[cpu] = (value & 1);
610
        DPRINTF("CPU %sabled\n", s->cpu_enabled ? "En" : "Dis");
610
        DPRINTF("CPU %d %sabled\n", cpu, s->cpu_enabled ? "En" : "Dis");
611 611
        break;
612 612
    case 0x04: /* Priority mask */
613 613
        s->priority_mask[cpu] = (value & 0xff);
b/hw/mpcore.c
1 1
/*
2
 * ARM MPCore internal peripheral emulation.
2
 * ARM MPCore internal peripheral emulation (common code).
3 3
 *
4 4
 * Copyright (c) 2006-2007 CodeSourcery.
5 5
 * Written by Paul Brook
......
10 10
#include "sysbus.h"
11 11
#include "qemu-timer.h"
12 12

  
13
#define MPCORE_PRIV_BASE  0x10100000
14 13
#define NCPU 4
15
/* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
16
   (+ 32 internal).  However my test chip only exposes/reports 32.
17
   More importantly Linux falls over if more than 32 are present!  */
18
#define GIC_NIRQ 64
19 14

  
20 15
static inline int
21 16
gic_get_current_cpu(void)
......
288 283
    }
289 284
    return 0;
290 285
}
291

  
292
/* Dummy PIC to route IRQ lines.  The baseboard has 4 independent IRQ
293
   controllers.  The output of these, plus some of the raw input lines
294
   are fed into a single SMP-aware interrupt controller on the CPU.  */
295
typedef struct {
296
    SysBusDevice busdev;
297
    qemu_irq cpuic[32];
298
    qemu_irq rvic[4][64];
299
    uint32_t num_cpu;
300
} mpcore_rirq_state;
301

  
302
/* Map baseboard IRQs onto CPU IRQ lines.  */
303
static const int mpcore_irq_map[32] = {
304
    -1, -1, -1, -1,  1,  2, -1, -1,
305
    -1, -1,  6, -1,  4,  5, -1, -1,
306
    -1, 14, 15,  0,  7,  8, -1, -1,
307
    -1, -1, -1, -1,  9,  3, -1, -1,
308
};
309

  
310
static void mpcore_rirq_set_irq(void *opaque, int irq, int level)
311
{
312
    mpcore_rirq_state *s = (mpcore_rirq_state *)opaque;
313
    int i;
314

  
315
    for (i = 0; i < 4; i++) {
316
        qemu_set_irq(s->rvic[i][irq], level);
317
    }
318
    if (irq < 32) {
319
        irq = mpcore_irq_map[irq];
320
        if (irq >= 0) {
321
            qemu_set_irq(s->cpuic[irq], level);
322
        }
323
    }
324
}
325

  
326
static int realview_mpcore_init(SysBusDevice *dev)
327
{
328
    mpcore_rirq_state *s = FROM_SYSBUS(mpcore_rirq_state, dev);
329
    DeviceState *gic;
330
    DeviceState *priv;
331
    SysBusDevice *bus_priv;
332
    int n;
333
    int i;
334

  
335
    priv = qdev_create(NULL, "arm11mpcore_priv");
336
    qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu);
337
    qdev_init_nofail(priv);
338
    bus_priv = sysbus_from_qdev(priv);
339
    sysbus_mmio_map(bus_priv, 0, MPCORE_PRIV_BASE);
340
    sysbus_pass_irq(dev, bus_priv);
341
    for (i = 0; i < 32; i++) {
342
        s->cpuic[i] = qdev_get_gpio_in(priv, i);
343
    }
344
    /* ??? IRQ routing is hardcoded to "normal" mode.  */
345
    for (n = 0; n < 4; n++) {
346
        gic = sysbus_create_simple("realview_gic", 0x10040000 + n * 0x10000,
347
                                   s->cpuic[10 + n]);
348
        for (i = 0; i < 64; i++) {
349
            s->rvic[n][i] = qdev_get_gpio_in(gic, i);
350
        }
351
    }
352
    qdev_init_gpio_in(&dev->qdev, mpcore_rirq_set_irq, 64);
353
    return 0;
354
}
355

  
356
static SysBusDeviceInfo mpcore_rirq_info = {
357
    .init = realview_mpcore_init,
358
    .qdev.name  = "realview_mpcore",
359
    .qdev.size  = sizeof(mpcore_rirq_state),
360
    .qdev.props = (Property[]) {
361
        DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1),
362
        DEFINE_PROP_END_OF_LIST(),
363
    }
364
};
365

  
366
static SysBusDeviceInfo mpcore_priv_info = {
367
    .init = mpcore_priv_init,
368
    .qdev.name  = "arm11mpcore_priv",
369
    .qdev.size  = sizeof(mpcore_priv_state),
370
    .qdev.props = (Property[]) {
371
        DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
372
        DEFINE_PROP_END_OF_LIST(),
373
    }
374
};
375

  
376
static void mpcore_register_devices(void)
377
{
378
    sysbus_register_withprop(&mpcore_rirq_info);
379
    sysbus_register_withprop(&mpcore_priv_info);
380
}
381

  
382
device_init(mpcore_register_devices)
b/hw/realview.c
34 34
  env->regs[15] = SMP_BOOT_ADDR;
35 35
}
36 36

  
37
/* The following two lists must be consistent.  */
37 38
enum realview_board_type {
38 39
    BOARD_EB,
39 40
    BOARD_EB_MPCORE,
40
    BOARD_PB_A8
41
    BOARD_PB_A8,
42
    BOARD_PBX_A9,
43
};
44

  
45
int realview_board_id[] = {
46
    0x33b,
47
    0x33b,
48
    0x769,
49
    0x76d
41 50
};
42 51

  
43 52
static void realview_init(ram_addr_t ram_size,
......
57 66
    int n;
58 67
    int done_nic = 0;
59 68
    qemu_irq cpu_irq[4];
60
    int is_mpcore = (board_type == BOARD_EB_MPCORE);
61
    int is_pb = (board_type == BOARD_PB_A8);
69
    int is_mpcore = 0;
70
    int is_pb = 0;
62 71
    uint32_t proc_id = 0;
63 72
    uint32_t sys_id;
64 73
    ram_addr_t low_ram_size;
65 74

  
75
    switch (board_type) {
76
    case BOARD_EB:
77
        break;
78
    case BOARD_EB_MPCORE:
79
        is_mpcore = 1;
80
        break;
81
    case BOARD_PB_A8:
82
        is_pb = 1;
83
        break;
84
    case BOARD_PBX_A9:
85
        is_mpcore = 1;
86
        is_pb = 1;
87
        break;
88
    }
66 89
    for (n = 0; n < smp_cpus; n++) {
67 90
        env = cpu_init(cpu_model);
68 91
        if (!env) {
......
76 99
        }
77 100
    }
78 101
    if (arm_feature(env, ARM_FEATURE_V7)) {
79
        proc_id = 0x0e000000;
102
        if (is_mpcore) {
103
            proc_id = 0x0c000000;
104
        } else {
105
            proc_id = 0x0e000000;
106
        }
80 107
    } else if (arm_feature(env, ARM_FEATURE_V6K)) {
81 108
        proc_id = 0x06000000;
82 109
    } else if (arm_feature(env, ARM_FEATURE_V6)) {
......
104 131
    arm_sysctl_init(0x10000000, sys_id, proc_id);
105 132

  
106 133
    if (is_mpcore) {
107
        dev = qdev_create(NULL, "realview_mpcore");
134
        dev = qdev_create(NULL, is_pb ? "a9mpcore_priv": "realview_mpcore");
108 135
        qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
109 136
        qdev_init_nofail(dev);
110 137
        busdev = sysbus_from_qdev(dev);
138
        if (is_pb) {
139
            realview_binfo.smp_priv_base = 0x1f000000;
140
        } else {
141
            realview_binfo.smp_priv_base = 0x10100000;
142
        }
143
        sysbus_mmio_map(busdev, 0, realview_binfo.smp_priv_base);
111 144
        for (n = 0; n < smp_cpus; n++) {
112 145
            sysbus_connect_irq(busdev, n, cpu_irq[n]);
113 146
        }
......
238 271
    realview_binfo.kernel_cmdline = kernel_cmdline;
239 272
    realview_binfo.initrd_filename = initrd_filename;
240 273
    realview_binfo.nb_cpus = smp_cpus;
241
    realview_binfo.board_id = is_pb ? 0x769 : 0x33b;
274
    realview_binfo.board_id = realview_board_id[board_type];
242 275
    realview_binfo.loader_start = is_pb ? 0x70000000 : 0;
243 276
    arm_load_kernel(first_cpu, &realview_binfo);
244 277
}
......
279 312
                  initrd_filename, cpu_model, BOARD_PB_A8);
280 313
}
281 314

  
315
static void realview_pbx_a9_init(ram_addr_t ram_size,
316
                     const char *boot_device,
317
                     const char *kernel_filename, const char *kernel_cmdline,
318
                     const char *initrd_filename, const char *cpu_model)
319
{
320
    if (!cpu_model) {
321
        cpu_model = "cortex-a9";
322
    }
323
    realview_init(ram_size, boot_device, kernel_filename, kernel_cmdline,
324
                  initrd_filename, cpu_model, BOARD_PBX_A9);
325
}
326

  
282 327
static QEMUMachine realview_eb_machine = {
283 328
    .name = "realview-eb",
284 329
    .desc = "ARM RealView Emulation Baseboard (ARM926EJ-S)",
......
298 343
    .name = "realview-pb-a8",
299 344
    .desc = "ARM RealView Platform Baseboard for Cortex-A8",
300 345
    .init = realview_pb_a8_init,
346
};
347

  
348
static QEMUMachine realview_pbx_a9_machine = {
349
    .name = "realview-pbx-a9",
350
    .desc = "ARM RealView Platform Baseboard Explore for Cortex-A9",
351
    .init = realview_pbx_a9_init,
301 352
    .use_scsi = 1,
353
    .max_cpus = 4,
302 354
};
303 355

  
304 356
static void realview_machine_init(void)
......
306 358
    qemu_register_machine(&realview_eb_machine);
307 359
    qemu_register_machine(&realview_eb_mpcore_machine);
308 360
    qemu_register_machine(&realview_pb_a8_machine);
361
    qemu_register_machine(&realview_pbx_a9_machine);
309 362
}
310 363

  
311 364
machine_init(realview_machine_init);
b/qemu-doc.texi
1664 1664

  
1665 1665
@itemize @minus
1666 1666
@item
1667
ARM926E, ARM1136, ARM11MPCORE or Cortex-A8 CPU
1667
ARM926E, ARM1136, ARM11MPCore, Cortex-A8 or Cortex-A9 MPCore CPU
1668 1668
@item
1669 1669
ARM AMBA Generic/Distributed Interrupt Controller
1670 1670
@item

Also available in: Unified diff