Revision 2a29ddee hw/armv7m_nvic.c

b/hw/armv7m_nvic.c
30 30
        int64_t tick;
31 31
        QEMUTimer *timer;
32 32
    } systick;
33
    MemoryRegion sysregmem;
34
    MemoryRegion gic_iomem_alias;
35
    MemoryRegion container;
33 36
    uint32_t num_irq;
34 37
} nvic_state;
35 38

  
39
static const uint8_t nvic_id[] = {
40
    0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1
41
};
42

  
36 43
/* qemu timers run at 1GHz.   We want something closer to 1MHz.  */
37 44
#define SYSTICK_SCALE 1000ULL
38 45

  
......
358 365
    case 0xd38: /* Bus Fault Address.  */
359 366
    case 0xd3c: /* Aux Fault Status.  */
360 367
        goto bad_reg;
368
    case 0xf00: /* Software Triggered Interrupt Register */
369
        if ((value & 0x1ff) < s->num_irq) {
370
            gic_set_pending_private(&s->gic, 0, value & 0x1ff);
371
        }
372
        break;
361 373
    default:
362 374
    bad_reg:
363 375
        hw_error("NVIC: Bad write offset 0x%x\n", offset);
364 376
    }
365 377
}
366 378

  
379
static uint64_t nvic_sysreg_read(void *opaque, target_phys_addr_t addr,
380
                                 unsigned size)
381
{
382
    /* At the moment we only support the ID registers for byte/word access.
383
     * This is not strictly correct as a few of the other registers also
384
     * allow byte access.
385
     */
386
    uint32_t offset = addr;
387
    if (offset >= 0xfe0) {
388
        if (offset & 3) {
389
            return 0;
390
        }
391
        return nvic_id[(offset - 0xfe0) >> 2];
392
    }
393
    if (size == 4) {
394
        return nvic_readl(opaque, offset);
395
    }
396
    hw_error("NVIC: Bad read of size %d at offset 0x%x\n", size, offset);
397
}
398

  
399
static void nvic_sysreg_write(void *opaque, target_phys_addr_t addr,
400
                              uint64_t value, unsigned size)
401
{
402
    uint32_t offset = addr;
403
    if (size == 4) {
404
        nvic_writel(opaque, offset, value);
405
        return;
406
    }
407
    hw_error("NVIC: Bad write of size %d at offset 0x%x\n", size, offset);
408
}
409

  
410
static const MemoryRegionOps nvic_sysreg_ops = {
411
    .read = nvic_sysreg_read,
412
    .write = nvic_sysreg_write,
413
    .endianness = DEVICE_NATIVE_ENDIAN,
414
};
415

  
367 416
static const VMStateDescription vmstate_nvic = {
368 417
    .name = "armv7m_nvic",
369 418
    .version_id = 1,
......
399 448
    /* The NVIC always has only one CPU */
400 449
    s->gic.num_cpu = 1;
401 450
    gic_init(&s->gic, s->num_irq);
402
    memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->gic.iomem);
451
    /* The NVIC and system controller register area looks like this:
452
     *  0..0xff : system control registers, including systick
453
     *  0x100..0xcff : GIC-like registers
454
     *  0xd00..0xfff : system control registers
455
     * We use overlaying to put the GIC like registers
456
     * over the top of the system control register region.
457
     */
458
    memory_region_init(&s->container, "nvic", 0x1000);
459
    /* The system register region goes at the bottom of the priority
460
     * stack as it covers the whole page.
461
     */
462
    memory_region_init_io(&s->sysregmem, &nvic_sysreg_ops, s,
463
                          "nvic_sysregs", 0x1000);
464
    memory_region_add_subregion(&s->container, 0, &s->sysregmem);
465
    /* Alias the GIC region so we can get only the section of it
466
     * we need, and layer it on top of the system register region.
467
     */
468
    memory_region_init_alias(&s->gic_iomem_alias, "nvic-gic", &s->gic.iomem,
469
                             0x100, 0xc00);
470
    memory_region_add_subregion_overlap(&s->container, 0x100, &s->gic.iomem, 1);
471
    /* Map the whole thing into system memory at the location required
472
     * by the v7M architecture.
473
     */
474
    memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->container);
403 475
    s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
404 476
    return 0;
405 477
}

Also available in: Unified diff