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"
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
)
164 if (!reg
->data
|| !reg
->access
) {
168 register_write_val(reg
, reg
->access
->reset
);
171 void register_init(RegisterInfo
*reg
)
175 if (!reg
->data
|| !reg
->access
) {
179 object_initialize((void *)reg
, sizeof(*reg
), TYPE_REGISTER
);
182 void register_write_memory(void *opaque
, hwaddr addr
,
183 uint64_t value
, unsigned size
)
185 RegisterInfoArray
*reg_array
= opaque
;
186 RegisterInfo
*reg
= NULL
;
190 for (i
= 0; i
< reg_array
->num_elements
; i
++) {
191 if (reg_array
->r
[i
]->access
->addr
== addr
) {
192 reg
= reg_array
->r
[i
];
198 qemu_log_mask(LOG_GUEST_ERROR
, "Write to unimplemented register at " \
199 "address: %#" PRIx64
"\n", addr
);
203 /* Generate appropriate write enable mask */
204 we
= register_enabled_mask(reg
->data_size
, size
);
206 register_write(reg
, value
, we
, reg_array
->prefix
,
210 uint64_t register_read_memory(void *opaque
, hwaddr addr
,
213 RegisterInfoArray
*reg_array
= opaque
;
214 RegisterInfo
*reg
= NULL
;
219 for (i
= 0; i
< reg_array
->num_elements
; i
++) {
220 if (reg_array
->r
[i
]->access
->addr
== addr
) {
221 reg
= reg_array
->r
[i
];
227 qemu_log_mask(LOG_GUEST_ERROR
, "Read to unimplemented register at " \
228 "address: %#" PRIx64
"\n", addr
);
232 /* Generate appropriate read enable mask */
233 re
= register_enabled_mask(reg
->data_size
, size
);
235 read_val
= register_read(reg
, re
, reg_array
->prefix
,
238 return extract64(read_val
, 0, size
* 8);
241 RegisterInfoArray
*register_init_block32(DeviceState
*owner
,
242 const RegisterAccessInfo
*rae
,
243 int num
, RegisterInfo
*ri
,
245 const MemoryRegionOps
*ops
,
247 uint64_t memory_size
)
249 const char *device_prefix
= object_get_typename(OBJECT(owner
));
250 RegisterInfoArray
*r_array
= g_new0(RegisterInfoArray
, 1);
253 r_array
->r
= g_new0(RegisterInfo
*, num
);
254 r_array
->num_elements
= num
;
255 r_array
->debug
= debug_enabled
;
256 r_array
->prefix
= device_prefix
;
258 for (i
= 0; i
< num
; i
++) {
259 int index
= rae
[i
].addr
/ 4;
260 RegisterInfo
*r
= &ri
[index
];
262 *r
= (RegisterInfo
) {
263 .data
= &data
[index
],
264 .data_size
= sizeof(uint32_t),
273 memory_region_init_io(&r_array
->mem
, OBJECT(owner
), ops
, r_array
,
274 device_prefix
, memory_size
);
279 void register_finalize_block(RegisterInfoArray
*r_array
)
281 object_unparent(OBJECT(&r_array
->mem
));
286 static void register_class_init(ObjectClass
*oc
, void *data
)
288 DeviceClass
*dc
= DEVICE_CLASS(oc
);
290 /* Reason: needs to be wired up to work */
291 dc
->user_creatable
= false;
294 static const TypeInfo register_info
= {
295 .name
= TYPE_REGISTER
,
296 .parent
= TYPE_DEVICE
,
297 .class_init
= register_class_init
,
300 static void register_register_types(void)
302 type_register_static(®ister_info
);
305 type_init(register_register_types
)