nbd: generalize usage of nbd_read
[qemu/ar7.git] / hw / misc / nrf51_rng.c
blobd188f044f4cb99b4c6162bdf4124991ff796cce5
1 /*
2 * nRF51 Random Number Generator
4 * Reference Manual: http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.1.pdf
6 * Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
8 * This code is licensed under the GPL version 2 or later. See
9 * the COPYING file in the top-level directory.
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 "crypto/random.h"
19 static void update_irq(NRF51RNGState *s)
21 bool irq = s->interrupt_enabled && s->event_valrdy;
22 qemu_set_irq(s->irq, irq);
25 static uint64_t rng_read(void *opaque, hwaddr offset, unsigned int size)
27 NRF51RNGState *s = NRF51_RNG(opaque);
28 uint64_t r = 0;
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;
49 default:
50 qemu_log_mask(LOG_GUEST_ERROR,
51 "%s: bad read offset 0x%" HWADDR_PRIx "\n",
52 __func__, offset);
55 return r;
58 static int64_t calc_next_timeout(NRF51RNGState *s)
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;
67 return timeout;
71 static void rng_update_timer(NRF51RNGState *s)
73 if (s->active) {
74 timer_mod(&s->timer, calc_next_timeout(s));
75 } else {
76 timer_del(&s->timer);
81 static void rng_write(void *opaque, hwaddr offset,
82 uint64_t value, unsigned int size)
84 NRF51RNGState *s = NRF51_RNG(opaque);
86 switch (offset) {
87 case NRF51_RNG_TASK_START:
88 if (value == NRF51_TRIGGER_TASK) {
89 s->active = 1;
90 rng_update_timer(s);
92 break;
93 case NRF51_RNG_TASK_STOP:
94 if (value == NRF51_TRIGGER_TASK) {
95 s->active = 0;
96 rng_update_timer(s);
98 break;
99 case NRF51_RNG_EVENT_VALRDY:
100 if (value == NRF51_EVENT_CLEAR) {
101 s->event_valrdy = 0;
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;
116 break;
117 case NRF51_RNG_REG_INTENCLR:
118 if (value & BIT_MASK(NRF51_RNG_REG_INTEN_VALRDY)) {
119 s->interrupt_enabled = 0;
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;
127 default:
128 qemu_log_mask(LOG_GUEST_ERROR,
129 "%s: bad write offset 0x%" HWADDR_PRIx "\n",
130 __func__, offset);
133 update_irq(s);
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
144 static void nrf51_rng_timer_expire(void *opaque)
146 NRF51RNGState *s = NRF51_RNG(opaque);
148 qcrypto_random_bytes(&s->value, 1, &error_abort);
150 s->event_valrdy = 1;
151 qemu_set_irq(s->eep_valrdy, 1);
153 if (s->shortcut_stop_on_valrdy) {
154 s->active = 0;
157 rng_update_timer(s);
158 update_irq(s);
161 static void nrf51_rng_tep_start(void *opaque, int n, int level)
163 NRF51RNGState *s = NRF51_RNG(opaque);
165 if (level) {
166 s->active = 1;
167 rng_update_timer(s);
171 static void nrf51_rng_tep_stop(void *opaque, int n, int level)
173 NRF51RNGState *s = NRF51_RNG(opaque);
175 if (level) {
176 s->active = 0;
177 rng_update_timer(s);
182 static void nrf51_rng_init(Object *obj)
184 NRF51RNGState *s = NRF51_RNG(obj);
185 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
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);
191 timer_init_us(&s->timer, QEMU_CLOCK_VIRTUAL, nrf51_rng_timer_expire, s);
193 sysbus_init_irq(sbd, &s->irq);
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);
199 /* Events */
200 qdev_init_gpio_out_named(DEVICE(s), &s->eep_valrdy, "eep_valrdy", 1);
203 static void nrf51_rng_reset(DeviceState *dev)
205 NRF51RNGState *s = NRF51_RNG(dev);
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;
214 rng_update_timer(s);
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(),
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()
240 static void nrf51_rng_class_init(ObjectClass *klass, void *data)
242 DeviceClass *dc = DEVICE_CLASS(klass);
244 dc->props = nrf51_rng_properties;
245 dc->vmsd = &vmstate_rng;
246 dc->reset = nrf51_rng_reset;
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
257 static void nrf51_rng_register_types(void)
259 type_register_static(&nrf51_rng_info);
262 type_init(nrf51_rng_register_types)