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
18 #include "qemu/osdep.h"
19 #include "hw/register.h"
21 #include "qemu/module.h"
23 static inline void register_write_val(RegisterInfo
*reg
, uint64_t val
)
27 switch (reg
->data_size
) {
29 *(uint8_t *)reg
->data
= val
;
32 *(uint16_t *)reg
->data
= val
;
35 *(uint32_t *)reg
->data
= val
;
38 *(uint64_t *)reg
->data
= val
;
41 g_assert_not_reached();
45 static inline uint64_t register_read_val(RegisterInfo
*reg
)
47 switch (reg
->data_size
) {
49 return *(uint8_t *)reg
->data
;
51 return *(uint16_t *)reg
->data
;
53 return *(uint32_t *)reg
->data
;
55 return *(uint64_t *)reg
->data
;
57 g_assert_not_reached();
59 return 0; /* unreachable */
62 static inline uint64_t register_enabled_mask(int data_size
, unsigned size
)
64 if (data_size
< size
) {
68 return MAKE_64BIT_MASK(0, size
* 8);
71 void register_write(RegisterInfo
*reg
, uint64_t val
, uint64_t we
,
72 const char *prefix
, bool debug
)
74 uint64_t old_val
, new_val
, test
, no_w_mask
;
75 const RegisterAccessInfo
*ac
;
81 if (!ac
|| !ac
->name
) {
82 qemu_log_mask(LOG_GUEST_ERROR
, "%s: write to undefined device state "
83 "(written value: %#" PRIx64
")\n", prefix
, val
);
87 old_val
= reg
->data
? register_read_val(reg
) : ac
->reset
;
89 test
= (old_val
^ val
) & ac
->rsvd
;
91 qemu_log_mask(LOG_GUEST_ERROR
, "%s: change of value in reserved bit"
92 "fields: %#" PRIx64
")\n", prefix
, test
);
95 test
= val
& ac
->unimp
;
97 qemu_log_mask(LOG_UNIMP
,
98 "%s:%s writing %#" PRIx64
" to unimplemented bits:" \
100 prefix
, reg
->access
->name
, val
, ac
->unimp
);
103 /* Create the no write mask based on the read only, write to clear and
104 * reserved bit masks.
106 no_w_mask
= ac
->ro
| ac
->w1c
| ac
->rsvd
| ~we
;
107 new_val
= (val
& ~no_w_mask
) | (old_val
& no_w_mask
);
108 new_val
&= ~(val
& ac
->w1c
);
111 new_val
= ac
->pre_write(reg
, new_val
);
115 qemu_log("%s:%s: write of value %#" PRIx64
"\n", prefix
, ac
->name
,
119 register_write_val(reg
, new_val
);
121 if (ac
->post_write
) {
122 ac
->post_write(reg
, new_val
);
126 uint64_t register_read(RegisterInfo
*reg
, uint64_t re
, const char* prefix
,
130 const RegisterAccessInfo
*ac
;
135 if (!ac
|| !ac
->name
) {
136 qemu_log_mask(LOG_GUEST_ERROR
, "%s: read from undefined device state\n",
141 ret
= reg
->data
? register_read_val(reg
) : ac
->reset
;
143 register_write_val(reg
, ret
& ~(ac
->cor
& re
));
145 /* Mask based on the read enable size */
149 ret
= ac
->post_read(reg
, ret
);
153 qemu_log("%s:%s: read of value %#" PRIx64
"\n", prefix
,
160 void register_reset(RegisterInfo
*reg
)
162 const RegisterAccessInfo
*ac
;
166 if (!reg
->data
|| !reg
->access
) {
172 register_write_val(reg
, reg
->access
->reset
);
174 if (ac
->post_write
) {
175 ac
->post_write(reg
, reg
->access
->reset
);
179 void register_write_memory(void *opaque
, hwaddr addr
,
180 uint64_t value
, unsigned size
)
182 RegisterInfoArray
*reg_array
= opaque
;
183 RegisterInfo
*reg
= NULL
;
187 for (i
= 0; i
< reg_array
->num_elements
; i
++) {
188 if (reg_array
->r
[i
]->access
->addr
== addr
) {
189 reg
= reg_array
->r
[i
];
195 qemu_log_mask(LOG_GUEST_ERROR
, "%s: write to unimplemented register " \
196 "at address: %#" PRIx64
"\n", reg_array
->prefix
, addr
);
200 /* Generate appropriate write enable mask */
201 we
= register_enabled_mask(reg
->data_size
, size
);
203 register_write(reg
, value
, we
, reg_array
->prefix
,
207 uint64_t register_read_memory(void *opaque
, hwaddr addr
,
210 RegisterInfoArray
*reg_array
= opaque
;
211 RegisterInfo
*reg
= NULL
;
216 for (i
= 0; i
< reg_array
->num_elements
; i
++) {
217 if (reg_array
->r
[i
]->access
->addr
== addr
) {
218 reg
= reg_array
->r
[i
];
224 qemu_log_mask(LOG_GUEST_ERROR
, "%s: read to unimplemented register " \
225 "at address: %#" PRIx64
"\n", reg_array
->prefix
, addr
);
229 /* Generate appropriate read enable mask */
230 re
= register_enabled_mask(reg
->data_size
, size
);
232 read_val
= register_read(reg
, re
, reg_array
->prefix
,
235 return extract64(read_val
, 0, size
* 8);
238 static RegisterInfoArray
*register_init_block(DeviceState
*owner
,
239 const RegisterAccessInfo
*rae
,
240 int num
, RegisterInfo
*ri
,
242 const MemoryRegionOps
*ops
,
244 uint64_t memory_size
,
245 size_t data_size_bits
)
247 const char *device_prefix
= object_get_typename(OBJECT(owner
));
248 RegisterInfoArray
*r_array
= g_new0(RegisterInfoArray
, 1);
249 int data_size
= data_size_bits
>> 3;
252 r_array
->r
= g_new0(RegisterInfo
*, num
);
253 r_array
->num_elements
= num
;
254 r_array
->debug
= debug_enabled
;
255 r_array
->prefix
= device_prefix
;
257 for (i
= 0; i
< num
; i
++) {
258 int index
= rae
[i
].addr
/ data_size
;
259 RegisterInfo
*r
= &ri
[index
];
261 if (data
+ data_size
* index
== 0 || !&rae
[i
]) {
265 /* Init the register, this will zero it. */
266 object_initialize((void *)r
, sizeof(*r
), TYPE_REGISTER
);
268 /* Set the properties of the register */
269 r
->data
= data
+ data_size
* index
;
270 r
->data_size
= data_size
;
277 memory_region_init_io(&r_array
->mem
, OBJECT(owner
), ops
, r_array
,
278 device_prefix
, memory_size
);
283 RegisterInfoArray
*register_init_block8(DeviceState
*owner
,
284 const RegisterAccessInfo
*rae
,
285 int num
, RegisterInfo
*ri
,
287 const MemoryRegionOps
*ops
,
289 uint64_t memory_size
)
291 return register_init_block(owner
, rae
, num
, ri
, (void *)
292 data
, ops
, debug_enabled
, memory_size
, 8);
295 RegisterInfoArray
*register_init_block32(DeviceState
*owner
,
296 const RegisterAccessInfo
*rae
,
297 int num
, RegisterInfo
*ri
,
299 const MemoryRegionOps
*ops
,
301 uint64_t memory_size
)
303 return register_init_block(owner
, rae
, num
, ri
, (void *)
304 data
, ops
, debug_enabled
, memory_size
, 32);
307 void register_finalize_block(RegisterInfoArray
*r_array
)
309 object_unparent(OBJECT(&r_array
->mem
));
314 static void register_class_init(ObjectClass
*oc
, void *data
)
316 DeviceClass
*dc
= DEVICE_CLASS(oc
);
318 /* Reason: needs to be wired up to work */
319 dc
->user_creatable
= false;
322 static const TypeInfo register_info
= {
323 .name
= TYPE_REGISTER
,
324 .parent
= TYPE_DEVICE
,
325 .class_init
= register_class_init
,
326 .instance_size
= sizeof(RegisterInfo
),
329 static void register_register_types(void)
331 type_register_static(®ister_info
);
334 type_init(register_register_types
)