Merge remote-tracking branch 'remotes/armbru/tags/pull-build-2019-07-02-v2' into...
[qemu/ar7.git] / hw / core / register.c
blobbb5ab9d4790c7785580d7c3915cb1ec02360bd09
1 /*
2 * Register Definition API
4 * Copyright (c) 2016 Xilinx Inc.
5 * Copyright (c) 2013 Peter Crosthwaite <peter.crosthwaite@xilinx.com>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
18 #include "qemu/osdep.h"
19 #include "hw/register.h"
20 #include "hw/qdev.h"
21 #include "qemu/log.h"
22 #include "qemu/module.h"
24 static inline void register_write_val(RegisterInfo *reg, uint64_t val)
26 g_assert(reg->data);
28 switch (reg->data_size) {
29 case 1:
30 *(uint8_t *)reg->data = val;
31 break;
32 case 2:
33 *(uint16_t *)reg->data = val;
34 break;
35 case 4:
36 *(uint32_t *)reg->data = val;
37 break;
38 case 8:
39 *(uint64_t *)reg->data = val;
40 break;
41 default:
42 g_assert_not_reached();
46 static inline uint64_t register_read_val(RegisterInfo *reg)
48 switch (reg->data_size) {
49 case 1:
50 return *(uint8_t *)reg->data;
51 case 2:
52 return *(uint16_t *)reg->data;
53 case 4:
54 return *(uint32_t *)reg->data;
55 case 8:
56 return *(uint64_t *)reg->data;
57 default:
58 g_assert_not_reached();
60 return 0; /* unreachable */
63 static inline uint64_t register_enabled_mask(int data_size, unsigned size)
65 if (data_size < size) {
66 size = data_size;
69 return MAKE_64BIT_MASK(0, size * 8);
72 void register_write(RegisterInfo *reg, uint64_t val, uint64_t we,
73 const char *prefix, bool debug)
75 uint64_t old_val, new_val, test, no_w_mask;
76 const RegisterAccessInfo *ac;
78 assert(reg);
80 ac = reg->access;
82 if (!ac || !ac->name) {
83 qemu_log_mask(LOG_GUEST_ERROR, "%s: write to undefined device state "
84 "(written value: %#" PRIx64 ")\n", prefix, val);
85 return;
88 old_val = reg->data ? register_read_val(reg) : ac->reset;
90 test = (old_val ^ val) & ac->rsvd;
91 if (test) {
92 qemu_log_mask(LOG_GUEST_ERROR, "%s: change of value in reserved bit"
93 "fields: %#" PRIx64 ")\n", prefix, test);
96 test = val & ac->unimp;
97 if (test) {
98 qemu_log_mask(LOG_UNIMP,
99 "%s:%s writing %#" PRIx64 " to unimplemented bits:" \
100 " %#" PRIx64 "\n",
101 prefix, reg->access->name, val, ac->unimp);
104 /* Create the no write mask based on the read only, write to clear and
105 * reserved bit masks.
107 no_w_mask = ac->ro | ac->w1c | ac->rsvd | ~we;
108 new_val = (val & ~no_w_mask) | (old_val & no_w_mask);
109 new_val &= ~(val & ac->w1c);
111 if (ac->pre_write) {
112 new_val = ac->pre_write(reg, new_val);
115 if (debug) {
116 qemu_log("%s:%s: write of value %#" PRIx64 "\n", prefix, ac->name,
117 new_val);
120 register_write_val(reg, new_val);
122 if (ac->post_write) {
123 ac->post_write(reg, new_val);
127 uint64_t register_read(RegisterInfo *reg, uint64_t re, const char* prefix,
128 bool debug)
130 uint64_t ret;
131 const RegisterAccessInfo *ac;
133 assert(reg);
135 ac = reg->access;
136 if (!ac || !ac->name) {
137 qemu_log_mask(LOG_GUEST_ERROR, "%s: read from undefined device state\n",
138 prefix);
139 return 0;
142 ret = reg->data ? register_read_val(reg) : ac->reset;
144 register_write_val(reg, ret & ~(ac->cor & re));
146 /* Mask based on the read enable size */
147 ret &= re;
149 if (ac->post_read) {
150 ret = ac->post_read(reg, ret);
153 if (debug) {
154 qemu_log("%s:%s: read of value %#" PRIx64 "\n", prefix,
155 ac->name, ret);
158 return ret;
161 void register_reset(RegisterInfo *reg)
163 const RegisterAccessInfo *ac;
165 g_assert(reg);
167 if (!reg->data || !reg->access) {
168 return;
171 ac = reg->access;
173 register_write_val(reg, reg->access->reset);
175 if (ac->post_write) {
176 ac->post_write(reg, reg->access->reset);
180 void register_init(RegisterInfo *reg)
182 assert(reg);
184 if (!reg->data || !reg->access) {
185 return;
188 object_initialize((void *)reg, sizeof(*reg), TYPE_REGISTER);
191 void register_write_memory(void *opaque, hwaddr addr,
192 uint64_t value, unsigned size)
194 RegisterInfoArray *reg_array = opaque;
195 RegisterInfo *reg = NULL;
196 uint64_t we;
197 int i;
199 for (i = 0; i < reg_array->num_elements; i++) {
200 if (reg_array->r[i]->access->addr == addr) {
201 reg = reg_array->r[i];
202 break;
206 if (!reg) {
207 qemu_log_mask(LOG_GUEST_ERROR, "%s: write to unimplemented register " \
208 "at address: %#" PRIx64 "\n", reg_array->prefix, addr);
209 return;
212 /* Generate appropriate write enable mask */
213 we = register_enabled_mask(reg->data_size, size);
215 register_write(reg, value, we, reg_array->prefix,
216 reg_array->debug);
219 uint64_t register_read_memory(void *opaque, hwaddr addr,
220 unsigned size)
222 RegisterInfoArray *reg_array = opaque;
223 RegisterInfo *reg = NULL;
224 uint64_t read_val;
225 uint64_t re;
226 int i;
228 for (i = 0; i < reg_array->num_elements; i++) {
229 if (reg_array->r[i]->access->addr == addr) {
230 reg = reg_array->r[i];
231 break;
235 if (!reg) {
236 qemu_log_mask(LOG_GUEST_ERROR, "%s: read to unimplemented register " \
237 "at address: %#" PRIx64 "\n", reg_array->prefix, addr);
238 return 0;
241 /* Generate appropriate read enable mask */
242 re = register_enabled_mask(reg->data_size, size);
244 read_val = register_read(reg, re, reg_array->prefix,
245 reg_array->debug);
247 return extract64(read_val, 0, size * 8);
250 RegisterInfoArray *register_init_block32(DeviceState *owner,
251 const RegisterAccessInfo *rae,
252 int num, RegisterInfo *ri,
253 uint32_t *data,
254 const MemoryRegionOps *ops,
255 bool debug_enabled,
256 uint64_t memory_size)
258 const char *device_prefix = object_get_typename(OBJECT(owner));
259 RegisterInfoArray *r_array = g_new0(RegisterInfoArray, 1);
260 int i;
262 r_array->r = g_new0(RegisterInfo *, num);
263 r_array->num_elements = num;
264 r_array->debug = debug_enabled;
265 r_array->prefix = device_prefix;
267 for (i = 0; i < num; i++) {
268 int index = rae[i].addr / 4;
269 RegisterInfo *r = &ri[index];
271 *r = (RegisterInfo) {
272 .data = &data[index],
273 .data_size = sizeof(uint32_t),
274 .access = &rae[i],
275 .opaque = owner,
277 register_init(r);
279 r_array->r[i] = r;
282 memory_region_init_io(&r_array->mem, OBJECT(owner), ops, r_array,
283 device_prefix, memory_size);
285 return r_array;
288 void register_finalize_block(RegisterInfoArray *r_array)
290 object_unparent(OBJECT(&r_array->mem));
291 g_free(r_array->r);
292 g_free(r_array);
295 static void register_class_init(ObjectClass *oc, void *data)
297 DeviceClass *dc = DEVICE_CLASS(oc);
299 /* Reason: needs to be wired up to work */
300 dc->user_creatable = false;
303 static const TypeInfo register_info = {
304 .name = TYPE_REGISTER,
305 .parent = TYPE_DEVICE,
306 .class_init = register_class_init,
309 static void register_register_types(void)
311 type_register_static(&register_info);
314 type_init(register_register_types)