2 * QEMU model of the ZynqMP eFuse
4 * Copyright (c) 2015 Xilinx Inc.
5 * Copyright (c) 2023 Advanced Micro Devices, Inc.
7 * Written by Edgar E. Iglesias <edgari@xilinx.com>
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28 #include "qemu/osdep.h"
29 #include "hw/nvram/xlnx-zynqmp-efuse.h"
32 #include "qapi/error.h"
33 #include "migration/vmstate.h"
34 #include "hw/qdev-properties.h"
36 #ifndef ZYNQMP_EFUSE_ERR_DEBUG
37 #define ZYNQMP_EFUSE_ERR_DEBUG 0
41 FIELD(WR_LOCK
, LOCK
, 0, 16)
43 FIELD(CFG
, SLVERR_ENABLE
, 5, 1)
44 FIELD(CFG
, MARGIN_RD
, 2, 2)
45 FIELD(CFG
, PGM_EN
, 1, 1)
46 FIELD(CFG
, EFUSE_CLK_SEL
, 0, 1)
48 FIELD(STATUS
, AES_CRC_PASS
, 7, 1)
49 FIELD(STATUS
, AES_CRC_DONE
, 6, 1)
50 FIELD(STATUS
, CACHE_DONE
, 5, 1)
51 FIELD(STATUS
, CACHE_LOAD
, 4, 1)
52 FIELD(STATUS
, EFUSE_3_TBIT
, 2, 1)
53 FIELD(STATUS
, EFUSE_2_TBIT
, 1, 1)
54 FIELD(STATUS
, EFUSE_0_TBIT
, 0, 1)
55 REG32(EFUSE_PGM_ADDR
, 0xc)
56 FIELD(EFUSE_PGM_ADDR
, EFUSE
, 11, 2)
57 FIELD(EFUSE_PGM_ADDR
, ROW
, 5, 6)
58 FIELD(EFUSE_PGM_ADDR
, COLUMN
, 0, 5)
59 REG32(EFUSE_RD_ADDR
, 0x10)
60 FIELD(EFUSE_RD_ADDR
, EFUSE
, 11, 2)
61 FIELD(EFUSE_RD_ADDR
, ROW
, 5, 6)
62 REG32(EFUSE_RD_DATA
, 0x14)
64 FIELD(TPGM
, VALUE
, 0, 16)
66 FIELD(TRD
, VALUE
, 0, 8)
68 FIELD(TSU_H_PS
, VALUE
, 0, 8)
69 REG32(TSU_H_PS_CS
, 0x24)
70 FIELD(TSU_H_PS_CS
, VALUE
, 0, 8)
72 FIELD(TSU_H_CS
, VALUE
, 0, 4)
73 REG32(EFUSE_ISR
, 0x30)
74 FIELD(EFUSE_ISR
, APB_SLVERR
, 31, 1)
75 FIELD(EFUSE_ISR
, CACHE_ERROR
, 4, 1)
76 FIELD(EFUSE_ISR
, RD_ERROR
, 3, 1)
77 FIELD(EFUSE_ISR
, RD_DONE
, 2, 1)
78 FIELD(EFUSE_ISR
, PGM_ERROR
, 1, 1)
79 FIELD(EFUSE_ISR
, PGM_DONE
, 0, 1)
80 REG32(EFUSE_IMR
, 0x34)
81 FIELD(EFUSE_IMR
, APB_SLVERR
, 31, 1)
82 FIELD(EFUSE_IMR
, CACHE_ERROR
, 4, 1)
83 FIELD(EFUSE_IMR
, RD_ERROR
, 3, 1)
84 FIELD(EFUSE_IMR
, RD_DONE
, 2, 1)
85 FIELD(EFUSE_IMR
, PGM_ERROR
, 1, 1)
86 FIELD(EFUSE_IMR
, PGM_DONE
, 0, 1)
87 REG32(EFUSE_IER
, 0x38)
88 FIELD(EFUSE_IER
, APB_SLVERR
, 31, 1)
89 FIELD(EFUSE_IER
, CACHE_ERROR
, 4, 1)
90 FIELD(EFUSE_IER
, RD_ERROR
, 3, 1)
91 FIELD(EFUSE_IER
, RD_DONE
, 2, 1)
92 FIELD(EFUSE_IER
, PGM_ERROR
, 1, 1)
93 FIELD(EFUSE_IER
, PGM_DONE
, 0, 1)
94 REG32(EFUSE_IDR
, 0x3c)
95 FIELD(EFUSE_IDR
, APB_SLVERR
, 31, 1)
96 FIELD(EFUSE_IDR
, CACHE_ERROR
, 4, 1)
97 FIELD(EFUSE_IDR
, RD_ERROR
, 3, 1)
98 FIELD(EFUSE_IDR
, RD_DONE
, 2, 1)
99 FIELD(EFUSE_IDR
, PGM_ERROR
, 1, 1)
100 FIELD(EFUSE_IDR
, PGM_DONE
, 0, 1)
101 REG32(EFUSE_CACHE_LOAD
, 0x40)
102 FIELD(EFUSE_CACHE_LOAD
, LOAD
, 0, 1)
103 REG32(EFUSE_PGM_LOCK
, 0x44)
104 FIELD(EFUSE_PGM_LOCK
, SPK_ID_LOCK
, 0, 1)
105 REG32(EFUSE_AES_CRC
, 0x48)
106 REG32(EFUSE_TBITS_PRGRMG_EN
, 0x100)
107 FIELD(EFUSE_TBITS_PRGRMG_EN
, TBITS_PRGRMG_EN
, 3, 1)
111 REG32(IPDISABLE
, 0x1018)
112 FIELD(IPDISABLE
, VCU_DIS
, 8, 1)
113 FIELD(IPDISABLE
, GPU_DIS
, 5, 1)
114 FIELD(IPDISABLE
, APU3_DIS
, 3, 1)
115 FIELD(IPDISABLE
, APU2_DIS
, 2, 1)
116 FIELD(IPDISABLE
, APU1_DIS
, 1, 1)
117 FIELD(IPDISABLE
, APU0_DIS
, 0, 1)
118 REG32(SYSOSC_CTRL
, 0x101c)
119 FIELD(SYSOSC_CTRL
, SYSOSC_EN
, 0, 1)
120 REG32(USER_0
, 0x1020)
121 REG32(USER_1
, 0x1024)
122 REG32(USER_2
, 0x1028)
123 REG32(USER_3
, 0x102c)
124 REG32(USER_4
, 0x1030)
125 REG32(USER_5
, 0x1034)
126 REG32(USER_6
, 0x1038)
127 REG32(USER_7
, 0x103c)
128 REG32(MISC_USER_CTRL
, 0x1040)
129 FIELD(MISC_USER_CTRL
, FPD_SC_EN_0
, 14, 1)
130 FIELD(MISC_USER_CTRL
, LPD_SC_EN_0
, 11, 1)
131 FIELD(MISC_USER_CTRL
, LBIST_EN
, 10, 1)
132 FIELD(MISC_USER_CTRL
, USR_WRLK_7
, 7, 1)
133 FIELD(MISC_USER_CTRL
, USR_WRLK_6
, 6, 1)
134 FIELD(MISC_USER_CTRL
, USR_WRLK_5
, 5, 1)
135 FIELD(MISC_USER_CTRL
, USR_WRLK_4
, 4, 1)
136 FIELD(MISC_USER_CTRL
, USR_WRLK_3
, 3, 1)
137 FIELD(MISC_USER_CTRL
, USR_WRLK_2
, 2, 1)
138 FIELD(MISC_USER_CTRL
, USR_WRLK_1
, 1, 1)
139 FIELD(MISC_USER_CTRL
, USR_WRLK_0
, 0, 1)
140 REG32(ROM_RSVD
, 0x1044)
141 FIELD(ROM_RSVD
, PBR_BOOT_ERROR
, 0, 3)
142 REG32(PUF_CHASH
, 0x1050)
143 REG32(PUF_MISC
, 0x1054)
144 FIELD(PUF_MISC
, REGISTER_DIS
, 31, 1)
145 FIELD(PUF_MISC
, SYN_WRLK
, 30, 1)
146 FIELD(PUF_MISC
, SYN_INVLD
, 29, 1)
147 FIELD(PUF_MISC
, TEST2_DIS
, 28, 1)
148 FIELD(PUF_MISC
, UNUSED27
, 27, 1)
149 FIELD(PUF_MISC
, UNUSED26
, 26, 1)
150 FIELD(PUF_MISC
, UNUSED25
, 25, 1)
151 FIELD(PUF_MISC
, UNUSED24
, 24, 1)
152 FIELD(PUF_MISC
, AUX
, 0, 24)
153 REG32(SEC_CTRL
, 0x1058)
154 FIELD(SEC_CTRL
, PPK1_INVLD
, 30, 2)
155 FIELD(SEC_CTRL
, PPK1_WRLK
, 29, 1)
156 FIELD(SEC_CTRL
, PPK0_INVLD
, 27, 2)
157 FIELD(SEC_CTRL
, PPK0_WRLK
, 26, 1)
158 FIELD(SEC_CTRL
, RSA_EN
, 11, 15)
159 FIELD(SEC_CTRL
, SEC_LOCK
, 10, 1)
160 FIELD(SEC_CTRL
, PROG_GATE_2
, 9, 1)
161 FIELD(SEC_CTRL
, PROG_GATE_1
, 8, 1)
162 FIELD(SEC_CTRL
, PROG_GATE_0
, 7, 1)
163 FIELD(SEC_CTRL
, DFT_DIS
, 6, 1)
164 FIELD(SEC_CTRL
, JTAG_DIS
, 5, 1)
165 FIELD(SEC_CTRL
, ERROR_DIS
, 4, 1)
166 FIELD(SEC_CTRL
, BBRAM_DIS
, 3, 1)
167 FIELD(SEC_CTRL
, ENC_ONLY
, 2, 1)
168 FIELD(SEC_CTRL
, AES_WRLK
, 1, 1)
169 FIELD(SEC_CTRL
, AES_RDLK
, 0, 1)
170 REG32(SPK_ID
, 0x105c)
171 REG32(PPK0_0
, 0x10a0)
172 REG32(PPK0_1
, 0x10a4)
173 REG32(PPK0_2
, 0x10a8)
174 REG32(PPK0_3
, 0x10ac)
175 REG32(PPK0_4
, 0x10b0)
176 REG32(PPK0_5
, 0x10b4)
177 REG32(PPK0_6
, 0x10b8)
178 REG32(PPK0_7
, 0x10bc)
179 REG32(PPK0_8
, 0x10c0)
180 REG32(PPK0_9
, 0x10c4)
181 REG32(PPK0_10
, 0x10c8)
182 REG32(PPK0_11
, 0x10cc)
183 REG32(PPK1_0
, 0x10d0)
184 REG32(PPK1_1
, 0x10d4)
185 REG32(PPK1_2
, 0x10d8)
186 REG32(PPK1_3
, 0x10dc)
187 REG32(PPK1_4
, 0x10e0)
188 REG32(PPK1_5
, 0x10e4)
189 REG32(PPK1_6
, 0x10e8)
190 REG32(PPK1_7
, 0x10ec)
191 REG32(PPK1_8
, 0x10f0)
192 REG32(PPK1_9
, 0x10f4)
193 REG32(PPK1_10
, 0x10f8)
194 REG32(PPK1_11
, 0x10fc)
196 #define BIT_POS(ROW, COLUMN) (ROW * 32 + COLUMN)
197 #define R_MAX (R_PPK1_11 + 1)
199 /* #define EFUSE_XOSC 26 */
202 * eFUSE layout references:
203 * ZynqMP: UG1085 (v2.1) August 21, 2019, p.277, Table 12-13
205 #define EFUSE_AES_RDLK BIT_POS(22, 0)
206 #define EFUSE_AES_WRLK BIT_POS(22, 1)
207 #define EFUSE_ENC_ONLY BIT_POS(22, 2)
208 #define EFUSE_BBRAM_DIS BIT_POS(22, 3)
209 #define EFUSE_ERROR_DIS BIT_POS(22, 4)
210 #define EFUSE_JTAG_DIS BIT_POS(22, 5)
211 #define EFUSE_DFT_DIS BIT_POS(22, 6)
212 #define EFUSE_PROG_GATE_0 BIT_POS(22, 7)
213 #define EFUSE_PROG_GATE_1 BIT_POS(22, 7)
214 #define EFUSE_PROG_GATE_2 BIT_POS(22, 9)
215 #define EFUSE_SEC_LOCK BIT_POS(22, 10)
216 #define EFUSE_RSA_EN BIT_POS(22, 11)
217 #define EFUSE_RSA_EN14 BIT_POS(22, 25)
218 #define EFUSE_PPK0_WRLK BIT_POS(22, 26)
219 #define EFUSE_PPK0_INVLD BIT_POS(22, 27)
220 #define EFUSE_PPK0_INVLD_1 BIT_POS(22, 28)
221 #define EFUSE_PPK1_WRLK BIT_POS(22, 29)
222 #define EFUSE_PPK1_INVLD BIT_POS(22, 30)
223 #define EFUSE_PPK1_INVLD_1 BIT_POS(22, 31)
226 #define EFUSE_TRIM_START BIT_POS(1, 0)
227 #define EFUSE_TRIM_END BIT_POS(1, 30)
228 #define EFUSE_DNA_START BIT_POS(3, 0)
229 #define EFUSE_DNA_END BIT_POS(5, 31)
230 #define EFUSE_AES_START BIT_POS(24, 0)
231 #define EFUSE_AES_END BIT_POS(31, 31)
232 #define EFUSE_ROM_START BIT_POS(17, 0)
233 #define EFUSE_ROM_END BIT_POS(17, 31)
234 #define EFUSE_IPDIS_START BIT_POS(6, 0)
235 #define EFUSE_IPDIS_END BIT_POS(6, 31)
236 #define EFUSE_USER_START BIT_POS(8, 0)
237 #define EFUSE_USER_END BIT_POS(15, 31)
238 #define EFUSE_BISR_START BIT_POS(32, 0)
239 #define EFUSE_BISR_END BIT_POS(39, 31)
241 #define EFUSE_USER_CTRL_START BIT_POS(16, 0)
242 #define EFUSE_USER_CTRL_END BIT_POS(16, 16)
243 #define EFUSE_USER_CTRL_MASK ((uint32_t)MAKE_64BIT_MASK(0, 17))
245 #define EFUSE_PUF_CHASH_START BIT_POS(20, 0)
246 #define EFUSE_PUF_CHASH_END BIT_POS(20, 31)
247 #define EFUSE_PUF_MISC_START BIT_POS(21, 0)
248 #define EFUSE_PUF_MISC_END BIT_POS(21, 31)
249 #define EFUSE_PUF_SYN_WRLK BIT_POS(21, 30)
251 #define EFUSE_SPK_START BIT_POS(23, 0)
252 #define EFUSE_SPK_END BIT_POS(23, 31)
254 #define EFUSE_PPK0_START BIT_POS(40, 0)
255 #define EFUSE_PPK0_END BIT_POS(51, 31)
256 #define EFUSE_PPK1_START BIT_POS(52, 0)
257 #define EFUSE_PPK1_END BIT_POS(63, 31)
259 #define EFUSE_CACHE_FLD(s, reg, field) \
260 ARRAY_FIELD_DP32((s)->regs, reg, field, \
261 (xlnx_efuse_get_row((s->efuse), EFUSE_ ## field) \
262 >> (EFUSE_ ## field % 32)))
264 #define EFUSE_CACHE_BIT(s, reg, field) \
265 ARRAY_FIELD_DP32((s)->regs, reg, field, xlnx_efuse_get_bit((s->efuse), \
268 #define FBIT_UNKNOWN (~0)
270 QEMU_BUILD_BUG_ON(R_MAX
!= ARRAY_SIZE(((XlnxZynqMPEFuse
*)0)->regs
));
272 static void update_tbit_status(XlnxZynqMPEFuse
*s
)
274 unsigned int check
= xlnx_efuse_tbits_check(s
->efuse
);
275 uint32_t val
= s
->regs
[R_STATUS
];
277 val
= FIELD_DP32(val
, STATUS
, EFUSE_0_TBIT
, !!(check
& (1 << 0)));
278 val
= FIELD_DP32(val
, STATUS
, EFUSE_2_TBIT
, !!(check
& (1 << 1)));
279 val
= FIELD_DP32(val
, STATUS
, EFUSE_3_TBIT
, !!(check
& (1 << 2)));
281 s
->regs
[R_STATUS
] = val
;
284 /* Update the u32 array from efuse bits. Slow but simple approach. */
285 static void cache_sync_u32(XlnxZynqMPEFuse
*s
, unsigned int r_start
,
286 unsigned int f_start
, unsigned int f_end
,
287 unsigned int f_written
)
289 uint32_t *u32
= &s
->regs
[r_start
];
290 unsigned int fbit
, wbits
= 0, u32_off
= 0;
292 /* Avoid working on bits that are not relevant. */
293 if (f_written
!= FBIT_UNKNOWN
294 && (f_written
< f_start
|| f_written
> f_end
)) {
298 for (fbit
= f_start
; fbit
<= f_end
; fbit
++, wbits
++) {
300 /* Update the key offset. */
304 u32
[u32_off
] |= xlnx_efuse_get_bit(s
->efuse
, fbit
) << wbits
;
309 * Keep the syncs in bit order so we can bail out for the
312 static void zynqmp_efuse_sync_cache(XlnxZynqMPEFuse
*s
, unsigned int bit
)
314 EFUSE_CACHE_BIT(s
, SEC_CTRL
, AES_RDLK
);
315 EFUSE_CACHE_BIT(s
, SEC_CTRL
, AES_WRLK
);
316 EFUSE_CACHE_BIT(s
, SEC_CTRL
, ENC_ONLY
);
317 EFUSE_CACHE_BIT(s
, SEC_CTRL
, BBRAM_DIS
);
318 EFUSE_CACHE_BIT(s
, SEC_CTRL
, ERROR_DIS
);
319 EFUSE_CACHE_BIT(s
, SEC_CTRL
, JTAG_DIS
);
320 EFUSE_CACHE_BIT(s
, SEC_CTRL
, DFT_DIS
);
321 EFUSE_CACHE_BIT(s
, SEC_CTRL
, PROG_GATE_0
);
322 EFUSE_CACHE_BIT(s
, SEC_CTRL
, PROG_GATE_1
);
323 EFUSE_CACHE_BIT(s
, SEC_CTRL
, PROG_GATE_2
);
324 EFUSE_CACHE_BIT(s
, SEC_CTRL
, SEC_LOCK
);
325 EFUSE_CACHE_BIT(s
, SEC_CTRL
, PPK0_WRLK
);
326 EFUSE_CACHE_BIT(s
, SEC_CTRL
, PPK1_WRLK
);
328 EFUSE_CACHE_FLD(s
, SEC_CTRL
, RSA_EN
);
329 EFUSE_CACHE_FLD(s
, SEC_CTRL
, PPK0_INVLD
);
330 EFUSE_CACHE_FLD(s
, SEC_CTRL
, PPK1_INVLD
);
332 /* Update the tbits. */
333 update_tbit_status(s
);
335 /* Sync the various areas. */
336 s
->regs
[R_MISC_USER_CTRL
] = xlnx_efuse_get_row(s
->efuse
,
337 EFUSE_USER_CTRL_START
)
338 & EFUSE_USER_CTRL_MASK
;
339 s
->regs
[R_PUF_CHASH
] = xlnx_efuse_get_row(s
->efuse
, EFUSE_PUF_CHASH_START
);
340 s
->regs
[R_PUF_MISC
] = xlnx_efuse_get_row(s
->efuse
, EFUSE_PUF_MISC_START
);
342 cache_sync_u32(s
, R_DNA_0
, EFUSE_DNA_START
, EFUSE_DNA_END
, bit
);
344 if (bit
< EFUSE_AES_START
) {
348 cache_sync_u32(s
, R_ROM_RSVD
, EFUSE_ROM_START
, EFUSE_ROM_END
, bit
);
349 cache_sync_u32(s
, R_IPDISABLE
, EFUSE_IPDIS_START
, EFUSE_IPDIS_END
, bit
);
350 cache_sync_u32(s
, R_USER_0
, EFUSE_USER_START
, EFUSE_USER_END
, bit
);
351 cache_sync_u32(s
, R_SPK_ID
, EFUSE_SPK_START
, EFUSE_SPK_END
, bit
);
352 cache_sync_u32(s
, R_PPK0_0
, EFUSE_PPK0_START
, EFUSE_PPK0_END
, bit
);
353 cache_sync_u32(s
, R_PPK1_0
, EFUSE_PPK1_START
, EFUSE_PPK1_END
, bit
);
356 static void zynqmp_efuse_update_irq(XlnxZynqMPEFuse
*s
)
358 bool pending
= s
->regs
[R_EFUSE_ISR
] & s
->regs
[R_EFUSE_IMR
];
359 qemu_set_irq(s
->irq
, pending
);
362 static void zynqmp_efuse_isr_postw(RegisterInfo
*reg
, uint64_t val64
)
364 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(reg
->opaque
);
365 zynqmp_efuse_update_irq(s
);
368 static uint64_t zynqmp_efuse_ier_prew(RegisterInfo
*reg
, uint64_t val64
)
370 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(reg
->opaque
);
371 uint32_t val
= val64
;
373 s
->regs
[R_EFUSE_IMR
] |= val
;
374 zynqmp_efuse_update_irq(s
);
378 static uint64_t zynqmp_efuse_idr_prew(RegisterInfo
*reg
, uint64_t val64
)
380 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(reg
->opaque
);
381 uint32_t val
= val64
;
383 s
->regs
[R_EFUSE_IMR
] &= ~val
;
384 zynqmp_efuse_update_irq(s
);
388 static void zynqmp_efuse_pgm_addr_postw(RegisterInfo
*reg
, uint64_t val64
)
390 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(reg
->opaque
);
391 unsigned bit
= val64
;
392 unsigned page
= FIELD_EX32(bit
, EFUSE_PGM_ADDR
, EFUSE
);
393 bool puf_prot
= false;
394 const char *errmsg
= NULL
;
396 /* Allow only valid array, and adjust for skipped array 1 */
401 bit
= FIELD_DP32(bit
, EFUSE_PGM_ADDR
, EFUSE
, page
- 1);
402 puf_prot
= xlnx_efuse_get_bit(s
->efuse
, EFUSE_PUF_SYN_WRLK
);
405 errmsg
= "Invalid address";
409 if (ARRAY_FIELD_EX32(s
->regs
, WR_LOCK
, LOCK
)) {
410 errmsg
= "Array write-locked";
414 if (!ARRAY_FIELD_EX32(s
->regs
, CFG
, PGM_EN
)) {
415 errmsg
= "Array pgm-disabled";
420 errmsg
= "PUF_HD-store write-locked";
424 if (ARRAY_FIELD_EX32(s
->regs
, SEC_CTRL
, AES_WRLK
)
425 && bit
>= EFUSE_AES_START
&& bit
<= EFUSE_AES_END
) {
426 errmsg
= "AES key-store Write-locked";
430 if (!xlnx_efuse_set_bit(s
->efuse
, bit
)) {
431 errmsg
= "Write failed";
436 ARRAY_FIELD_DP32(s
->regs
, EFUSE_ISR
, PGM_ERROR
, 0);
438 g_autofree
char *path
= object_get_canonical_path(OBJECT(s
));
440 ARRAY_FIELD_DP32(s
->regs
, EFUSE_ISR
, PGM_ERROR
, 1);
441 qemu_log_mask(LOG_GUEST_ERROR
,
442 "%s - eFuse write error: %s; addr=0x%x\n",
443 path
, errmsg
, (unsigned)val64
);
446 ARRAY_FIELD_DP32(s
->regs
, EFUSE_ISR
, PGM_DONE
, 1);
447 zynqmp_efuse_update_irq(s
);
450 static void zynqmp_efuse_rd_addr_postw(RegisterInfo
*reg
, uint64_t val64
)
452 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(reg
->opaque
);
453 g_autofree
char *path
= NULL
;
456 * Grant reads only to allowed bits; reference sources:
457 * 1/ XilSKey - XilSKey_ZynqMp_EfusePs_ReadRow()
458 * 2/ UG1085, v2.0, table 12-13
459 * (note: enumerates the masks as <first, last> per described in
460 * references to avoid mental translation).
462 #define COL_MASK(L_, H_) \
463 ((uint32_t)MAKE_64BIT_MASK((L_), (1 + (H_) - (L_))))
465 static const uint32_t ary0_col_mask
[] = {
466 /* XilSKey - XSK_ZYNQMP_EFUSEPS_TBITS_ROW */
467 [0] = COL_MASK(28, 31),
469 /* XilSKey - XSK_ZYNQMP_EFUSEPS_USR{0:7}_FUSE_ROW */
470 [8] = COL_MASK(0, 31), [9] = COL_MASK(0, 31),
471 [10] = COL_MASK(0, 31), [11] = COL_MASK(0, 31),
472 [12] = COL_MASK(0, 31), [13] = COL_MASK(0, 31),
473 [14] = COL_MASK(0, 31), [15] = COL_MASK(0, 31),
475 /* XilSKey - XSK_ZYNQMP_EFUSEPS_MISC_USR_CTRL_ROW */
476 [16] = COL_MASK(0, 7) | COL_MASK(10, 16),
478 /* XilSKey - XSK_ZYNQMP_EFUSEPS_PBR_BOOT_ERR_ROW */
479 [17] = COL_MASK(0, 2),
481 /* XilSKey - XSK_ZYNQMP_EFUSEPS_PUF_CHASH_ROW */
482 [20] = COL_MASK(0, 31),
484 /* XilSKey - XSK_ZYNQMP_EFUSEPS_PUF_AUX_ROW */
485 [21] = COL_MASK(0, 23) | COL_MASK(29, 31),
487 /* XilSKey - XSK_ZYNQMP_EFUSEPS_SEC_CTRL_ROW */
488 [22] = COL_MASK(0, 31),
490 /* XilSKey - XSK_ZYNQMP_EFUSEPS_SPK_ID_ROW */
491 [23] = COL_MASK(0, 31),
493 /* XilSKey - XSK_ZYNQMP_EFUSEPS_PPK0_START_ROW */
494 [40] = COL_MASK(0, 31), [41] = COL_MASK(0, 31),
495 [42] = COL_MASK(0, 31), [43] = COL_MASK(0, 31),
496 [44] = COL_MASK(0, 31), [45] = COL_MASK(0, 31),
497 [46] = COL_MASK(0, 31), [47] = COL_MASK(0, 31),
498 [48] = COL_MASK(0, 31), [49] = COL_MASK(0, 31),
499 [50] = COL_MASK(0, 31), [51] = COL_MASK(0, 31),
501 /* XilSKey - XSK_ZYNQMP_EFUSEPS_PPK1_START_ROW */
502 [52] = COL_MASK(0, 31), [53] = COL_MASK(0, 31),
503 [54] = COL_MASK(0, 31), [55] = COL_MASK(0, 31),
504 [56] = COL_MASK(0, 31), [57] = COL_MASK(0, 31),
505 [58] = COL_MASK(0, 31), [59] = COL_MASK(0, 31),
506 [60] = COL_MASK(0, 31), [61] = COL_MASK(0, 31),
507 [62] = COL_MASK(0, 31), [63] = COL_MASK(0, 31),
510 uint32_t col_mask
= COL_MASK(0, 31);
513 uint32_t efuse_idx
= s
->regs
[R_EFUSE_RD_ADDR
];
514 uint32_t efuse_ary
= FIELD_EX32(efuse_idx
, EFUSE_RD_ADDR
, EFUSE
);
515 uint32_t efuse_row
= FIELD_EX32(efuse_idx
, EFUSE_RD_ADDR
, ROW
);
518 case 0: /* Various */
519 if (efuse_row
>= ARRAY_SIZE(ary0_col_mask
)) {
523 col_mask
= ary0_col_mask
[efuse_row
];
528 case 2: /* PUF helper data, adjust for skipped array 1 */
530 val64
= FIELD_DP32(efuse_idx
, EFUSE_RD_ADDR
, EFUSE
, efuse_ary
- 1);
536 s
->regs
[R_EFUSE_RD_DATA
] = xlnx_efuse_get_row(s
->efuse
, val64
) & col_mask
;
538 ARRAY_FIELD_DP32(s
->regs
, EFUSE_ISR
, RD_ERROR
, 0);
539 ARRAY_FIELD_DP32(s
->regs
, EFUSE_ISR
, RD_DONE
, 1);
540 zynqmp_efuse_update_irq(s
);
544 path
= object_get_canonical_path(OBJECT(s
));
545 qemu_log_mask(LOG_GUEST_ERROR
,
546 "%s: Denied efuse read from array %u, row %u\n",
547 path
, efuse_ary
, efuse_row
);
549 s
->regs
[R_EFUSE_RD_DATA
] = 0;
551 ARRAY_FIELD_DP32(s
->regs
, EFUSE_ISR
, RD_ERROR
, 1);
552 ARRAY_FIELD_DP32(s
->regs
, EFUSE_ISR
, RD_DONE
, 0);
553 zynqmp_efuse_update_irq(s
);
556 static void zynqmp_efuse_aes_crc_postw(RegisterInfo
*reg
, uint64_t val64
)
558 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(reg
->opaque
);
561 ok
= xlnx_efuse_k256_check(s
->efuse
, (uint32_t)val64
, EFUSE_AES_START
);
563 ARRAY_FIELD_DP32(s
->regs
, STATUS
, AES_CRC_PASS
, (ok
? 1 : 0));
564 ARRAY_FIELD_DP32(s
->regs
, STATUS
, AES_CRC_DONE
, 1);
566 s
->regs
[R_EFUSE_AES_CRC
] = 0; /* crc value is write-only */
569 static uint64_t zynqmp_efuse_cache_load_prew(RegisterInfo
*reg
,
572 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(reg
->opaque
);
574 if (valu64
& R_EFUSE_CACHE_LOAD_LOAD_MASK
) {
575 zynqmp_efuse_sync_cache(s
, FBIT_UNKNOWN
);
576 ARRAY_FIELD_DP32(s
->regs
, STATUS
, CACHE_DONE
, 1);
577 zynqmp_efuse_update_irq(s
);
583 static uint64_t zynqmp_efuse_wr_lock_prew(RegisterInfo
*reg
, uint64_t val
)
585 return val
== 0xDF0D ? 0 : 1;
588 static RegisterAccessInfo zynqmp_efuse_regs_info
[] = {
589 { .name
= "WR_LOCK", .addr
= A_WR_LOCK
,
591 .pre_write
= zynqmp_efuse_wr_lock_prew
,
592 },{ .name
= "CFG", .addr
= A_CFG
,
593 },{ .name
= "STATUS", .addr
= A_STATUS
,
596 },{ .name
= "EFUSE_PGM_ADDR", .addr
= A_EFUSE_PGM_ADDR
,
597 .post_write
= zynqmp_efuse_pgm_addr_postw
598 },{ .name
= "EFUSE_RD_ADDR", .addr
= A_EFUSE_RD_ADDR
,
600 .post_write
= zynqmp_efuse_rd_addr_postw
,
601 },{ .name
= "EFUSE_RD_DATA", .addr
= A_EFUSE_RD_DATA
,
603 },{ .name
= "TPGM", .addr
= A_TPGM
,
604 },{ .name
= "TRD", .addr
= A_TRD
,
606 },{ .name
= "TSU_H_PS", .addr
= A_TSU_H_PS
,
608 },{ .name
= "TSU_H_PS_CS", .addr
= A_TSU_H_PS_CS
,
610 },{ .name
= "TSU_H_CS", .addr
= A_TSU_H_CS
,
612 },{ .name
= "EFUSE_ISR", .addr
= A_EFUSE_ISR
,
615 .post_write
= zynqmp_efuse_isr_postw
,
616 },{ .name
= "EFUSE_IMR", .addr
= A_EFUSE_IMR
,
620 },{ .name
= "EFUSE_IER", .addr
= A_EFUSE_IER
,
622 .pre_write
= zynqmp_efuse_ier_prew
,
623 },{ .name
= "EFUSE_IDR", .addr
= A_EFUSE_IDR
,
625 .pre_write
= zynqmp_efuse_idr_prew
,
626 },{ .name
= "EFUSE_CACHE_LOAD", .addr
= A_EFUSE_CACHE_LOAD
,
627 .pre_write
= zynqmp_efuse_cache_load_prew
,
628 },{ .name
= "EFUSE_PGM_LOCK", .addr
= A_EFUSE_PGM_LOCK
,
629 },{ .name
= "EFUSE_AES_CRC", .addr
= A_EFUSE_AES_CRC
,
630 .post_write
= zynqmp_efuse_aes_crc_postw
,
631 },{ .name
= "EFUSE_TBITS_PRGRMG_EN", .addr
= A_EFUSE_TBITS_PRGRMG_EN
,
632 .reset
= R_EFUSE_TBITS_PRGRMG_EN_TBITS_PRGRMG_EN_MASK
,
633 },{ .name
= "DNA_0", .addr
= A_DNA_0
,
635 },{ .name
= "DNA_1", .addr
= A_DNA_1
,
637 },{ .name
= "DNA_2", .addr
= A_DNA_2
,
639 },{ .name
= "IPDISABLE", .addr
= A_IPDISABLE
,
641 },{ .name
= "SYSOSC_CTRL", .addr
= A_SYSOSC_CTRL
,
643 },{ .name
= "USER_0", .addr
= A_USER_0
,
645 },{ .name
= "USER_1", .addr
= A_USER_1
,
647 },{ .name
= "USER_2", .addr
= A_USER_2
,
649 },{ .name
= "USER_3", .addr
= A_USER_3
,
651 },{ .name
= "USER_4", .addr
= A_USER_4
,
653 },{ .name
= "USER_5", .addr
= A_USER_5
,
655 },{ .name
= "USER_6", .addr
= A_USER_6
,
657 },{ .name
= "USER_7", .addr
= A_USER_7
,
659 },{ .name
= "MISC_USER_CTRL", .addr
= A_MISC_USER_CTRL
,
661 },{ .name
= "ROM_RSVD", .addr
= A_ROM_RSVD
,
663 },{ .name
= "PUF_CHASH", .addr
= A_PUF_CHASH
,
665 },{ .name
= "PUF_MISC", .addr
= A_PUF_MISC
,
667 },{ .name
= "SEC_CTRL", .addr
= A_SEC_CTRL
,
669 },{ .name
= "SPK_ID", .addr
= A_SPK_ID
,
671 },{ .name
= "PPK0_0", .addr
= A_PPK0_0
,
673 },{ .name
= "PPK0_1", .addr
= A_PPK0_1
,
675 },{ .name
= "PPK0_2", .addr
= A_PPK0_2
,
677 },{ .name
= "PPK0_3", .addr
= A_PPK0_3
,
679 },{ .name
= "PPK0_4", .addr
= A_PPK0_4
,
681 },{ .name
= "PPK0_5", .addr
= A_PPK0_5
,
683 },{ .name
= "PPK0_6", .addr
= A_PPK0_6
,
685 },{ .name
= "PPK0_7", .addr
= A_PPK0_7
,
687 },{ .name
= "PPK0_8", .addr
= A_PPK0_8
,
689 },{ .name
= "PPK0_9", .addr
= A_PPK0_9
,
691 },{ .name
= "PPK0_10", .addr
= A_PPK0_10
,
693 },{ .name
= "PPK0_11", .addr
= A_PPK0_11
,
695 },{ .name
= "PPK1_0", .addr
= A_PPK1_0
,
697 },{ .name
= "PPK1_1", .addr
= A_PPK1_1
,
699 },{ .name
= "PPK1_2", .addr
= A_PPK1_2
,
701 },{ .name
= "PPK1_3", .addr
= A_PPK1_3
,
703 },{ .name
= "PPK1_4", .addr
= A_PPK1_4
,
705 },{ .name
= "PPK1_5", .addr
= A_PPK1_5
,
707 },{ .name
= "PPK1_6", .addr
= A_PPK1_6
,
709 },{ .name
= "PPK1_7", .addr
= A_PPK1_7
,
711 },{ .name
= "PPK1_8", .addr
= A_PPK1_8
,
713 },{ .name
= "PPK1_9", .addr
= A_PPK1_9
,
715 },{ .name
= "PPK1_10", .addr
= A_PPK1_10
,
717 },{ .name
= "PPK1_11", .addr
= A_PPK1_11
,
722 static void zynqmp_efuse_reg_write(void *opaque
, hwaddr addr
,
723 uint64_t data
, unsigned size
)
725 RegisterInfoArray
*reg_array
= opaque
;
729 assert(reg_array
!= NULL
);
731 dev
= reg_array
->mem
.owner
;
734 s
= XLNX_ZYNQMP_EFUSE(dev
);
736 if (addr
!= A_WR_LOCK
&& s
->regs
[R_WR_LOCK
]) {
737 g_autofree
char *path
= object_get_canonical_path(OBJECT(s
));
739 qemu_log_mask(LOG_GUEST_ERROR
,
740 "%s[reg_0x%02lx]: Attempt to write locked register.\n",
743 register_write_memory(opaque
, addr
, data
, size
);
747 static const MemoryRegionOps zynqmp_efuse_ops
= {
748 .read
= register_read_memory
,
749 .write
= zynqmp_efuse_reg_write
,
750 .endianness
= DEVICE_LITTLE_ENDIAN
,
752 .min_access_size
= 4,
753 .max_access_size
= 4,
757 static void zynqmp_efuse_register_reset(RegisterInfo
*reg
)
759 if (!reg
->data
|| !reg
->access
) {
763 /* Reset must not trigger some registers' writers */
764 switch (reg
->access
->addr
) {
765 case A_EFUSE_AES_CRC
:
766 *(uint32_t *)reg
->data
= reg
->access
->reset
;
773 static void zynqmp_efuse_reset_hold(Object
*obj
, ResetType type
)
775 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(obj
);
778 for (i
= 0; i
< ARRAY_SIZE(s
->regs_info
); ++i
) {
779 zynqmp_efuse_register_reset(&s
->regs_info
[i
]);
782 zynqmp_efuse_sync_cache(s
, FBIT_UNKNOWN
);
783 ARRAY_FIELD_DP32(s
->regs
, STATUS
, CACHE_DONE
, 1);
784 zynqmp_efuse_update_irq(s
);
787 static void zynqmp_efuse_realize(DeviceState
*dev
, Error
**errp
)
789 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(dev
);
792 g_autofree
char *path
= object_get_canonical_path(OBJECT(s
));
794 error_setg(errp
, "%s.efuse: link property not connected to XLNX-EFUSE",
802 static void zynqmp_efuse_init(Object
*obj
)
804 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(obj
);
805 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
808 register_init_block32(DEVICE(obj
), zynqmp_efuse_regs_info
,
809 ARRAY_SIZE(zynqmp_efuse_regs_info
),
810 s
->regs_info
, s
->regs
,
812 ZYNQMP_EFUSE_ERR_DEBUG
,
815 sysbus_init_mmio(sbd
, &s
->reg_array
->mem
);
816 sysbus_init_irq(sbd
, &s
->irq
);
819 static void zynqmp_efuse_finalize(Object
*obj
)
821 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(obj
);
823 register_finalize_block(s
->reg_array
);
826 static const VMStateDescription vmstate_efuse
= {
827 .name
= TYPE_XLNX_ZYNQMP_EFUSE
,
829 .minimum_version_id
= 1,
830 .fields
= (const VMStateField
[]) {
831 VMSTATE_UINT32_ARRAY(regs
, XlnxZynqMPEFuse
, R_MAX
),
832 VMSTATE_END_OF_LIST(),
836 static Property zynqmp_efuse_props
[] = {
837 DEFINE_PROP_LINK("efuse",
838 XlnxZynqMPEFuse
, efuse
,
839 TYPE_XLNX_EFUSE
, XlnxEFuse
*),
841 DEFINE_PROP_END_OF_LIST(),
844 static void zynqmp_efuse_class_init(ObjectClass
*klass
, void *data
)
846 DeviceClass
*dc
= DEVICE_CLASS(klass
);
847 ResettableClass
*rc
= RESETTABLE_CLASS(klass
);
849 rc
->phases
.hold
= zynqmp_efuse_reset_hold
;
850 dc
->realize
= zynqmp_efuse_realize
;
851 dc
->vmsd
= &vmstate_efuse
;
852 device_class_set_props(dc
, zynqmp_efuse_props
);
856 static const TypeInfo efuse_info
= {
857 .name
= TYPE_XLNX_ZYNQMP_EFUSE
,
858 .parent
= TYPE_SYS_BUS_DEVICE
,
859 .instance_size
= sizeof(XlnxZynqMPEFuse
),
860 .class_init
= zynqmp_efuse_class_init
,
861 .instance_init
= zynqmp_efuse_init
,
862 .instance_finalize
= zynqmp_efuse_finalize
,
865 static void efuse_register_types(void)
867 type_register_static(&efuse_info
);
870 type_init(efuse_register_types
)