1 /* 2 * ARM11MPCore Snoop Control Unit (SCU) emulation 3 * 4 * Copyright (c) 2006-2007 CodeSourcery. 5 * Copyright (c) 2013 SUSE LINUX Products GmbH 6 * Written by Paul Brook and Andreas Färber 7 * 8 * This code is licensed under the GPL. 9 */ 10 11 #include "qemu/osdep.h" 12 #include "hw/misc/arm11scu.h" 13 #include "qemu/log.h" 14 #include "qemu/module.h" 15 16 static uint64_t mpcore_scu_read(void *opaque, hwaddr offset, 17 unsigned size) 18 { 19 ARM11SCUState *s = (ARM11SCUState *)opaque; 20 int id; 21 /* SCU */ 22 switch (offset) { 23 case 0x00: /* Control. */ 24 return s->control; 25 case 0x04: /* Configuration. */ 26 id = ((1 << s->num_cpu) - 1) << 4; 27 return id | (s->num_cpu - 1); 28 case 0x08: /* CPU status. */ 29 return 0; 30 case 0x0c: /* Invalidate all. */ 31 return 0; 32 default: 33 qemu_log_mask(LOG_GUEST_ERROR, 34 "mpcore_priv_read: Bad offset %x\n", (int)offset); 35 return 0; 36 } 37 } 38 39 static void mpcore_scu_write(void *opaque, hwaddr offset, 40 uint64_t value, unsigned size) 41 { 42 ARM11SCUState *s = (ARM11SCUState *)opaque; 43 /* SCU */ 44 switch (offset) { 45 case 0: /* Control register. */ 46 s->control = value & 1; 47 break; 48 case 0x0c: /* Invalidate all. */ 49 /* This is a no-op as cache is not emulated. */ 50 break; 51 default: 52 qemu_log_mask(LOG_GUEST_ERROR, 53 "mpcore_priv_read: Bad offset %x\n", (int)offset); 54 } 55 } 56 57 static const MemoryRegionOps mpcore_scu_ops = { 58 .read = mpcore_scu_read, 59 .write = mpcore_scu_write, 60 .endianness = DEVICE_NATIVE_ENDIAN, 61 }; 62 63 static void arm11_scu_realize(DeviceState *dev, Error **errp) 64 { 65 } 66 67 static void arm11_scu_init(Object *obj) 68 { 69 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 70 ARM11SCUState *s = ARM11_SCU(obj); 71 72 memory_region_init_io(&s->iomem, OBJECT(s), 73 &mpcore_scu_ops, s, "mpcore-scu", 0x100); 74 sysbus_init_mmio(sbd, &s->iomem); 75 } 76 77 static Property arm11_scu_properties[] = { 78 DEFINE_PROP_UINT32("num-cpu", ARM11SCUState, num_cpu, 1), 79 DEFINE_PROP_END_OF_LIST() 80 }; 81 82 static void arm11_scu_class_init(ObjectClass *oc, void *data) 83 { 84 DeviceClass *dc = DEVICE_CLASS(oc); 85 86 dc->realize = arm11_scu_realize; 87 dc->props = arm11_scu_properties; 88 } 89 90 static const TypeInfo arm11_scu_type_info = { 91 .name = TYPE_ARM11_SCU, 92 .parent = TYPE_SYS_BUS_DEVICE, 93 .instance_size = sizeof(ARM11SCUState), 94 .instance_init = arm11_scu_init, 95 .class_init = arm11_scu_class_init, 96 }; 97 98 static void arm11_scu_register_types(void) 99 { 100 type_register_static(&arm11_scu_type_info); 101 } 102 103 type_init(arm11_scu_register_types) 104