qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

xlnx-zynqmp-efuse.c (28267B)


      1 /*
      2  * QEMU model of the ZynqMP eFuse
      3  *
      4  * Copyright (c) 2015 Xilinx Inc.
      5  *
      6  * Written by Edgar E. Iglesias <edgari@xilinx.com>
      7  *
      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:
     14  *
     15  * The above copyright notice and this permission notice shall be included in
     16  * all copies or substantial portions of the Software.
     17  *
     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.
     25  */
     26 
     27 #include "qemu/osdep.h"
     28 #include "hw/nvram/xlnx-zynqmp-efuse.h"
     29 
     30 #include "qemu/log.h"
     31 #include "qapi/error.h"
     32 #include "migration/vmstate.h"
     33 #include "hw/qdev-properties.h"
     34 
     35 #ifndef ZYNQMP_EFUSE_ERR_DEBUG
     36 #define ZYNQMP_EFUSE_ERR_DEBUG 0
     37 #endif
     38 
     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)
    194 
    195 #define BIT_POS(ROW, COLUMN)    (ROW * 32 + COLUMN)
    196 #define R_MAX (R_PPK1_11 + 1)
    197 
    198 /* #define EFUSE_XOSC            26 */
    199 
    200 /*
    201  * eFUSE layout references:
    202  *   ZynqMP: UG1085 (v2.1) August 21, 2019, p.277, Table 12-13
    203  */
    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)
    223 
    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)
    239 
    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))
    243 
    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)
    249 
    250 #define EFUSE_SPK_START       BIT_POS(23, 0)
    251 #define EFUSE_SPK_END         BIT_POS(23, 31)
    252 
    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)
    257 
    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)))
    262 
    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))
    266 
    267 #define FBIT_UNKNOWN (~0)
    268 
    269 QEMU_BUILD_BUG_ON(R_MAX != ARRAY_SIZE(((XlnxZynqMPEFuse *)0)->regs));
    270 
    271 static void update_tbit_status(XlnxZynqMPEFuse *s)
    272 {
    273     unsigned int check = xlnx_efuse_tbits_check(s->efuse);
    274     uint32_t val = s->regs[R_STATUS];
    275 
    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)));
    279 
    280     s->regs[R_STATUS] = val;
    281 }
    282 
    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)
    287 {
    288     uint32_t *u32 = &s->regs[r_start];
    289     unsigned int fbit, wbits = 0, u32_off = 0;
    290 
    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;
    295     }
    296 
    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;
    302         }
    303         u32[u32_off] |= xlnx_efuse_get_bit(s->efuse, fbit) << wbits;
    304     }
    305 }
    306 
    307 /*
    308  * Keep the syncs in bit order so we can bail out for the
    309  * slower ones.
    310  */
    311 static void zynqmp_efuse_sync_cache(XlnxZynqMPEFuse *s, unsigned int bit)
    312 {
    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);
    326 
    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);
    330 
    331     /* Update the tbits.  */
    332     update_tbit_status(s);
    333 
    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);
    340 
    341     cache_sync_u32(s, R_DNA_0, EFUSE_DNA_START, EFUSE_DNA_END, bit);
    342 
    343     if (bit < EFUSE_AES_START) {
    344         return;
    345     }
    346 
    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);
    353 }
    354 
    355 static void zynqmp_efuse_update_irq(XlnxZynqMPEFuse *s)
    356 {
    357     bool pending = s->regs[R_EFUSE_ISR] & s->regs[R_EFUSE_IMR];
    358     qemu_set_irq(s->irq, pending);
    359 }
    360 
    361 static void zynqmp_efuse_isr_postw(RegisterInfo *reg, uint64_t val64)
    362 {
    363     XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(reg->opaque);
    364     zynqmp_efuse_update_irq(s);
    365 }
    366 
    367 static uint64_t zynqmp_efuse_ier_prew(RegisterInfo *reg, uint64_t val64)
    368 {
    369     XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(reg->opaque);
    370     uint32_t val = val64;
    371 
    372     s->regs[R_EFUSE_IMR] |= val;
    373     zynqmp_efuse_update_irq(s);
    374     return 0;
    375 }
    376 
    377 static uint64_t zynqmp_efuse_idr_prew(RegisterInfo *reg, uint64_t val64)
    378 {
    379     XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(reg->opaque);
    380     uint32_t val = val64;
    381 
    382     s->regs[R_EFUSE_IMR] &= ~val;
    383     zynqmp_efuse_update_irq(s);
    384     return 0;
    385 }
    386 
    387 static void zynqmp_efuse_pgm_addr_postw(RegisterInfo *reg, uint64_t val64)
    388 {
    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;
    394 
    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;
    406     }
    407 
    408     if (ARRAY_FIELD_EX32(s->regs, WR_LOCK, LOCK)) {
    409         errmsg = "Array write-locked";
    410         goto pgm_done;
    411     }
    412 
    413     if (!ARRAY_FIELD_EX32(s->regs, CFG, PGM_EN)) {
    414         errmsg = "Array pgm-disabled";
    415         goto pgm_done;
    416     }
    417 
    418     if (puf_prot) {
    419         errmsg = "PUF_HD-store write-locked";
    420         goto pgm_done;
    421     }
    422 
    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;
    427     }
    428 
    429     if (!xlnx_efuse_set_bit(s->efuse, bit)) {
    430         errmsg = "Write failed";
    431     }
    432 
    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));
    438 
    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);
    443     }
    444 
    445     ARRAY_FIELD_DP32(s->regs, EFUSE_ISR, PGM_DONE, 1);
    446     zynqmp_efuse_update_irq(s);
    447 }
    448 
    449 static void zynqmp_efuse_rd_addr_postw(RegisterInfo *reg, uint64_t val64)
    450 {
    451     XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(reg->opaque);
    452     g_autofree char *path = NULL;
    453 
    454     /*
    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).
    460      */
    461 #define COL_MASK(L_, H_) \
    462     ((uint32_t)MAKE_64BIT_MASK((L_), (1 + (H_) - (L_))))
    463 
    464     static const uint32_t ary0_col_mask[] = {
    465         /* XilSKey - XSK_ZYNQMP_EFUSEPS_TBITS_ROW */
    466         [0]  = COL_MASK(28, 31),
    467 
    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),
    473 
    474         /* XilSKey - XSK_ZYNQMP_EFUSEPS_MISC_USR_CTRL_ROW */
    475         [16] = COL_MASK(0, 7) | COL_MASK(10, 16),
    476 
    477         /* XilSKey - XSK_ZYNQMP_EFUSEPS_PBR_BOOT_ERR_ROW */
    478         [17] = COL_MASK(0, 2),
    479 
    480         /* XilSKey - XSK_ZYNQMP_EFUSEPS_PUF_CHASH_ROW */
    481         [20] = COL_MASK(0, 31),
    482 
    483         /* XilSKey - XSK_ZYNQMP_EFUSEPS_PUF_AUX_ROW */
    484         [21] = COL_MASK(0, 23) | COL_MASK(29, 31),
    485 
    486         /* XilSKey - XSK_ZYNQMP_EFUSEPS_SEC_CTRL_ROW */
    487         [22] = COL_MASK(0, 31),
    488 
    489         /* XilSKey - XSK_ZYNQMP_EFUSEPS_SPK_ID_ROW */
    490         [23] = COL_MASK(0, 31),
    491 
    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),
    499 
    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),
    507     };
    508 
    509     uint32_t col_mask = COL_MASK(0, 31);
    510 #undef COL_MASK
    511 
    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);
    515 
    516     switch (efuse_ary) {
    517     case 0:     /* Various */
    518         if (efuse_row >= ARRAY_SIZE(ary0_col_mask)) {
    519             goto denied;
    520         }
    521 
    522         col_mask = ary0_col_mask[efuse_row];
    523         if (!col_mask) {
    524             goto denied;
    525         }
    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;
    533     }
    534 
    535     s->regs[R_EFUSE_RD_DATA] = xlnx_efuse_get_row(s->efuse, val64) & col_mask;
    536 
    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;
    541 
    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);
    547 
    548     s->regs[R_EFUSE_RD_DATA] = 0;
    549 
    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);
    553 }
    554 
    555 static void zynqmp_efuse_aes_crc_postw(RegisterInfo *reg, uint64_t val64)
    556 {
    557     XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(reg->opaque);
    558     bool ok;
    559 
    560     ok = xlnx_efuse_k256_check(s->efuse, (uint32_t)val64, EFUSE_AES_START);
    561 
    562     ARRAY_FIELD_DP32(s->regs, STATUS, AES_CRC_PASS, (ok ? 1 : 0));
    563     ARRAY_FIELD_DP32(s->regs, STATUS, AES_CRC_DONE, 1);
    564 
    565     s->regs[R_EFUSE_AES_CRC] = 0;   /* crc value is write-only */
    566 }
    567 
    568 static uint64_t zynqmp_efuse_cache_load_prew(RegisterInfo *reg,
    569                                              uint64_t valu64)
    570 {
    571     XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(reg->opaque);
    572 
    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);
    577     }
    578 
    579     return 0;
    580 }
    581 
    582 static uint64_t zynqmp_efuse_wr_lock_prew(RegisterInfo *reg, uint64_t val)
    583 {
    584     return val == 0xDF0D ? 0 : 1;
    585 }
    586 
    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,
    718     }
    719 };
    720 
    721 static void zynqmp_efuse_reg_write(void *opaque, hwaddr addr,
    722                                    uint64_t data, unsigned size)
    723 {
    724     RegisterInfoArray *reg_array = opaque;
    725     XlnxZynqMPEFuse *s;
    726     Object *dev;
    727 
    728     assert(reg_array != NULL);
    729 
    730     dev = reg_array->mem.owner;
    731     assert(dev);
    732 
    733     s = XLNX_ZYNQMP_EFUSE(dev);
    734 
    735     if (addr != A_WR_LOCK && s->regs[R_WR_LOCK]) {
    736         g_autofree char *path = object_get_canonical_path(OBJECT(s));
    737 
    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);
    743     }
    744 }
    745 
    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,
    753     },
    754 };
    755 
    756 static void zynqmp_efuse_register_reset(RegisterInfo *reg)
    757 {
    758     if (!reg->data || !reg->access) {
    759         return;
    760     }
    761 
    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;
    767     }
    768 
    769     register_reset(reg);
    770 }
    771 
    772 static void zynqmp_efuse_reset(DeviceState *dev)
    773 {
    774     XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(dev);
    775     unsigned int i;
    776 
    777     for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
    778         zynqmp_efuse_register_reset(&s->regs_info[i]);
    779     }
    780 
    781     zynqmp_efuse_sync_cache(s, FBIT_UNKNOWN);
    782     ARRAY_FIELD_DP32(s->regs, STATUS, CACHE_DONE, 1);
    783     zynqmp_efuse_update_irq(s);
    784 }
    785 
    786 static void zynqmp_efuse_realize(DeviceState *dev, Error **errp)
    787 {
    788     XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(dev);
    789 
    790     if (!s->efuse) {
    791         g_autofree char *path = object_get_canonical_path(OBJECT(s));
    792 
    793         error_setg(errp, "%s.efuse: link property not connected to XLNX-EFUSE",
    794                    path);
    795         return;
    796     }
    797 
    798     s->efuse->dev = dev;
    799 }
    800 
    801 static void zynqmp_efuse_init(Object *obj)
    802 {
    803     XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(obj);
    804     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    805     RegisterInfoArray *reg_array;
    806 
    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);
    814 
    815     sysbus_init_mmio(sbd, &reg_array->mem);
    816     sysbus_init_irq(sbd, &s->irq);
    817 }
    818 
    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(),
    826     }
    827 };
    828 
    829 static Property zynqmp_efuse_props[] = {
    830     DEFINE_PROP_LINK("efuse",
    831                      XlnxZynqMPEFuse, efuse,
    832                      TYPE_XLNX_EFUSE, XlnxEFuse *),
    833 
    834     DEFINE_PROP_END_OF_LIST(),
    835 };
    836 
    837 static void zynqmp_efuse_class_init(ObjectClass *klass, void *data)
    838 {
    839     DeviceClass *dc = DEVICE_CLASS(klass);
    840 
    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);
    845 }
    846 
    847 
    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,
    854 };
    855 
    856 static void efuse_register_types(void)
    857 {
    858     type_register_static(&efuse_info);
    859 }
    860 
    861 type_init(efuse_register_types)