2 * QEMU model of the ZynqMP eFuse
4 * Copyright (c) 2015 Xilinx Inc.
6 * Written by Edgar E. Iglesias <edgari@xilinx.com>
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 #include "qemu/osdep.h"
28 #include "hw/nvram/xlnx-zynqmp-efuse.h"
31 #include "qapi/error.h"
32 #include "migration/vmstate.h"
33 #include "hw/qdev-properties.h"
35 #ifndef ZYNQMP_EFUSE_ERR_DEBUG
36 #define ZYNQMP_EFUSE_ERR_DEBUG 0
40 FIELD(WR_LOCK
, LOCK
, 0, 16)
42 FIELD(CFG
, SLVERR_ENABLE
, 5, 1)
43 FIELD(CFG
, MARGIN_RD
, 2, 2)
44 FIELD(CFG
, PGM_EN
, 1, 1)
45 FIELD(CFG
, EFUSE_CLK_SEL
, 0, 1)
47 FIELD(STATUS
, AES_CRC_PASS
, 7, 1)
48 FIELD(STATUS
, AES_CRC_DONE
, 6, 1)
49 FIELD(STATUS
, CACHE_DONE
, 5, 1)
50 FIELD(STATUS
, CACHE_LOAD
, 4, 1)
51 FIELD(STATUS
, EFUSE_3_TBIT
, 2, 1)
52 FIELD(STATUS
, EFUSE_2_TBIT
, 1, 1)
53 FIELD(STATUS
, EFUSE_0_TBIT
, 0, 1)
54 REG32(EFUSE_PGM_ADDR
, 0xc)
55 FIELD(EFUSE_PGM_ADDR
, EFUSE
, 11, 2)
56 FIELD(EFUSE_PGM_ADDR
, ROW
, 5, 6)
57 FIELD(EFUSE_PGM_ADDR
, COLUMN
, 0, 5)
58 REG32(EFUSE_RD_ADDR
, 0x10)
59 FIELD(EFUSE_RD_ADDR
, EFUSE
, 11, 2)
60 FIELD(EFUSE_RD_ADDR
, ROW
, 5, 6)
61 REG32(EFUSE_RD_DATA
, 0x14)
63 FIELD(TPGM
, VALUE
, 0, 16)
65 FIELD(TRD
, VALUE
, 0, 8)
67 FIELD(TSU_H_PS
, VALUE
, 0, 8)
68 REG32(TSU_H_PS_CS
, 0x24)
69 FIELD(TSU_H_PS_CS
, VALUE
, 0, 8)
71 FIELD(TSU_H_CS
, VALUE
, 0, 4)
72 REG32(EFUSE_ISR
, 0x30)
73 FIELD(EFUSE_ISR
, APB_SLVERR
, 31, 1)
74 FIELD(EFUSE_ISR
, CACHE_ERROR
, 4, 1)
75 FIELD(EFUSE_ISR
, RD_ERROR
, 3, 1)
76 FIELD(EFUSE_ISR
, RD_DONE
, 2, 1)
77 FIELD(EFUSE_ISR
, PGM_ERROR
, 1, 1)
78 FIELD(EFUSE_ISR
, PGM_DONE
, 0, 1)
79 REG32(EFUSE_IMR
, 0x34)
80 FIELD(EFUSE_IMR
, APB_SLVERR
, 31, 1)
81 FIELD(EFUSE_IMR
, CACHE_ERROR
, 4, 1)
82 FIELD(EFUSE_IMR
, RD_ERROR
, 3, 1)
83 FIELD(EFUSE_IMR
, RD_DONE
, 2, 1)
84 FIELD(EFUSE_IMR
, PGM_ERROR
, 1, 1)
85 FIELD(EFUSE_IMR
, PGM_DONE
, 0, 1)
86 REG32(EFUSE_IER
, 0x38)
87 FIELD(EFUSE_IER
, APB_SLVERR
, 31, 1)
88 FIELD(EFUSE_IER
, CACHE_ERROR
, 4, 1)
89 FIELD(EFUSE_IER
, RD_ERROR
, 3, 1)
90 FIELD(EFUSE_IER
, RD_DONE
, 2, 1)
91 FIELD(EFUSE_IER
, PGM_ERROR
, 1, 1)
92 FIELD(EFUSE_IER
, PGM_DONE
, 0, 1)
93 REG32(EFUSE_IDR
, 0x3c)
94 FIELD(EFUSE_IDR
, APB_SLVERR
, 31, 1)
95 FIELD(EFUSE_IDR
, CACHE_ERROR
, 4, 1)
96 FIELD(EFUSE_IDR
, RD_ERROR
, 3, 1)
97 FIELD(EFUSE_IDR
, RD_DONE
, 2, 1)
98 FIELD(EFUSE_IDR
, PGM_ERROR
, 1, 1)
99 FIELD(EFUSE_IDR
, PGM_DONE
, 0, 1)
100 REG32(EFUSE_CACHE_LOAD
, 0x40)
101 FIELD(EFUSE_CACHE_LOAD
, LOAD
, 0, 1)
102 REG32(EFUSE_PGM_LOCK
, 0x44)
103 FIELD(EFUSE_PGM_LOCK
, SPK_ID_LOCK
, 0, 1)
104 REG32(EFUSE_AES_CRC
, 0x48)
105 REG32(EFUSE_TBITS_PRGRMG_EN
, 0x100)
106 FIELD(EFUSE_TBITS_PRGRMG_EN
, TBITS_PRGRMG_EN
, 3, 1)
110 REG32(IPDISABLE
, 0x1018)
111 FIELD(IPDISABLE
, VCU_DIS
, 8, 1)
112 FIELD(IPDISABLE
, GPU_DIS
, 5, 1)
113 FIELD(IPDISABLE
, APU3_DIS
, 3, 1)
114 FIELD(IPDISABLE
, APU2_DIS
, 2, 1)
115 FIELD(IPDISABLE
, APU1_DIS
, 1, 1)
116 FIELD(IPDISABLE
, APU0_DIS
, 0, 1)
117 REG32(SYSOSC_CTRL
, 0x101c)
118 FIELD(SYSOSC_CTRL
, SYSOSC_EN
, 0, 1)
119 REG32(USER_0
, 0x1020)
120 REG32(USER_1
, 0x1024)
121 REG32(USER_2
, 0x1028)
122 REG32(USER_3
, 0x102c)
123 REG32(USER_4
, 0x1030)
124 REG32(USER_5
, 0x1034)
125 REG32(USER_6
, 0x1038)
126 REG32(USER_7
, 0x103c)
127 REG32(MISC_USER_CTRL
, 0x1040)
128 FIELD(MISC_USER_CTRL
, FPD_SC_EN_0
, 14, 1)
129 FIELD(MISC_USER_CTRL
, LPD_SC_EN_0
, 11, 1)
130 FIELD(MISC_USER_CTRL
, LBIST_EN
, 10, 1)
131 FIELD(MISC_USER_CTRL
, USR_WRLK_7
, 7, 1)
132 FIELD(MISC_USER_CTRL
, USR_WRLK_6
, 6, 1)
133 FIELD(MISC_USER_CTRL
, USR_WRLK_5
, 5, 1)
134 FIELD(MISC_USER_CTRL
, USR_WRLK_4
, 4, 1)
135 FIELD(MISC_USER_CTRL
, USR_WRLK_3
, 3, 1)
136 FIELD(MISC_USER_CTRL
, USR_WRLK_2
, 2, 1)
137 FIELD(MISC_USER_CTRL
, USR_WRLK_1
, 1, 1)
138 FIELD(MISC_USER_CTRL
, USR_WRLK_0
, 0, 1)
139 REG32(ROM_RSVD
, 0x1044)
140 FIELD(ROM_RSVD
, PBR_BOOT_ERROR
, 0, 3)
141 REG32(PUF_CHASH
, 0x1050)
142 REG32(PUF_MISC
, 0x1054)
143 FIELD(PUF_MISC
, REGISTER_DIS
, 31, 1)
144 FIELD(PUF_MISC
, SYN_WRLK
, 30, 1)
145 FIELD(PUF_MISC
, SYN_INVLD
, 29, 1)
146 FIELD(PUF_MISC
, TEST2_DIS
, 28, 1)
147 FIELD(PUF_MISC
, UNUSED27
, 27, 1)
148 FIELD(PUF_MISC
, UNUSED26
, 26, 1)
149 FIELD(PUF_MISC
, UNUSED25
, 25, 1)
150 FIELD(PUF_MISC
, UNUSED24
, 24, 1)
151 FIELD(PUF_MISC
, AUX
, 0, 24)
152 REG32(SEC_CTRL
, 0x1058)
153 FIELD(SEC_CTRL
, PPK1_INVLD
, 30, 2)
154 FIELD(SEC_CTRL
, PPK1_WRLK
, 29, 1)
155 FIELD(SEC_CTRL
, PPK0_INVLD
, 27, 2)
156 FIELD(SEC_CTRL
, PPK0_WRLK
, 26, 1)
157 FIELD(SEC_CTRL
, RSA_EN
, 11, 15)
158 FIELD(SEC_CTRL
, SEC_LOCK
, 10, 1)
159 FIELD(SEC_CTRL
, PROG_GATE_2
, 9, 1)
160 FIELD(SEC_CTRL
, PROG_GATE_1
, 8, 1)
161 FIELD(SEC_CTRL
, PROG_GATE_0
, 7, 1)
162 FIELD(SEC_CTRL
, DFT_DIS
, 6, 1)
163 FIELD(SEC_CTRL
, JTAG_DIS
, 5, 1)
164 FIELD(SEC_CTRL
, ERROR_DIS
, 4, 1)
165 FIELD(SEC_CTRL
, BBRAM_DIS
, 3, 1)
166 FIELD(SEC_CTRL
, ENC_ONLY
, 2, 1)
167 FIELD(SEC_CTRL
, AES_WRLK
, 1, 1)
168 FIELD(SEC_CTRL
, AES_RDLK
, 0, 1)
169 REG32(SPK_ID
, 0x105c)
170 REG32(PPK0_0
, 0x10a0)
171 REG32(PPK0_1
, 0x10a4)
172 REG32(PPK0_2
, 0x10a8)
173 REG32(PPK0_3
, 0x10ac)
174 REG32(PPK0_4
, 0x10b0)
175 REG32(PPK0_5
, 0x10b4)
176 REG32(PPK0_6
, 0x10b8)
177 REG32(PPK0_7
, 0x10bc)
178 REG32(PPK0_8
, 0x10c0)
179 REG32(PPK0_9
, 0x10c4)
180 REG32(PPK0_10
, 0x10c8)
181 REG32(PPK0_11
, 0x10cc)
182 REG32(PPK1_0
, 0x10d0)
183 REG32(PPK1_1
, 0x10d4)
184 REG32(PPK1_2
, 0x10d8)
185 REG32(PPK1_3
, 0x10dc)
186 REG32(PPK1_4
, 0x10e0)
187 REG32(PPK1_5
, 0x10e4)
188 REG32(PPK1_6
, 0x10e8)
189 REG32(PPK1_7
, 0x10ec)
190 REG32(PPK1_8
, 0x10f0)
191 REG32(PPK1_9
, 0x10f4)
192 REG32(PPK1_10
, 0x10f8)
193 REG32(PPK1_11
, 0x10fc)
195 #define BIT_POS(ROW, COLUMN) (ROW * 32 + COLUMN)
196 #define R_MAX (R_PPK1_11 + 1)
198 /* #define EFUSE_XOSC 26 */
201 * eFUSE layout references:
202 * ZynqMP: UG1085 (v2.1) August 21, 2019, p.277, Table 12-13
204 #define EFUSE_AES_RDLK BIT_POS(22, 0)
205 #define EFUSE_AES_WRLK BIT_POS(22, 1)
206 #define EFUSE_ENC_ONLY BIT_POS(22, 2)
207 #define EFUSE_BBRAM_DIS BIT_POS(22, 3)
208 #define EFUSE_ERROR_DIS BIT_POS(22, 4)
209 #define EFUSE_JTAG_DIS BIT_POS(22, 5)
210 #define EFUSE_DFT_DIS BIT_POS(22, 6)
211 #define EFUSE_PROG_GATE_0 BIT_POS(22, 7)
212 #define EFUSE_PROG_GATE_1 BIT_POS(22, 7)
213 #define EFUSE_PROG_GATE_2 BIT_POS(22, 9)
214 #define EFUSE_SEC_LOCK BIT_POS(22, 10)
215 #define EFUSE_RSA_EN BIT_POS(22, 11)
216 #define EFUSE_RSA_EN14 BIT_POS(22, 25)
217 #define EFUSE_PPK0_WRLK BIT_POS(22, 26)
218 #define EFUSE_PPK0_INVLD BIT_POS(22, 27)
219 #define EFUSE_PPK0_INVLD_1 BIT_POS(22, 28)
220 #define EFUSE_PPK1_WRLK BIT_POS(22, 29)
221 #define EFUSE_PPK1_INVLD BIT_POS(22, 30)
222 #define EFUSE_PPK1_INVLD_1 BIT_POS(22, 31)
225 #define EFUSE_TRIM_START BIT_POS(1, 0)
226 #define EFUSE_TRIM_END BIT_POS(1, 30)
227 #define EFUSE_DNA_START BIT_POS(3, 0)
228 #define EFUSE_DNA_END BIT_POS(5, 31)
229 #define EFUSE_AES_START BIT_POS(24, 0)
230 #define EFUSE_AES_END BIT_POS(31, 31)
231 #define EFUSE_ROM_START BIT_POS(17, 0)
232 #define EFUSE_ROM_END BIT_POS(17, 31)
233 #define EFUSE_IPDIS_START BIT_POS(6, 0)
234 #define EFUSE_IPDIS_END BIT_POS(6, 31)
235 #define EFUSE_USER_START BIT_POS(8, 0)
236 #define EFUSE_USER_END BIT_POS(15, 31)
237 #define EFUSE_BISR_START BIT_POS(32, 0)
238 #define EFUSE_BISR_END BIT_POS(39, 31)
240 #define EFUSE_USER_CTRL_START BIT_POS(16, 0)
241 #define EFUSE_USER_CTRL_END BIT_POS(16, 16)
242 #define EFUSE_USER_CTRL_MASK ((uint32_t)MAKE_64BIT_MASK(0, 17))
244 #define EFUSE_PUF_CHASH_START BIT_POS(20, 0)
245 #define EFUSE_PUF_CHASH_END BIT_POS(20, 31)
246 #define EFUSE_PUF_MISC_START BIT_POS(21, 0)
247 #define EFUSE_PUF_MISC_END BIT_POS(21, 31)
248 #define EFUSE_PUF_SYN_WRLK BIT_POS(21, 30)
250 #define EFUSE_SPK_START BIT_POS(23, 0)
251 #define EFUSE_SPK_END BIT_POS(23, 31)
253 #define EFUSE_PPK0_START BIT_POS(40, 0)
254 #define EFUSE_PPK0_END BIT_POS(51, 31)
255 #define EFUSE_PPK1_START BIT_POS(52, 0)
256 #define EFUSE_PPK1_END BIT_POS(63, 31)
258 #define EFUSE_CACHE_FLD(s, reg, field) \
259 ARRAY_FIELD_DP32((s)->regs, reg, field, \
260 (xlnx_efuse_get_row((s->efuse), EFUSE_ ## field) \
261 >> (EFUSE_ ## field % 32)))
263 #define EFUSE_CACHE_BIT(s, reg, field) \
264 ARRAY_FIELD_DP32((s)->regs, reg, field, xlnx_efuse_get_bit((s->efuse), \
267 #define FBIT_UNKNOWN (~0)
269 QEMU_BUILD_BUG_ON(R_MAX
!= ARRAY_SIZE(((XlnxZynqMPEFuse
*)0)->regs
));
271 static void update_tbit_status(XlnxZynqMPEFuse
*s
)
273 unsigned int check
= xlnx_efuse_tbits_check(s
->efuse
);
274 uint32_t val
= s
->regs
[R_STATUS
];
276 val
= FIELD_DP32(val
, STATUS
, EFUSE_0_TBIT
, !!(check
& (1 << 0)));
277 val
= FIELD_DP32(val
, STATUS
, EFUSE_2_TBIT
, !!(check
& (1 << 1)));
278 val
= FIELD_DP32(val
, STATUS
, EFUSE_3_TBIT
, !!(check
& (1 << 2)));
280 s
->regs
[R_STATUS
] = val
;
283 /* Update the u32 array from efuse bits. Slow but simple approach. */
284 static void cache_sync_u32(XlnxZynqMPEFuse
*s
, unsigned int r_start
,
285 unsigned int f_start
, unsigned int f_end
,
286 unsigned int f_written
)
288 uint32_t *u32
= &s
->regs
[r_start
];
289 unsigned int fbit
, wbits
= 0, u32_off
= 0;
291 /* Avoid working on bits that are not relevant. */
292 if (f_written
!= FBIT_UNKNOWN
293 && (f_written
< f_start
|| f_written
> f_end
)) {
297 for (fbit
= f_start
; fbit
<= f_end
; fbit
++, wbits
++) {
299 /* Update the key offset. */
303 u32
[u32_off
] |= xlnx_efuse_get_bit(s
->efuse
, fbit
) << wbits
;
308 * Keep the syncs in bit order so we can bail out for the
311 static void zynqmp_efuse_sync_cache(XlnxZynqMPEFuse
*s
, unsigned int bit
)
313 EFUSE_CACHE_BIT(s
, SEC_CTRL
, AES_RDLK
);
314 EFUSE_CACHE_BIT(s
, SEC_CTRL
, AES_WRLK
);
315 EFUSE_CACHE_BIT(s
, SEC_CTRL
, ENC_ONLY
);
316 EFUSE_CACHE_BIT(s
, SEC_CTRL
, BBRAM_DIS
);
317 EFUSE_CACHE_BIT(s
, SEC_CTRL
, ERROR_DIS
);
318 EFUSE_CACHE_BIT(s
, SEC_CTRL
, JTAG_DIS
);
319 EFUSE_CACHE_BIT(s
, SEC_CTRL
, DFT_DIS
);
320 EFUSE_CACHE_BIT(s
, SEC_CTRL
, PROG_GATE_0
);
321 EFUSE_CACHE_BIT(s
, SEC_CTRL
, PROG_GATE_1
);
322 EFUSE_CACHE_BIT(s
, SEC_CTRL
, PROG_GATE_2
);
323 EFUSE_CACHE_BIT(s
, SEC_CTRL
, SEC_LOCK
);
324 EFUSE_CACHE_BIT(s
, SEC_CTRL
, PPK0_WRLK
);
325 EFUSE_CACHE_BIT(s
, SEC_CTRL
, PPK1_WRLK
);
327 EFUSE_CACHE_FLD(s
, SEC_CTRL
, RSA_EN
);
328 EFUSE_CACHE_FLD(s
, SEC_CTRL
, PPK0_INVLD
);
329 EFUSE_CACHE_FLD(s
, SEC_CTRL
, PPK1_INVLD
);
331 /* Update the tbits. */
332 update_tbit_status(s
);
334 /* Sync the various areas. */
335 s
->regs
[R_MISC_USER_CTRL
] = xlnx_efuse_get_row(s
->efuse
,
336 EFUSE_USER_CTRL_START
)
337 & EFUSE_USER_CTRL_MASK
;
338 s
->regs
[R_PUF_CHASH
] = xlnx_efuse_get_row(s
->efuse
, EFUSE_PUF_CHASH_START
);
339 s
->regs
[R_PUF_MISC
] = xlnx_efuse_get_row(s
->efuse
, EFUSE_PUF_MISC_START
);
341 cache_sync_u32(s
, R_DNA_0
, EFUSE_DNA_START
, EFUSE_DNA_END
, bit
);
343 if (bit
< EFUSE_AES_START
) {
347 cache_sync_u32(s
, R_ROM_RSVD
, EFUSE_ROM_START
, EFUSE_ROM_END
, bit
);
348 cache_sync_u32(s
, R_IPDISABLE
, EFUSE_IPDIS_START
, EFUSE_IPDIS_END
, bit
);
349 cache_sync_u32(s
, R_USER_0
, EFUSE_USER_START
, EFUSE_USER_END
, bit
);
350 cache_sync_u32(s
, R_SPK_ID
, EFUSE_SPK_START
, EFUSE_SPK_END
, bit
);
351 cache_sync_u32(s
, R_PPK0_0
, EFUSE_PPK0_START
, EFUSE_PPK0_END
, bit
);
352 cache_sync_u32(s
, R_PPK1_0
, EFUSE_PPK1_START
, EFUSE_PPK1_END
, bit
);
355 static void zynqmp_efuse_update_irq(XlnxZynqMPEFuse
*s
)
357 bool pending
= s
->regs
[R_EFUSE_ISR
] & s
->regs
[R_EFUSE_IMR
];
358 qemu_set_irq(s
->irq
, pending
);
361 static void zynqmp_efuse_isr_postw(RegisterInfo
*reg
, uint64_t val64
)
363 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(reg
->opaque
);
364 zynqmp_efuse_update_irq(s
);
367 static uint64_t zynqmp_efuse_ier_prew(RegisterInfo
*reg
, uint64_t val64
)
369 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(reg
->opaque
);
370 uint32_t val
= val64
;
372 s
->regs
[R_EFUSE_IMR
] |= val
;
373 zynqmp_efuse_update_irq(s
);
377 static uint64_t zynqmp_efuse_idr_prew(RegisterInfo
*reg
, uint64_t val64
)
379 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(reg
->opaque
);
380 uint32_t val
= val64
;
382 s
->regs
[R_EFUSE_IMR
] &= ~val
;
383 zynqmp_efuse_update_irq(s
);
387 static void zynqmp_efuse_pgm_addr_postw(RegisterInfo
*reg
, uint64_t val64
)
389 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(reg
->opaque
);
390 unsigned bit
= val64
;
391 unsigned page
= FIELD_EX32(bit
, EFUSE_PGM_ADDR
, EFUSE
);
392 bool puf_prot
= false;
393 const char *errmsg
= NULL
;
395 /* Allow only valid array, and adjust for skipped array 1 */
400 bit
= FIELD_DP32(bit
, EFUSE_PGM_ADDR
, EFUSE
, page
- 1);
401 puf_prot
= xlnx_efuse_get_bit(s
->efuse
, EFUSE_PUF_SYN_WRLK
);
404 errmsg
= "Invalid address";
408 if (ARRAY_FIELD_EX32(s
->regs
, WR_LOCK
, LOCK
)) {
409 errmsg
= "Array write-locked";
413 if (!ARRAY_FIELD_EX32(s
->regs
, CFG
, PGM_EN
)) {
414 errmsg
= "Array pgm-disabled";
419 errmsg
= "PUF_HD-store write-locked";
423 if (ARRAY_FIELD_EX32(s
->regs
, SEC_CTRL
, AES_WRLK
)
424 && bit
>= EFUSE_AES_START
&& bit
<= EFUSE_AES_END
) {
425 errmsg
= "AES key-store Write-locked";
429 if (!xlnx_efuse_set_bit(s
->efuse
, bit
)) {
430 errmsg
= "Write failed";
435 ARRAY_FIELD_DP32(s
->regs
, EFUSE_ISR
, PGM_ERROR
, 0);
437 g_autofree
char *path
= object_get_canonical_path(OBJECT(s
));
439 ARRAY_FIELD_DP32(s
->regs
, EFUSE_ISR
, PGM_ERROR
, 1);
440 qemu_log_mask(LOG_GUEST_ERROR
,
441 "%s - eFuse write error: %s; addr=0x%x\n",
442 path
, errmsg
, (unsigned)val64
);
445 ARRAY_FIELD_DP32(s
->regs
, EFUSE_ISR
, PGM_DONE
, 1);
446 zynqmp_efuse_update_irq(s
);
449 static void zynqmp_efuse_rd_addr_postw(RegisterInfo
*reg
, uint64_t val64
)
451 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(reg
->opaque
);
452 g_autofree
char *path
= NULL
;
455 * Grant reads only to allowed bits; reference sources:
456 * 1/ XilSKey - XilSKey_ZynqMp_EfusePs_ReadRow()
457 * 2/ UG1085, v2.0, table 12-13
458 * (note: enumerates the masks as <first, last> per described in
459 * references to avoid mental translation).
461 #define COL_MASK(L_, H_) \
462 ((uint32_t)MAKE_64BIT_MASK((L_), (1 + (H_) - (L_))))
464 static const uint32_t ary0_col_mask
[] = {
465 /* XilSKey - XSK_ZYNQMP_EFUSEPS_TBITS_ROW */
466 [0] = COL_MASK(28, 31),
468 /* XilSKey - XSK_ZYNQMP_EFUSEPS_USR{0:7}_FUSE_ROW */
469 [8] = COL_MASK(0, 31), [9] = COL_MASK(0, 31),
470 [10] = COL_MASK(0, 31), [11] = COL_MASK(0, 31),
471 [12] = COL_MASK(0, 31), [13] = COL_MASK(0, 31),
472 [14] = COL_MASK(0, 31), [15] = COL_MASK(0, 31),
474 /* XilSKey - XSK_ZYNQMP_EFUSEPS_MISC_USR_CTRL_ROW */
475 [16] = COL_MASK(0, 7) | COL_MASK(10, 16),
477 /* XilSKey - XSK_ZYNQMP_EFUSEPS_PBR_BOOT_ERR_ROW */
478 [17] = COL_MASK(0, 2),
480 /* XilSKey - XSK_ZYNQMP_EFUSEPS_PUF_CHASH_ROW */
481 [20] = COL_MASK(0, 31),
483 /* XilSKey - XSK_ZYNQMP_EFUSEPS_PUF_AUX_ROW */
484 [21] = COL_MASK(0, 23) | COL_MASK(29, 31),
486 /* XilSKey - XSK_ZYNQMP_EFUSEPS_SEC_CTRL_ROW */
487 [22] = COL_MASK(0, 31),
489 /* XilSKey - XSK_ZYNQMP_EFUSEPS_SPK_ID_ROW */
490 [23] = COL_MASK(0, 31),
492 /* XilSKey - XSK_ZYNQMP_EFUSEPS_PPK0_START_ROW */
493 [40] = COL_MASK(0, 31), [41] = COL_MASK(0, 31),
494 [42] = COL_MASK(0, 31), [43] = COL_MASK(0, 31),
495 [44] = COL_MASK(0, 31), [45] = COL_MASK(0, 31),
496 [46] = COL_MASK(0, 31), [47] = COL_MASK(0, 31),
497 [48] = COL_MASK(0, 31), [49] = COL_MASK(0, 31),
498 [50] = COL_MASK(0, 31), [51] = COL_MASK(0, 31),
500 /* XilSKey - XSK_ZYNQMP_EFUSEPS_PPK1_START_ROW */
501 [52] = COL_MASK(0, 31), [53] = COL_MASK(0, 31),
502 [54] = COL_MASK(0, 31), [55] = COL_MASK(0, 31),
503 [56] = COL_MASK(0, 31), [57] = COL_MASK(0, 31),
504 [58] = COL_MASK(0, 31), [59] = COL_MASK(0, 31),
505 [60] = COL_MASK(0, 31), [61] = COL_MASK(0, 31),
506 [62] = COL_MASK(0, 31), [63] = COL_MASK(0, 31),
509 uint32_t col_mask
= COL_MASK(0, 31);
512 uint32_t efuse_idx
= s
->regs
[R_EFUSE_RD_ADDR
];
513 uint32_t efuse_ary
= FIELD_EX32(efuse_idx
, EFUSE_RD_ADDR
, EFUSE
);
514 uint32_t efuse_row
= FIELD_EX32(efuse_idx
, EFUSE_RD_ADDR
, ROW
);
517 case 0: /* Various */
518 if (efuse_row
>= ARRAY_SIZE(ary0_col_mask
)) {
522 col_mask
= ary0_col_mask
[efuse_row
];
527 case 2: /* PUF helper data, adjust for skipped array 1 */
529 val64
= FIELD_DP32(efuse_idx
, EFUSE_RD_ADDR
, EFUSE
, efuse_ary
- 1);
535 s
->regs
[R_EFUSE_RD_DATA
] = xlnx_efuse_get_row(s
->efuse
, val64
) & col_mask
;
537 ARRAY_FIELD_DP32(s
->regs
, EFUSE_ISR
, RD_ERROR
, 0);
538 ARRAY_FIELD_DP32(s
->regs
, EFUSE_ISR
, RD_DONE
, 1);
539 zynqmp_efuse_update_irq(s
);
543 path
= object_get_canonical_path(OBJECT(s
));
544 qemu_log_mask(LOG_GUEST_ERROR
,
545 "%s: Denied efuse read from array %u, row %u\n",
546 path
, efuse_ary
, efuse_row
);
548 s
->regs
[R_EFUSE_RD_DATA
] = 0;
550 ARRAY_FIELD_DP32(s
->regs
, EFUSE_ISR
, RD_ERROR
, 1);
551 ARRAY_FIELD_DP32(s
->regs
, EFUSE_ISR
, RD_DONE
, 0);
552 zynqmp_efuse_update_irq(s
);
555 static void zynqmp_efuse_aes_crc_postw(RegisterInfo
*reg
, uint64_t val64
)
557 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(reg
->opaque
);
560 ok
= xlnx_efuse_k256_check(s
->efuse
, (uint32_t)val64
, EFUSE_AES_START
);
562 ARRAY_FIELD_DP32(s
->regs
, STATUS
, AES_CRC_PASS
, (ok
? 1 : 0));
563 ARRAY_FIELD_DP32(s
->regs
, STATUS
, AES_CRC_DONE
, 1);
565 s
->regs
[R_EFUSE_AES_CRC
] = 0; /* crc value is write-only */
568 static uint64_t zynqmp_efuse_cache_load_prew(RegisterInfo
*reg
,
571 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(reg
->opaque
);
573 if (valu64
& R_EFUSE_CACHE_LOAD_LOAD_MASK
) {
574 zynqmp_efuse_sync_cache(s
, FBIT_UNKNOWN
);
575 ARRAY_FIELD_DP32(s
->regs
, STATUS
, CACHE_DONE
, 1);
576 zynqmp_efuse_update_irq(s
);
582 static uint64_t zynqmp_efuse_wr_lock_prew(RegisterInfo
*reg
, uint64_t val
)
584 return val
== 0xDF0D ? 0 : 1;
587 static RegisterAccessInfo zynqmp_efuse_regs_info
[] = {
588 { .name
= "WR_LOCK", .addr
= A_WR_LOCK
,
590 .pre_write
= zynqmp_efuse_wr_lock_prew
,
591 },{ .name
= "CFG", .addr
= A_CFG
,
592 },{ .name
= "STATUS", .addr
= A_STATUS
,
595 },{ .name
= "EFUSE_PGM_ADDR", .addr
= A_EFUSE_PGM_ADDR
,
596 .post_write
= zynqmp_efuse_pgm_addr_postw
597 },{ .name
= "EFUSE_RD_ADDR", .addr
= A_EFUSE_RD_ADDR
,
599 .post_write
= zynqmp_efuse_rd_addr_postw
,
600 },{ .name
= "EFUSE_RD_DATA", .addr
= A_EFUSE_RD_DATA
,
602 },{ .name
= "TPGM", .addr
= A_TPGM
,
603 },{ .name
= "TRD", .addr
= A_TRD
,
605 },{ .name
= "TSU_H_PS", .addr
= A_TSU_H_PS
,
607 },{ .name
= "TSU_H_PS_CS", .addr
= A_TSU_H_PS_CS
,
609 },{ .name
= "TSU_H_CS", .addr
= A_TSU_H_CS
,
611 },{ .name
= "EFUSE_ISR", .addr
= A_EFUSE_ISR
,
614 .post_write
= zynqmp_efuse_isr_postw
,
615 },{ .name
= "EFUSE_IMR", .addr
= A_EFUSE_IMR
,
619 },{ .name
= "EFUSE_IER", .addr
= A_EFUSE_IER
,
621 .pre_write
= zynqmp_efuse_ier_prew
,
622 },{ .name
= "EFUSE_IDR", .addr
= A_EFUSE_IDR
,
624 .pre_write
= zynqmp_efuse_idr_prew
,
625 },{ .name
= "EFUSE_CACHE_LOAD", .addr
= A_EFUSE_CACHE_LOAD
,
626 .pre_write
= zynqmp_efuse_cache_load_prew
,
627 },{ .name
= "EFUSE_PGM_LOCK", .addr
= A_EFUSE_PGM_LOCK
,
628 },{ .name
= "EFUSE_AES_CRC", .addr
= A_EFUSE_AES_CRC
,
629 .post_write
= zynqmp_efuse_aes_crc_postw
,
630 },{ .name
= "EFUSE_TBITS_PRGRMG_EN", .addr
= A_EFUSE_TBITS_PRGRMG_EN
,
631 .reset
= R_EFUSE_TBITS_PRGRMG_EN_TBITS_PRGRMG_EN_MASK
,
632 },{ .name
= "DNA_0", .addr
= A_DNA_0
,
634 },{ .name
= "DNA_1", .addr
= A_DNA_1
,
636 },{ .name
= "DNA_2", .addr
= A_DNA_2
,
638 },{ .name
= "IPDISABLE", .addr
= A_IPDISABLE
,
640 },{ .name
= "SYSOSC_CTRL", .addr
= A_SYSOSC_CTRL
,
642 },{ .name
= "USER_0", .addr
= A_USER_0
,
644 },{ .name
= "USER_1", .addr
= A_USER_1
,
646 },{ .name
= "USER_2", .addr
= A_USER_2
,
648 },{ .name
= "USER_3", .addr
= A_USER_3
,
650 },{ .name
= "USER_4", .addr
= A_USER_4
,
652 },{ .name
= "USER_5", .addr
= A_USER_5
,
654 },{ .name
= "USER_6", .addr
= A_USER_6
,
656 },{ .name
= "USER_7", .addr
= A_USER_7
,
658 },{ .name
= "MISC_USER_CTRL", .addr
= A_MISC_USER_CTRL
,
660 },{ .name
= "ROM_RSVD", .addr
= A_ROM_RSVD
,
662 },{ .name
= "PUF_CHASH", .addr
= A_PUF_CHASH
,
664 },{ .name
= "PUF_MISC", .addr
= A_PUF_MISC
,
666 },{ .name
= "SEC_CTRL", .addr
= A_SEC_CTRL
,
668 },{ .name
= "SPK_ID", .addr
= A_SPK_ID
,
670 },{ .name
= "PPK0_0", .addr
= A_PPK0_0
,
672 },{ .name
= "PPK0_1", .addr
= A_PPK0_1
,
674 },{ .name
= "PPK0_2", .addr
= A_PPK0_2
,
676 },{ .name
= "PPK0_3", .addr
= A_PPK0_3
,
678 },{ .name
= "PPK0_4", .addr
= A_PPK0_4
,
680 },{ .name
= "PPK0_5", .addr
= A_PPK0_5
,
682 },{ .name
= "PPK0_6", .addr
= A_PPK0_6
,
684 },{ .name
= "PPK0_7", .addr
= A_PPK0_7
,
686 },{ .name
= "PPK0_8", .addr
= A_PPK0_8
,
688 },{ .name
= "PPK0_9", .addr
= A_PPK0_9
,
690 },{ .name
= "PPK0_10", .addr
= A_PPK0_10
,
692 },{ .name
= "PPK0_11", .addr
= A_PPK0_11
,
694 },{ .name
= "PPK1_0", .addr
= A_PPK1_0
,
696 },{ .name
= "PPK1_1", .addr
= A_PPK1_1
,
698 },{ .name
= "PPK1_2", .addr
= A_PPK1_2
,
700 },{ .name
= "PPK1_3", .addr
= A_PPK1_3
,
702 },{ .name
= "PPK1_4", .addr
= A_PPK1_4
,
704 },{ .name
= "PPK1_5", .addr
= A_PPK1_5
,
706 },{ .name
= "PPK1_6", .addr
= A_PPK1_6
,
708 },{ .name
= "PPK1_7", .addr
= A_PPK1_7
,
710 },{ .name
= "PPK1_8", .addr
= A_PPK1_8
,
712 },{ .name
= "PPK1_9", .addr
= A_PPK1_9
,
714 },{ .name
= "PPK1_10", .addr
= A_PPK1_10
,
716 },{ .name
= "PPK1_11", .addr
= A_PPK1_11
,
721 static void zynqmp_efuse_reg_write(void *opaque
, hwaddr addr
,
722 uint64_t data
, unsigned size
)
724 RegisterInfoArray
*reg_array
= opaque
;
728 assert(reg_array
!= NULL
);
730 dev
= reg_array
->mem
.owner
;
733 s
= XLNX_ZYNQMP_EFUSE(dev
);
735 if (addr
!= A_WR_LOCK
&& s
->regs
[R_WR_LOCK
]) {
736 g_autofree
char *path
= object_get_canonical_path(OBJECT(s
));
738 qemu_log_mask(LOG_GUEST_ERROR
,
739 "%s[reg_0x%02lx]: Attempt to write locked register.\n",
742 register_write_memory(opaque
, addr
, data
, size
);
746 static const MemoryRegionOps zynqmp_efuse_ops
= {
747 .read
= register_read_memory
,
748 .write
= zynqmp_efuse_reg_write
,
749 .endianness
= DEVICE_LITTLE_ENDIAN
,
751 .min_access_size
= 4,
752 .max_access_size
= 4,
756 static void zynqmp_efuse_register_reset(RegisterInfo
*reg
)
758 if (!reg
->data
|| !reg
->access
) {
762 /* Reset must not trigger some registers' writers */
763 switch (reg
->access
->addr
) {
764 case A_EFUSE_AES_CRC
:
765 *(uint32_t *)reg
->data
= reg
->access
->reset
;
772 static void zynqmp_efuse_reset(DeviceState
*dev
)
774 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(dev
);
777 for (i
= 0; i
< ARRAY_SIZE(s
->regs_info
); ++i
) {
778 zynqmp_efuse_register_reset(&s
->regs_info
[i
]);
781 zynqmp_efuse_sync_cache(s
, FBIT_UNKNOWN
);
782 ARRAY_FIELD_DP32(s
->regs
, STATUS
, CACHE_DONE
, 1);
783 zynqmp_efuse_update_irq(s
);
786 static void zynqmp_efuse_realize(DeviceState
*dev
, Error
**errp
)
788 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(dev
);
791 g_autofree
char *path
= object_get_canonical_path(OBJECT(s
));
793 error_setg(errp
, "%s.efuse: link property not connected to XLNX-EFUSE",
801 static void zynqmp_efuse_init(Object
*obj
)
803 XlnxZynqMPEFuse
*s
= XLNX_ZYNQMP_EFUSE(obj
);
804 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
805 RegisterInfoArray
*reg_array
;
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
, ®_array
->mem
);
816 sysbus_init_irq(sbd
, &s
->irq
);
819 static const VMStateDescription vmstate_efuse
= {
820 .name
= TYPE_XLNX_ZYNQMP_EFUSE
,
822 .minimum_version_id
= 1,
823 .fields
= (VMStateField
[]) {
824 VMSTATE_UINT32_ARRAY(regs
, XlnxZynqMPEFuse
, R_MAX
),
825 VMSTATE_END_OF_LIST(),
829 static Property zynqmp_efuse_props
[] = {
830 DEFINE_PROP_LINK("efuse",
831 XlnxZynqMPEFuse
, efuse
,
832 TYPE_XLNX_EFUSE
, XlnxEFuse
*),
834 DEFINE_PROP_END_OF_LIST(),
837 static void zynqmp_efuse_class_init(ObjectClass
*klass
, void *data
)
839 DeviceClass
*dc
= DEVICE_CLASS(klass
);
841 dc
->reset
= zynqmp_efuse_reset
;
842 dc
->realize
= zynqmp_efuse_realize
;
843 dc
->vmsd
= &vmstate_efuse
;
844 device_class_set_props(dc
, zynqmp_efuse_props
);
848 static const TypeInfo efuse_info
= {
849 .name
= TYPE_XLNX_ZYNQMP_EFUSE
,
850 .parent
= TYPE_SYS_BUS_DEVICE
,
851 .instance_size
= sizeof(XlnxZynqMPEFuse
),
852 .class_init
= zynqmp_efuse_class_init
,
853 .instance_init
= zynqmp_efuse_init
,
856 static void efuse_register_types(void)
858 type_register_static(&efuse_info
);
861 type_init(efuse_register_types
)