*/
#include "hw.h"
-#include "qemu-timer.h"
+#include "qemu/timer.h"
#include "sysbus.h"
#include "primecell.h"
-#include "sysemu.h"
+#include "sysemu/sysemu.h"
#define LOCK_VALUE 0xa05f
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, hwaddr 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 */
return s->sys_cfgstat;
default:
bad_reg:
- printf ("arm_sysctl_read: Bad register offset 0x%x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "arm_sysctl_read: Bad register offset 0x%x\n",
+ (int)offset);
return 0;
}
}
-static void arm_sysctl_write(void *opaque, target_phys_addr_t offset,
- uint32_t val)
+static void arm_sysctl_write(void *opaque, hwaddr offset,
+ uint64_t val, unsigned size)
{
arm_sysctl_state *s = (arm_sysctl_state *)opaque;
s->nvflags &= ~val;
break;
case 0x40: /* RESETCTL */
- if (board_id(s) == BOARD_ID_VEXPRESS) {
+ switch (board_id(s)) {
+ case BOARD_ID_PB926:
+ if (s->lockval == LOCK_VALUE) {
+ s->resetlevel = val;
+ if (val & 0x100) {
+ qemu_system_reset_request();
+ }
+ }
+ break;
+ case BOARD_ID_PBX:
+ case BOARD_ID_PBA8:
+ if (s->lockval == LOCK_VALUE) {
+ s->resetlevel = val;
+ if (val & 0x04) {
+ qemu_system_reset_request();
+ }
+ }
+ break;
+ case BOARD_ID_VEXPRESS:
+ case BOARD_ID_EB:
+ default:
/* reserved: RAZ/WI */
break;
}
- if (s->lockval == LOCK_VALUE) {
- s->resetlevel = val;
- if (val & 0x100)
- qemu_system_reset_request ();
- }
break;
case 0x44: /* PCICTL */
/* 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 */
return;
default:
bad_reg:
- printf ("arm_sysctl_write: Bad register offset 0x%x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "arm_sysctl_write: Bad register offset 0x%x\n",
+ (int)offset);
return;
}
}
-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)
+static int arm_sysctl_init(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(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;
}
-/* Legacy helper function. */
-void arm_sysctl_init(uint32_t base, uint32_t sys_id, uint32_t proc_id)
+static Property arm_sysctl_properties[] = {
+ DEFINE_PROP_UINT32("sys_id", arm_sysctl_state, sys_id, 0),
+ DEFINE_PROP_UINT32("proc_id", arm_sysctl_state, proc_id, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void arm_sysctl_class_init(ObjectClass *klass, void *data)
{
- DeviceState *dev;
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- dev = qdev_create(NULL, "realview_sysctl");
- qdev_prop_set_uint32(dev, "sys_id", sys_id);
- qdev_init_nofail(dev);
- qdev_prop_set_uint32(dev, "proc_id", proc_id);
- sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+ k->init = arm_sysctl_init;
+ dc->reset = arm_sysctl_reset;
+ dc->vmsd = &vmstate_arm_sysctl;
+ dc->props = arm_sysctl_properties;
}
-static SysBusDeviceInfo arm_sysctl_info = {
- .init = arm_sysctl_init1,
- .qdev.name = "realview_sysctl",
- .qdev.size = sizeof(arm_sysctl_state),
- .qdev.vmsd = &vmstate_arm_sysctl,
- .qdev.reset = arm_sysctl_reset,
- .qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("sys_id", arm_sysctl_state, sys_id, 0),
- DEFINE_PROP_UINT32("proc_id", arm_sysctl_state, proc_id, 0),
- DEFINE_PROP_END_OF_LIST(),
- }
+static const TypeInfo arm_sysctl_info = {
+ .name = "realview_sysctl",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(arm_sysctl_state),
+ .class_init = arm_sysctl_class_init,
};
-static void arm_sysctl_register_devices(void)
+static void arm_sysctl_register_types(void)
{
- sysbus_register_withprop(&arm_sysctl_info);
+ type_register_static(&arm_sysctl_info);
}
-device_init(arm_sysctl_register_devices)
+type_init(arm_sysctl_register_types)