1 /* 2 * ASPEED GFX Controller 3 * 4 * Copyright (C) 2023 IBM Corp. 5 * 6 * This code is licensed under the GPL version 2 or later. See 7 * the COPYING file in the top-level directory. 8 */ 9 10 #include "qemu/osdep.h" 11 #include "qemu/log.h" 12 #include "qemu/error-report.h" 13 #include "hw/misc/aspeed_gfx.h" 14 #include "qapi/error.h" 15 #include "migration/vmstate.h" 16 17 #include "trace.h" 18 19 static uint64_t aspeed_gfx_read(void *opaque, hwaddr addr, 20 unsigned int size) 21 { 22 AspeedGFXState *s = ASPEED_GFX(opaque); 23 uint64_t val = 0; 24 25 addr >>= 2; 26 27 if (addr >= ASPEED_GFX_NR_REGS) { 28 qemu_log_mask(LOG_GUEST_ERROR, 29 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", 30 __func__, addr << 2); 31 } else { 32 val = s->regs[addr]; 33 } 34 35 trace_aspeed_gfx_read(addr << 2, val); 36 37 return val; 38 } 39 40 static void aspeed_gfx_write(void *opaque, hwaddr addr, uint64_t data, 41 unsigned int size) 42 { 43 AspeedGFXState *s = ASPEED_GFX(opaque); 44 45 trace_aspeed_gfx_write(addr, data); 46 47 addr >>= 2; 48 49 if (addr >= ASPEED_GFX_NR_REGS) { 50 qemu_log_mask(LOG_GUEST_ERROR, 51 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n", 52 __func__, addr << 2); 53 return; 54 } 55 56 s->regs[addr] = data; 57 } 58 59 static const MemoryRegionOps aspeed_gfx_ops = { 60 .read = aspeed_gfx_read, 61 .write = aspeed_gfx_write, 62 .endianness = DEVICE_LITTLE_ENDIAN, 63 .valid = { 64 .min_access_size = 1, 65 .max_access_size = 4, 66 }, 67 }; 68 69 static void aspeed_gfx_reset(DeviceState *dev) 70 { 71 struct AspeedGFXState *s = ASPEED_GFX(dev); 72 73 memset(s->regs, 0, sizeof(s->regs)); 74 } 75 76 static void aspeed_gfx_realize(DeviceState *dev, Error **errp) 77 { 78 AspeedGFXState *s = ASPEED_GFX(dev); 79 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 80 81 sysbus_init_irq(sbd, &s->irq); 82 83 memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_gfx_ops, s, 84 TYPE_ASPEED_GFX, 0x1000); 85 86 sysbus_init_mmio(sbd, &s->iomem); 87 } 88 89 static const VMStateDescription vmstate_aspeed_gfx = { 90 .name = TYPE_ASPEED_GFX, 91 .version_id = 1, 92 .minimum_version_id = 1, 93 .fields = (VMStateField[]) { 94 VMSTATE_UINT32_ARRAY(regs, AspeedGFXState, ASPEED_GFX_NR_REGS), 95 VMSTATE_END_OF_LIST(), 96 } 97 }; 98 99 static void aspeed_gfx_class_init(ObjectClass *klass, void *data) 100 { 101 DeviceClass *dc = DEVICE_CLASS(klass); 102 103 dc->realize = aspeed_gfx_realize; 104 device_class_set_legacy_reset(dc, aspeed_gfx_reset); 105 dc->desc = "Aspeed GFX Controller"; 106 dc->vmsd = &vmstate_aspeed_gfx; 107 } 108 109 static const TypeInfo aspeed_gfx_info = { 110 .name = TYPE_ASPEED_GFX, 111 .parent = TYPE_SYS_BUS_DEVICE, 112 .instance_size = sizeof(AspeedGFXState), 113 .class_init = aspeed_gfx_class_init, 114 }; 115 116 static void aspeed_gfx_register_types(void) 117 { 118 type_register_static(&aspeed_gfx_info); 119 } 120 121 type_init(aspeed_gfx_register_types); 122