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