qapi: Improve specificity of type/member descriptions
[qemu/armbru.git] / hw / nvram / xlnx-zynqmp-efuse.c
blob228ba0bbfaf19607d28225b99e071b75630c33ac
1 /*
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
24 * THE SOFTWARE.
27 #include "qemu/osdep.h"
28 #include "hw/nvram/xlnx-zynqmp-efuse.h"
30 #include "qemu/log.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
37 #endif
39 REG32(WR_LOCK, 0x0)
40 FIELD(WR_LOCK, LOCK, 0, 16)
41 REG32(CFG, 0x4)
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)
46 REG32(STATUS, 0x8)
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)
62 REG32(TPGM, 0x18)
63 FIELD(TPGM, VALUE, 0, 16)
64 REG32(TRD, 0x1c)
65 FIELD(TRD, VALUE, 0, 8)
66 REG32(TSU_H_PS, 0x20)
67 FIELD(TSU_H_PS, VALUE, 0, 8)
68 REG32(TSU_H_PS_CS, 0x24)
69 FIELD(TSU_H_PS_CS, VALUE, 0, 8)
70 REG32(TSU_H_CS, 0x2c)
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)
107 REG32(DNA_0, 0x100c)
108 REG32(DNA_1, 0x1010)
109 REG32(DNA_2, 0x1014)
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)
224 /* Areas. */
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), \
265 EFUSE_ ## field))
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)) {
294 return;
297 for (fbit = f_start; fbit <= f_end; fbit++, wbits++) {
298 if (wbits == 32) {
299 /* Update the key offset. */
300 u32_off += 1;
301 wbits = 0;
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
309 * slower ones.
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) {
344 return;
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);
374 return 0;
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);
384 return 0;
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 */
396 switch (page) {
397 case 0:
398 break;
399 case 2 ... 3:
400 bit = FIELD_DP32(bit, EFUSE_PGM_ADDR, EFUSE, page - 1);
401 puf_prot = xlnx_efuse_get_bit(s->efuse, EFUSE_PUF_SYN_WRLK);
402 break;
403 default:
404 errmsg = "Invalid address";
405 goto pgm_done;
408 if (ARRAY_FIELD_EX32(s->regs, WR_LOCK, LOCK)) {
409 errmsg = "Array write-locked";
410 goto pgm_done;
413 if (!ARRAY_FIELD_EX32(s->regs, CFG, PGM_EN)) {
414 errmsg = "Array pgm-disabled";
415 goto pgm_done;
418 if (puf_prot) {
419 errmsg = "PUF_HD-store write-locked";
420 goto pgm_done;
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";
426 goto pgm_done;
429 if (!xlnx_efuse_set_bit(s->efuse, bit)) {
430 errmsg = "Write failed";
433 pgm_done:
434 if (!errmsg) {
435 ARRAY_FIELD_DP32(s->regs, EFUSE_ISR, PGM_ERROR, 0);
436 } else {
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);
510 #undef COL_MASK
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);
516 switch (efuse_ary) {
517 case 0: /* Various */
518 if (efuse_row >= ARRAY_SIZE(ary0_col_mask)) {
519 goto denied;
522 col_mask = ary0_col_mask[efuse_row];
523 if (!col_mask) {
524 goto denied;
526 break;
527 case 2: /* PUF helper data, adjust for skipped array 1 */
528 case 3:
529 val64 = FIELD_DP32(efuse_idx, EFUSE_RD_ADDR, EFUSE, efuse_ary - 1);
530 break;
531 default:
532 goto denied;
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);
540 return;
542 denied:
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);
558 bool ok;
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,
569 uint64_t valu64)
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);
579 return 0;
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,
589 .reset = 0x1,
590 .pre_write = zynqmp_efuse_wr_lock_prew,
591 },{ .name = "CFG", .addr = A_CFG,
592 },{ .name = "STATUS", .addr = A_STATUS,
593 .rsvd = 0x8,
594 .ro = 0xff,
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,
598 .rsvd = 0x1f,
599 .post_write = zynqmp_efuse_rd_addr_postw,
600 },{ .name = "EFUSE_RD_DATA", .addr = A_EFUSE_RD_DATA,
601 .ro = 0xffffffff,
602 },{ .name = "TPGM", .addr = A_TPGM,
603 },{ .name = "TRD", .addr = A_TRD,
604 .reset = 0x1b,
605 },{ .name = "TSU_H_PS", .addr = A_TSU_H_PS,
606 .reset = 0xff,
607 },{ .name = "TSU_H_PS_CS", .addr = A_TSU_H_PS_CS,
608 .reset = 0xb,
609 },{ .name = "TSU_H_CS", .addr = A_TSU_H_CS,
610 .reset = 0x7,
611 },{ .name = "EFUSE_ISR", .addr = A_EFUSE_ISR,
612 .rsvd = 0x7fffffe0,
613 .w1c = 0x8000001f,
614 .post_write = zynqmp_efuse_isr_postw,
615 },{ .name = "EFUSE_IMR", .addr = A_EFUSE_IMR,
616 .reset = 0x8000001f,
617 .rsvd = 0x7fffffe0,
618 .ro = 0xffffffff,
619 },{ .name = "EFUSE_IER", .addr = A_EFUSE_IER,
620 .rsvd = 0x7fffffe0,
621 .pre_write = zynqmp_efuse_ier_prew,
622 },{ .name = "EFUSE_IDR", .addr = A_EFUSE_IDR,
623 .rsvd = 0x7fffffe0,
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,
633 .ro = 0xffffffff,
634 },{ .name = "DNA_1", .addr = A_DNA_1,
635 .ro = 0xffffffff,
636 },{ .name = "DNA_2", .addr = A_DNA_2,
637 .ro = 0xffffffff,
638 },{ .name = "IPDISABLE", .addr = A_IPDISABLE,
639 .ro = 0xffffffff,
640 },{ .name = "SYSOSC_CTRL", .addr = A_SYSOSC_CTRL,
641 .ro = 0xffffffff,
642 },{ .name = "USER_0", .addr = A_USER_0,
643 .ro = 0xffffffff,
644 },{ .name = "USER_1", .addr = A_USER_1,
645 .ro = 0xffffffff,
646 },{ .name = "USER_2", .addr = A_USER_2,
647 .ro = 0xffffffff,
648 },{ .name = "USER_3", .addr = A_USER_3,
649 .ro = 0xffffffff,
650 },{ .name = "USER_4", .addr = A_USER_4,
651 .ro = 0xffffffff,
652 },{ .name = "USER_5", .addr = A_USER_5,
653 .ro = 0xffffffff,
654 },{ .name = "USER_6", .addr = A_USER_6,
655 .ro = 0xffffffff,
656 },{ .name = "USER_7", .addr = A_USER_7,
657 .ro = 0xffffffff,
658 },{ .name = "MISC_USER_CTRL", .addr = A_MISC_USER_CTRL,
659 .ro = 0xffffffff,
660 },{ .name = "ROM_RSVD", .addr = A_ROM_RSVD,
661 .ro = 0xffffffff,
662 },{ .name = "PUF_CHASH", .addr = A_PUF_CHASH,
663 .ro = 0xffffffff,
664 },{ .name = "PUF_MISC", .addr = A_PUF_MISC,
665 .ro = 0xffffffff,
666 },{ .name = "SEC_CTRL", .addr = A_SEC_CTRL,
667 .ro = 0xffffffff,
668 },{ .name = "SPK_ID", .addr = A_SPK_ID,
669 .ro = 0xffffffff,
670 },{ .name = "PPK0_0", .addr = A_PPK0_0,
671 .ro = 0xffffffff,
672 },{ .name = "PPK0_1", .addr = A_PPK0_1,
673 .ro = 0xffffffff,
674 },{ .name = "PPK0_2", .addr = A_PPK0_2,
675 .ro = 0xffffffff,
676 },{ .name = "PPK0_3", .addr = A_PPK0_3,
677 .ro = 0xffffffff,
678 },{ .name = "PPK0_4", .addr = A_PPK0_4,
679 .ro = 0xffffffff,
680 },{ .name = "PPK0_5", .addr = A_PPK0_5,
681 .ro = 0xffffffff,
682 },{ .name = "PPK0_6", .addr = A_PPK0_6,
683 .ro = 0xffffffff,
684 },{ .name = "PPK0_7", .addr = A_PPK0_7,
685 .ro = 0xffffffff,
686 },{ .name = "PPK0_8", .addr = A_PPK0_8,
687 .ro = 0xffffffff,
688 },{ .name = "PPK0_9", .addr = A_PPK0_9,
689 .ro = 0xffffffff,
690 },{ .name = "PPK0_10", .addr = A_PPK0_10,
691 .ro = 0xffffffff,
692 },{ .name = "PPK0_11", .addr = A_PPK0_11,
693 .ro = 0xffffffff,
694 },{ .name = "PPK1_0", .addr = A_PPK1_0,
695 .ro = 0xffffffff,
696 },{ .name = "PPK1_1", .addr = A_PPK1_1,
697 .ro = 0xffffffff,
698 },{ .name = "PPK1_2", .addr = A_PPK1_2,
699 .ro = 0xffffffff,
700 },{ .name = "PPK1_3", .addr = A_PPK1_3,
701 .ro = 0xffffffff,
702 },{ .name = "PPK1_4", .addr = A_PPK1_4,
703 .ro = 0xffffffff,
704 },{ .name = "PPK1_5", .addr = A_PPK1_5,
705 .ro = 0xffffffff,
706 },{ .name = "PPK1_6", .addr = A_PPK1_6,
707 .ro = 0xffffffff,
708 },{ .name = "PPK1_7", .addr = A_PPK1_7,
709 .ro = 0xffffffff,
710 },{ .name = "PPK1_8", .addr = A_PPK1_8,
711 .ro = 0xffffffff,
712 },{ .name = "PPK1_9", .addr = A_PPK1_9,
713 .ro = 0xffffffff,
714 },{ .name = "PPK1_10", .addr = A_PPK1_10,
715 .ro = 0xffffffff,
716 },{ .name = "PPK1_11", .addr = A_PPK1_11,
717 .ro = 0xffffffff,
721 static void zynqmp_efuse_reg_write(void *opaque, hwaddr addr,
722 uint64_t data, unsigned size)
724 RegisterInfoArray *reg_array = opaque;
725 XlnxZynqMPEFuse *s;
726 Object *dev;
728 assert(reg_array != NULL);
730 dev = reg_array->mem.owner;
731 assert(dev);
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",
740 path, (long)addr);
741 } else {
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,
750 .valid = {
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) {
759 return;
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;
766 return;
769 register_reset(reg);
772 static void zynqmp_efuse_reset(DeviceState *dev)
774 XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(dev);
775 unsigned int i;
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);
790 if (!s->efuse) {
791 g_autofree char *path = object_get_canonical_path(OBJECT(s));
793 error_setg(errp, "%s.efuse: link property not connected to XLNX-EFUSE",
794 path);
795 return;
798 s->efuse->dev = dev;
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;
807 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,
811 &zynqmp_efuse_ops,
812 ZYNQMP_EFUSE_ERR_DEBUG,
813 R_MAX * 4);
815 sysbus_init_mmio(sbd, &reg_array->mem);
816 sysbus_init_irq(sbd, &s->irq);
819 static const VMStateDescription vmstate_efuse = {
820 .name = TYPE_XLNX_ZYNQMP_EFUSE,
821 .version_id = 1,
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)