#include "qemu/osdep.h" #include "hw/core/sysbus.h" #include "qemu/log.h" #include "qom/object.h" #define TYPE_S5L8950X_CHIPID "s5l8950x-chipid" OBJECT_DECLARE_SIMPLE_TYPE(S5L8950XChipIdState, S5L8950X_CHIPID) struct S5L8950XChipIdState { SysBusDevice parent_obj; MemoryRegion iomem; }; static uint64_t s5l8950x_chipid_read(void *opaque, hwaddr offset, unsigned size) { switch (offset) { case 0x00: /* n41ap: CPFM 0x03, SCEP 0x10, BDID 0x00, IBFL 0x00. */ return 0x200D; case 0x04: /* * SecureROM leaves the high handoff bit asserted before entering * iBSS. Early iBoot aborts immediately when this latch is clear. */ return 0x80000000; case 0x08: return 0xDEADBEEF; case 0x0C: return 0xCAFEBABE; case 0x10: return 0x1; case 0x14: return 0x1; case 0x18: return 0x1; case 0x1C: return 0x0; case 0x20: return 0x1; case 0x24: /* CPRV 0x20. Also contributes to the synthetic ECID. */ return 0x4000; default: return 0; } } static void s5l8950x_chipid_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) { qemu_log_mask(LOG_UNIMP, "%s: Unimplemented write to offset 0x%" HWADDR_PRIx " with value 0x%" PRIx64 "\n", __func__, offset, val); } static const MemoryRegionOps s5l8950x_chipid_ops = { .read = s5l8950x_chipid_read, .write = s5l8950x_chipid_write, .endianness = DEVICE_LITTLE_ENDIAN, .impl = { .min_access_size = 4, .max_access_size = 4, }, }; static void s5l8950x_chipid_init(Object *obj) { S5L8950XChipIdState *s = S5L8950X_CHIPID(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); memory_region_init_io(&s->iomem, obj, &s5l8950x_chipid_ops, s, TYPE_S5L8950X_CHIPID, 0x100); sysbus_init_mmio(sbd, &s->iomem); } static const TypeInfo s5l8950x_chipid_info = { .name = TYPE_S5L8950X_CHIPID, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(S5L8950XChipIdState), .instance_init = s5l8950x_chipid_init, }; static void s5l8950x_chipid_register_types(void) { type_register_static(&s5l8950x_chipid_info); } type_init(s5l8950x_chipid_register_types)