1 /* 2 * MAX78000 True Random Number Generator 3 * 4 * Copyright (c) 2025 Jackson Donaldson <jcksn@duck.com> 5 * 6 * SPDX-License-Identifier: GPL-2.0-or-later 7 */ 8 9 #include "qemu/osdep.h" 10 #include "qemu/log.h" 11 #include "trace.h" 12 #include "hw/irq.h" 13 #include "migration/vmstate.h" 14 #include "hw/misc/max78000_trng.h" 15 #include "qemu/guest-random.h" 16 17 static uint64_t max78000_trng_read(void *opaque, hwaddr addr, 18 unsigned int size) 19 { 20 uint32_t data; 21 22 Max78000TrngState *s = opaque; 23 switch (addr) { 24 case CTRL: 25 return s->ctrl; 26 27 case STATUS: 28 return 1; 29 30 case DATA: 31 /* 32 * When interrupts are enabled, reading random data should cause a 33 * new interrupt to be generated; since there's always a random number 34 * available, we could qemu_set_irq(s->irq, s->ctrl & RND_IE). Because 35 * of how trng_write is set up, this is always a noop, so don't 36 */ 37 qemu_guest_getrandom_nofail(&data, sizeof(data)); 38 return data; 39 40 default: 41 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" 42 HWADDR_PRIx "\n", __func__, addr); 43 break; 44 } 45 return 0; 46 } 47 48 static void max78000_trng_write(void *opaque, hwaddr addr, 49 uint64_t val64, unsigned int size) 50 { 51 Max78000TrngState *s = opaque; 52 uint32_t val = val64; 53 switch (addr) { 54 case CTRL: 55 /* TODO: implement AES keygen */ 56 s->ctrl = val; 57 58 /* 59 * This device models random number generation as taking 0 time. 60 * A new random number is always available, so the condition for the 61 * RND interrupt is always fulfilled; we can just set irq to 1. 62 */ 63 if (val & RND_IE) { 64 qemu_set_irq(s->irq, 1); 65 } else{ 66 qemu_set_irq(s->irq, 0); 67 } 68 break; 69 70 default: 71 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" 72 HWADDR_PRIx "\n", __func__, addr); 73 break; 74 } 75 } 76 77 static void max78000_trng_reset_hold(Object *obj, ResetType type) 78 { 79 Max78000TrngState *s = MAX78000_TRNG(obj); 80 s->ctrl = 0; 81 s->status = 0; 82 s->data = 0; 83 } 84 85 static const MemoryRegionOps max78000_trng_ops = { 86 .read = max78000_trng_read, 87 .write = max78000_trng_write, 88 .endianness = DEVICE_LITTLE_ENDIAN, 89 .valid.min_access_size = 4, 90 .valid.max_access_size = 4, 91 }; 92 93 static const VMStateDescription max78000_trng_vmstate = { 94 .name = TYPE_MAX78000_TRNG, 95 .version_id = 1, 96 .minimum_version_id = 1, 97 .fields = (const VMStateField[]) { 98 VMSTATE_UINT32(ctrl, Max78000TrngState), 99 VMSTATE_UINT32(status, Max78000TrngState), 100 VMSTATE_UINT32(data, Max78000TrngState), 101 VMSTATE_END_OF_LIST() 102 } 103 }; 104 105 static void max78000_trng_init(Object *obj) 106 { 107 Max78000TrngState *s = MAX78000_TRNG(obj); 108 sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); 109 110 memory_region_init_io(&s->mmio, obj, &max78000_trng_ops, s, 111 TYPE_MAX78000_TRNG, 0x1000); 112 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); 113 114 } 115 116 static void max78000_trng_class_init(ObjectClass *klass, const void *data) 117 { 118 ResettableClass *rc = RESETTABLE_CLASS(klass); 119 DeviceClass *dc = DEVICE_CLASS(klass); 120 121 rc->phases.hold = max78000_trng_reset_hold; 122 dc->vmsd = &max78000_trng_vmstate; 123 124 } 125 126 static const TypeInfo max78000_trng_info = { 127 .name = TYPE_MAX78000_TRNG, 128 .parent = TYPE_SYS_BUS_DEVICE, 129 .instance_size = sizeof(Max78000TrngState), 130 .instance_init = max78000_trng_init, 131 .class_init = max78000_trng_class_init, 132 }; 133 134 static void max78000_trng_register_types(void) 135 { 136 type_register_static(&max78000_trng_info); 137 } 138 139 type_init(max78000_trng_register_types) 140