1 /* 2 * nRF51 Random Number Generator 3 * 4 * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.1.pdf 5 * 6 * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de> 7 * 8 * This code is licensed under the GPL version 2 or later. See 9 * the COPYING file in the top-level directory. 10 */ 11 12 #include "qemu/osdep.h" 13 #include "qemu/log.h" 14 #include "qemu/module.h" 15 #include "qapi/error.h" 16 #include "hw/arm/nrf51.h" 17 #include "hw/irq.h" 18 #include "hw/misc/nrf51_rng.h" 19 #include "qemu/guest-random.h" 20 21 static void update_irq(NRF51RNGState *s) 22 { 23 bool irq = s->interrupt_enabled && s->event_valrdy; 24 qemu_set_irq(s->irq, irq); 25 } 26 27 static uint64_t rng_read(void *opaque, hwaddr offset, unsigned int size) 28 { 29 NRF51RNGState *s = NRF51_RNG(opaque); 30 uint64_t r = 0; 31 32 switch (offset) { 33 case NRF51_RNG_EVENT_VALRDY: 34 r = s->event_valrdy; 35 break; 36 case NRF51_RNG_REG_SHORTS: 37 r = s->shortcut_stop_on_valrdy; 38 break; 39 case NRF51_RNG_REG_INTEN: 40 case NRF51_RNG_REG_INTENSET: 41 case NRF51_RNG_REG_INTENCLR: 42 r = s->interrupt_enabled; 43 break; 44 case NRF51_RNG_REG_CONFIG: 45 r = s->filter_enabled; 46 break; 47 case NRF51_RNG_REG_VALUE: 48 r = s->value; 49 break; 50 51 default: 52 qemu_log_mask(LOG_GUEST_ERROR, 53 "%s: bad read offset 0x%" HWADDR_PRIx "\n", 54 __func__, offset); 55 } 56 57 return r; 58 } 59 60 static int64_t calc_next_timeout(NRF51RNGState *s) 61 { 62 int64_t timeout = qemu_clock_get_us(QEMU_CLOCK_VIRTUAL); 63 if (s->filter_enabled) { 64 timeout += s->period_filtered_us; 65 } else { 66 timeout += s->period_unfiltered_us; 67 } 68 69 return timeout; 70 } 71 72 73 static void rng_update_timer(NRF51RNGState *s) 74 { 75 if (s->active) { 76 timer_mod(&s->timer, calc_next_timeout(s)); 77 } else { 78 timer_del(&s->timer); 79 } 80 } 81 82 83 static void rng_write(void *opaque, hwaddr offset, 84 uint64_t value, unsigned int size) 85 { 86 NRF51RNGState *s = NRF51_RNG(opaque); 87 88 switch (offset) { 89 case NRF51_RNG_TASK_START: 90 if (value == NRF51_TRIGGER_TASK) { 91 s->active = 1; 92 rng_update_timer(s); 93 } 94 break; 95 case NRF51_RNG_TASK_STOP: 96 if (value == NRF51_TRIGGER_TASK) { 97 s->active = 0; 98 rng_update_timer(s); 99 } 100 break; 101 case NRF51_RNG_EVENT_VALRDY: 102 if (value == NRF51_EVENT_CLEAR) { 103 s->event_valrdy = 0; 104 } 105 break; 106 case NRF51_RNG_REG_SHORTS: 107 s->shortcut_stop_on_valrdy = 108 (value & BIT_MASK(NRF51_RNG_REG_SHORTS_VALRDY_STOP)) ? 1 : 0; 109 break; 110 case NRF51_RNG_REG_INTEN: 111 s->interrupt_enabled = 112 (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) ? 1 : 0; 113 break; 114 case NRF51_RNG_REG_INTENSET: 115 if (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) { 116 s->interrupt_enabled = 1; 117 } 118 break; 119 case NRF51_RNG_REG_INTENCLR: 120 if (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) { 121 s->interrupt_enabled = 0; 122 } 123 break; 124 case NRF51_RNG_REG_CONFIG: 125 s->filter_enabled = 126 (value & BIT_MASK(NRF51_RNG_REG_CONFIG_DECEN)) ? 1 : 0; 127 break; 128 129 default: 130 qemu_log_mask(LOG_GUEST_ERROR, 131 "%s: bad write offset 0x%" HWADDR_PRIx "\n", 132 __func__, offset); 133 } 134 135 update_irq(s); 136 } 137 138 static const MemoryRegionOps rng_ops = { 139 .read = rng_read, 140 .write = rng_write, 141 .endianness = DEVICE_LITTLE_ENDIAN, 142 .impl.min_access_size = 4, 143 .impl.max_access_size = 4 144 }; 145 146 static void nrf51_rng_timer_expire(void *opaque) 147 { 148 NRF51RNGState *s = NRF51_RNG(opaque); 149 150 qemu_guest_getrandom_nofail(&s->value, 1); 151 152 s->event_valrdy = 1; 153 qemu_set_irq(s->eep_valrdy, 1); 154 155 if (s->shortcut_stop_on_valrdy) { 156 s->active = 0; 157 } 158 159 rng_update_timer(s); 160 update_irq(s); 161 } 162 163 static void nrf51_rng_tep_start(void *opaque, int n, int level) 164 { 165 NRF51RNGState *s = NRF51_RNG(opaque); 166 167 if (level) { 168 s->active = 1; 169 rng_update_timer(s); 170 } 171 } 172 173 static void nrf51_rng_tep_stop(void *opaque, int n, int level) 174 { 175 NRF51RNGState *s = NRF51_RNG(opaque); 176 177 if (level) { 178 s->active = 0; 179 rng_update_timer(s); 180 } 181 } 182 183 184 static void nrf51_rng_init(Object *obj) 185 { 186 NRF51RNGState *s = NRF51_RNG(obj); 187 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 188 189 memory_region_init_io(&s->mmio, obj, &rng_ops, s, 190 TYPE_NRF51_RNG, NRF51_RNG_SIZE); 191 sysbus_init_mmio(sbd, &s->mmio); 192 193 timer_init_us(&s->timer, QEMU_CLOCK_VIRTUAL, nrf51_rng_timer_expire, s); 194 195 sysbus_init_irq(sbd, &s->irq); 196 197 /* Tasks */ 198 qdev_init_gpio_in_named(DEVICE(s), nrf51_rng_tep_start, "tep_start", 1); 199 qdev_init_gpio_in_named(DEVICE(s), nrf51_rng_tep_stop, "tep_stop", 1); 200 201 /* Events */ 202 qdev_init_gpio_out_named(DEVICE(s), &s->eep_valrdy, "eep_valrdy", 1); 203 } 204 205 static void nrf51_rng_reset(DeviceState *dev) 206 { 207 NRF51RNGState *s = NRF51_RNG(dev); 208 209 s->value = 0; 210 s->active = 0; 211 s->event_valrdy = 0; 212 s->shortcut_stop_on_valrdy = 0; 213 s->interrupt_enabled = 0; 214 s->filter_enabled = 0; 215 216 rng_update_timer(s); 217 } 218 219 220 static Property nrf51_rng_properties[] = { 221 DEFINE_PROP_UINT16("period_unfiltered_us", NRF51RNGState, 222 period_unfiltered_us, 167), 223 DEFINE_PROP_UINT16("period_filtered_us", NRF51RNGState, 224 period_filtered_us, 660), 225 DEFINE_PROP_END_OF_LIST(), 226 }; 227 228 static const VMStateDescription vmstate_rng = { 229 .name = "nrf51_soc.rng", 230 .version_id = 1, 231 .minimum_version_id = 1, 232 .fields = (VMStateField[]) { 233 VMSTATE_UINT32(active, NRF51RNGState), 234 VMSTATE_UINT32(event_valrdy, NRF51RNGState), 235 VMSTATE_UINT32(shortcut_stop_on_valrdy, NRF51RNGState), 236 VMSTATE_UINT32(interrupt_enabled, NRF51RNGState), 237 VMSTATE_UINT32(filter_enabled, NRF51RNGState), 238 VMSTATE_END_OF_LIST() 239 } 240 }; 241 242 static void nrf51_rng_class_init(ObjectClass *klass, void *data) 243 { 244 DeviceClass *dc = DEVICE_CLASS(klass); 245 246 dc->props = nrf51_rng_properties; 247 dc->vmsd = &vmstate_rng; 248 dc->reset = nrf51_rng_reset; 249 } 250 251 static const TypeInfo nrf51_rng_info = { 252 .name = TYPE_NRF51_RNG, 253 .parent = TYPE_SYS_BUS_DEVICE, 254 .instance_size = sizeof(NRF51RNGState), 255 .instance_init = nrf51_rng_init, 256 .class_init = nrf51_rng_class_init 257 }; 258 259 static void nrf51_rng_register_types(void) 260 { 261 type_register_static(&nrf51_rng_info); 262 } 263 264 type_init(nrf51_rng_register_types) 265