typedef struct {
SysBusDevice busdev;
+ MemoryRegion iomem;
+ qemu_irq pl110_mux_ctrl;
+
uint32_t sys_id;
uint32_t leds;
uint16_t lockval;
uint32_t sys_cfgdata;
uint32_t sys_cfgctrl;
uint32_t sys_cfgstat;
+ uint32_t sys_clcd;
} arm_sysctl_state;
static const VMStateDescription vmstate_arm_sysctl = {
.name = "realview_sysctl",
- .version_id = 2,
+ .version_id = 3,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT32(leds, arm_sysctl_state),
VMSTATE_UINT32_V(sys_cfgdata, arm_sysctl_state, 2),
VMSTATE_UINT32_V(sys_cfgctrl, arm_sysctl_state, 2),
VMSTATE_UINT32_V(sys_cfgstat, arm_sysctl_state, 2),
+ VMSTATE_UINT32_V(sys_clcd, arm_sysctl_state, 3),
VMSTATE_END_OF_LIST()
}
};
s->cfgdata2 = 0;
s->flags = 0;
s->resetlevel = 0;
+ if (board_id(s) == BOARD_ID_VEXPRESS) {
+ /* On VExpress this register will RAZ/WI */
+ s->sys_clcd = 0;
+ } else {
+ /* All others: CLCDID 0x1f, indicating VGA */
+ s->sys_clcd = 0x1f00;
+ }
}
-static uint32_t arm_sysctl_read(void *opaque, target_phys_addr_t offset)
+static uint64_t arm_sysctl_read(void *opaque, target_phys_addr_t offset,
+ unsigned size)
{
arm_sysctl_state *s = (arm_sysctl_state *)opaque;
case 0x4c: /* FLASH */
return 0;
case 0x50: /* CLCD */
- return 0x1000;
+ return s->sys_clcd;
case 0x54: /* CLCDSER */
return 0;
case 0x58: /* BOOTCS */
}
static void arm_sysctl_write(void *opaque, target_phys_addr_t offset,
- uint32_t val)
+ uint64_t val, unsigned size)
{
arm_sysctl_state *s = (arm_sysctl_state *)opaque;
/* nothing to do. */
break;
case 0x4c: /* FLASH */
+ break;
case 0x50: /* CLCD */
+ switch (board_id(s)) {
+ case BOARD_ID_PB926:
+ /* On 926 bits 13:8 are R/O, bits 1:0 control
+ * the mux that defines how to interpret the PL110
+ * graphics format, and other bits are r/w but we
+ * don't implement them to do anything.
+ */
+ s->sys_clcd &= 0x3f00;
+ s->sys_clcd |= val & ~0x3f00;
+ qemu_set_irq(s->pl110_mux_ctrl, val & 3);
+ break;
+ case BOARD_ID_EB:
+ /* The EB is the same except that there is no mux since
+ * the EB has a PL111.
+ */
+ s->sys_clcd &= 0x3f00;
+ s->sys_clcd |= val & ~0x3f00;
+ break;
+ case BOARD_ID_PBA8:
+ case BOARD_ID_PBX:
+ /* On PBA8 and PBX bit 7 is r/w and all other bits
+ * are either r/o or RAZ/WI.
+ */
+ s->sys_clcd &= (1 << 7);
+ s->sys_clcd |= val & ~(1 << 7);
+ break;
+ case BOARD_ID_VEXPRESS:
+ default:
+ /* On VExpress this register is unimplemented and will RAZ/WI */
+ break;
+ }
case 0x54: /* CLCDSER */
case 0x64: /* DMAPSR0 */
case 0x68: /* DMAPSR1 */
}
}
-static CPUReadMemoryFunc * const arm_sysctl_readfn[] = {
- arm_sysctl_read,
- arm_sysctl_read,
- arm_sysctl_read
-};
-
-static CPUWriteMemoryFunc * const arm_sysctl_writefn[] = {
- arm_sysctl_write,
- arm_sysctl_write,
- arm_sysctl_write
+static const MemoryRegionOps arm_sysctl_ops = {
+ .read = arm_sysctl_read,
+ .write = arm_sysctl_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
};
static void arm_sysctl_gpio_set(void *opaque, int line, int level)
static int arm_sysctl_init1(SysBusDevice *dev)
{
arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev);
- int iomemtype;
- iomemtype = cpu_register_io_memory(arm_sysctl_readfn,
- arm_sysctl_writefn, s,
- DEVICE_NATIVE_ENDIAN);
- sysbus_init_mmio(dev, 0x1000, iomemtype);
+ memory_region_init_io(&s->iomem, &arm_sysctl_ops, s, "arm-sysctl", 0x1000);
+ sysbus_init_mmio_region(dev, &s->iomem);
qdev_init_gpio_in(&s->busdev.qdev, arm_sysctl_gpio_set, 2);
- /* ??? Save/restore. */
+ qdev_init_gpio_out(&s->busdev.qdev, &s->pl110_mux_ctrl, 1);
return 0;
}