2 * QEMU model of the EFuse_Cache
4 * Copyright (c) 2017 Xilinx Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 #include "qemu/osdep.h"
26 #include "hw/nvram/xlnx-versal-efuse.h"
29 #include "hw/qdev-properties.h"
33 static uint64_t efuse_cache_read(void *opaque
, hwaddr addr
, unsigned size
)
35 XlnxVersalEFuseCache
*s
= XLNX_VERSAL_EFUSE_CACHE(opaque
);
36 unsigned int w0
= QEMU_ALIGN_DOWN(addr
* 8, 32);
37 unsigned int w1
= QEMU_ALIGN_DOWN((addr
+ size
- 1) * 8, 32);
41 assert(w0
== w1
|| (w0
+ 32) == w1
);
43 ret
= xlnx_versal_efuse_read_row(s
->efuse
, w1
, NULL
);
46 ret
|= xlnx_versal_efuse_read_row(s
->efuse
, w0
, NULL
);
49 /* If 'addr' unaligned, the guest is always assumed to be little-endian. */
58 static void efuse_cache_write(void *opaque
, hwaddr addr
, uint64_t value
,
61 /* No Register Writes allowed */
62 qemu_log_mask(LOG_GUEST_ERROR
, "%s: efuse cache registers are read-only",
66 static const MemoryRegionOps efuse_cache_ops
= {
67 .read
= efuse_cache_read
,
68 .write
= efuse_cache_write
,
69 .endianness
= DEVICE_LITTLE_ENDIAN
,
76 static void efuse_cache_init(Object
*obj
)
78 XlnxVersalEFuseCache
*s
= XLNX_VERSAL_EFUSE_CACHE(obj
);
79 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
81 memory_region_init_io(&s
->iomem
, obj
, &efuse_cache_ops
, s
,
82 TYPE_XLNX_VERSAL_EFUSE_CACHE
, MR_SIZE
);
83 sysbus_init_mmio(sbd
, &s
->iomem
);
86 static Property efuse_cache_props
[] = {
87 DEFINE_PROP_LINK("efuse",
88 XlnxVersalEFuseCache
, efuse
,
89 TYPE_XLNX_EFUSE
, XlnxEFuse
*),
91 DEFINE_PROP_END_OF_LIST(),
94 static void efuse_cache_class_init(ObjectClass
*klass
, void *data
)
96 DeviceClass
*dc
= DEVICE_CLASS(klass
);
98 device_class_set_props(dc
, efuse_cache_props
);
101 static const TypeInfo efuse_cache_info
= {
102 .name
= TYPE_XLNX_VERSAL_EFUSE_CACHE
,
103 .parent
= TYPE_SYS_BUS_DEVICE
,
104 .instance_size
= sizeof(XlnxVersalEFuseCache
),
105 .class_init
= efuse_cache_class_init
,
106 .instance_init
= efuse_cache_init
,
109 static void efuse_cache_register_types(void)
111 type_register_static(&efuse_cache_info
);
114 type_init(efuse_cache_register_types
)