1# This file describes eFuses fields and registers for ESP32 chip
2#
3# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
4#
5# SPDX-License-Identifier: GPL-2.0-or-later
6
7import os
8
9import yaml
10
11from ..mem_definition_base import (
12    EfuseBlocksBase,
13    EfuseFieldsBase,
14    EfuseRegistersBase,
15    Field,
16)
17
18
19class EfuseDefineRegisters(EfuseRegistersBase):
20    EFUSE_MEM_SIZE = 0x01FC + 4
21
22    # EFUSE registers & command/conf values
23    DR_REG_EFUSE_BASE = 0x3F41A000
24    EFUSE_PGM_DATA0_REG = DR_REG_EFUSE_BASE
25    EFUSE_CHECK_VALUE0_REG = DR_REG_EFUSE_BASE + 0x020
26    EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x1C8
27    EFUSE_CONF_REG = DR_REG_EFUSE_BASE + 0x1CC
28    EFUSE_STATUS_REG = DR_REG_EFUSE_BASE + 0x1D0
29    EFUSE_CMD_REG = DR_REG_EFUSE_BASE + 0x1D4
30    EFUSE_RD_RS_ERR0_REG = DR_REG_EFUSE_BASE + 0x194
31    EFUSE_RD_RS_ERR1_REG = DR_REG_EFUSE_BASE + 0x198
32    EFUSE_RD_REPEAT_ERR0_REG = DR_REG_EFUSE_BASE + 0x17C
33    EFUSE_RD_REPEAT_ERR1_REG = DR_REG_EFUSE_BASE + 0x180
34    EFUSE_RD_REPEAT_ERR2_REG = DR_REG_EFUSE_BASE + 0x184
35    EFUSE_RD_REPEAT_ERR3_REG = DR_REG_EFUSE_BASE + 0x188
36    EFUSE_RD_REPEAT_ERR4_REG = DR_REG_EFUSE_BASE + 0x18C
37    EFUSE_DAC_CONF_REG = DR_REG_EFUSE_BASE + 0x1E8
38    EFUSE_RD_TIM_CONF_REG = DR_REG_EFUSE_BASE + 0x1EC
39    EFUSE_WR_TIM_CONF1_REG = DR_REG_EFUSE_BASE + 0x1F4
40    EFUSE_WR_TIM_CONF2_REG = DR_REG_EFUSE_BASE + 0x1F8
41    EFUSE_DATE_REG = DR_REG_EFUSE_BASE + 0x1FC
42    EFUSE_WRITE_OP_CODE = 0x5A5A
43    EFUSE_READ_OP_CODE = 0x5AA5
44    EFUSE_PGM_CMD_MASK = 0x3
45    EFUSE_PGM_CMD = 0x2
46    EFUSE_READ_CMD = 0x1
47
48    BLOCK_ERRORS = [
49        # error_reg,               err_num_mask, err_num_offs,     fail_bit
50        (EFUSE_RD_REPEAT_ERR0_REG, None, None, None),  # BLOCK0
51        (EFUSE_RD_RS_ERR0_REG, 0x7, 0, 3),  # MAC_SPI_8M_0
52        (EFUSE_RD_RS_ERR0_REG, 0x7, 4, 7),  # BLOCK_SYS_DATA
53        (EFUSE_RD_RS_ERR0_REG, 0x7, 8, 11),  # BLOCK_USR_DATA
54        (EFUSE_RD_RS_ERR0_REG, 0x7, 12, 15),  # BLOCK_KEY0
55        (EFUSE_RD_RS_ERR0_REG, 0x7, 16, 19),  # BLOCK_KEY1
56        (EFUSE_RD_RS_ERR0_REG, 0x7, 20, 23),  # BLOCK_KEY2
57        (EFUSE_RD_RS_ERR0_REG, 0x7, 24, 27),  # BLOCK_KEY3
58        (EFUSE_RD_RS_ERR0_REG, 0x7, 28, 31),  # BLOCK_KEY4
59        (EFUSE_RD_RS_ERR1_REG, 0x7, 0, 3),  # BLOCK_KEY5
60        (EFUSE_RD_RS_ERR1_REG, 0x7, 4, 7),  # BLOCK_SYS_DATA2
61    ]
62
63    EFUSE_DAC_CONF_REG = DR_REG_EFUSE_BASE + 0x1E8
64    EFUSE_DAC_CLK_DIV_S = 0
65    EFUSE_DAC_CLK_DIV_M = 0xFF << EFUSE_DAC_CLK_DIV_S
66
67    EFUSE_RD_TIM_CONF_REG = DR_REG_EFUSE_BASE + 0x1EC
68    EFUSE_TSUR_A_S = 16
69    EFUSE_TSUR_A_M = 0xFF << EFUSE_TSUR_A_S
70    EFUSE_TRD_S = 8
71    EFUSE_TRD_M = 0xFF << EFUSE_TRD_S
72    EFUSE_THR_A_S = 0
73    EFUSE_THR_A_M = 0xFF << EFUSE_THR_A_S
74
75    EFUSE_WR_TIM_CONF0_REG = DR_REG_EFUSE_BASE + 0x1F0
76    EFUSE_TPGM_S = 16
77    EFUSE_TPGM_M = 0xFFFF << EFUSE_TPGM_S
78    EFUSE_TPGM_INACTIVE_S = 8
79    EFUSE_TPGM_INACTIVE_M = 0xFF << EFUSE_TPGM_INACTIVE_S
80    EFUSE_THP_A_S = 0
81    EFUSE_THP_A_M = 0xFF << EFUSE_THP_A_S
82
83    # EFUSE_WR_TIM_CONF1_REG
84    EFUSE_PWR_ON_NUM_S = 8
85    EFUSE_PWR_ON_NUM_M = 0xFFFF << EFUSE_PWR_ON_NUM_S
86    EFUSE_TSUP_A_S = 0
87    EFUSE_TSUP_A_M = 0xFF << EFUSE_TSUP_A_S
88
89    # EFUSE_WR_TIM_CONF2_REG
90    EFUSE_PWR_OFF_NUM_S = 0
91    EFUSE_PWR_OFF_NUM_M = 0xFFFF << EFUSE_PWR_OFF_NUM_S
92
93    # Configure clock
94    EFUSE_PROGRAMMING_TIMING_PARAMETERS = {
95        # APB Frequency: ( EFUSE_TSUP_A, EFUSE_TPGM, EFUSE_THP_A, EFUSE_TPGM_INACTIVE )
96        # Taken from TRM chapter "eFuse Controller": eFuse-Programming Timing
97        80: (0x2, 0x320, 0x2, 0x4),
98        40: (0x1, 0x190, 0x1, 0x2),
99        20: (0x1, 0xC8, 0x1, 0x1),
100    }
101
102    VDDQ_TIMING_PARAMETERS = {
103        # APB Frequency: ( EFUSE_DAC_CLK_DIV, EFUSE_PWR_ON_NUM, EFUSE_PWR_OFF_NUM )
104        # Taken from TRM chapter "eFuse Controller": eFuse VDDQ Timing Setting
105        80: (0xA0, 0xA200, 0x100),
106        40: (0x50, 0x5100, 0x80),
107        20: (0x28, 0x2880, 0x40),
108    }
109
110    EFUSE_READING_PARAMETERS = {
111        # APB Frequency: ( EFUSE_TSUR_A, EFUSE_TRD, EFUSE_THR_A )
112        # Taken from TRM chapter "eFuse Controller": eFuse-Read Timing
113        80: (0x2, 0x4, 0x2),
114        40: (0x1, 0x2, 0x1),
115        20: (0x1, 0x1, 0x1),
116    }
117
118
119class EfuseDefineBlocks(EfuseBlocksBase):
120    __base_rd_regs = EfuseDefineRegisters.DR_REG_EFUSE_BASE
121    __base_wr_regs = EfuseDefineRegisters.EFUSE_PGM_DATA0_REG
122    # List of efuse blocks
123    # fmt: off
124    BLOCKS = [
125        # Name,             Alias,   Index,  Read address,                           Write address,   Write protect bit, Read protect bit, Len, key_purpose
126        ("BLOCK0",          [],          0,  __base_rd_regs + 0x02C, __base_wr_regs, None, None, 6, None),
127        ("MAC_SPI_8M_0",    ["BLOCK1"],  1,  __base_rd_regs + 0x044, __base_wr_regs, 20,   None, 6, None),
128        ("BLOCK_SYS_DATA",  ["BLOCK2"],  2,  __base_rd_regs + 0x05C, __base_wr_regs, 21,   None, 8, None),
129        ("BLOCK_USR_DATA",  ["BLOCK3"],  3,  __base_rd_regs + 0x07C, __base_wr_regs, 22,   None, 8, None),
130        ("BLOCK_KEY0",      ["BLOCK4"],  4,  __base_rd_regs + 0x09C, __base_wr_regs, 23,   0,    8, "KEY_PURPOSE_0"),
131        ("BLOCK_KEY1",      ["BLOCK5"],  5,  __base_rd_regs + 0x0BC, __base_wr_regs, 24,   1,    8, "KEY_PURPOSE_1"),
132        ("BLOCK_KEY2",      ["BLOCK6"],  6,  __base_rd_regs + 0x0DC, __base_wr_regs, 25,   2,    8, "KEY_PURPOSE_2"),
133        ("BLOCK_KEY3",      ["BLOCK7"],  7,  __base_rd_regs + 0x0FC, __base_wr_regs, 26,   3,    8, "KEY_PURPOSE_3"),
134        ("BLOCK_KEY4",      ["BLOCK8"],  8,  __base_rd_regs + 0x11C, __base_wr_regs, 27,   4,    8, "KEY_PURPOSE_4"),
135        ("BLOCK_KEY5",      ["BLOCK9"],  9,  __base_rd_regs + 0x13C, __base_wr_regs, 28,   5,    8, "KEY_PURPOSE_5"),
136        ("BLOCK_SYS_DATA2", ["BLOCK10"], 10, __base_rd_regs + 0x15C, __base_wr_regs, 29,   6,    8, None),
137    ]
138    # fmt: on
139
140    def get_burn_block_data_names(self):
141        list_of_names = []
142        for block in self.BLOCKS:
143            blk = self.get(block)
144            if blk.name:
145                list_of_names.append(blk.name)
146            if blk.alias:
147                for alias in blk.alias:
148                    list_of_names.append(alias)
149        return list_of_names
150
151
152class EfuseDefineFields(EfuseFieldsBase):
153    def __init__(self, extend_efuse_table) -> None:
154        # List of efuse fields from TRM the chapter eFuse Controller.
155        self.EFUSES = []
156
157        self.KEYBLOCKS = []
158
159        # if BLK_VERSION_MINOR is 1, these efuse fields are in BLOCK2
160        self.BLOCK2_CALIBRATION_EFUSES = []
161
162        self.CALC = []
163
164        dir_name = os.path.dirname(os.path.abspath(__file__))
165        dir_name, file_name = os.path.split(dir_name)
166        file_name = file_name + ".yaml"
167        dir_name, _ = os.path.split(dir_name)
168        efuse_file = os.path.join(dir_name, "efuse_defs", file_name)
169        with open(f"{efuse_file}", "r") as r_file:
170            e_desc = yaml.safe_load(r_file)
171        super().__init__(e_desc, extend_efuse_table)
172
173        for i, efuse in enumerate(self.ALL_EFUSES):
174            if efuse.name in [
175                "BLOCK_USR_DATA",
176                "BLOCK_KEY0",
177                "BLOCK_KEY1",
178                "BLOCK_KEY2",
179                "BLOCK_KEY3",
180                "BLOCK_KEY4",
181                "BLOCK_KEY5",
182                "BLOCK_SYS_DATA2",
183            ]:
184                if efuse.name == "BLOCK_USR_DATA":
185                    efuse.bit_len = 256
186                    efuse.type = "bytes:32"
187                self.KEYBLOCKS.append(efuse)
188                self.ALL_EFUSES[i] = None
189
190            elif efuse.category == "calibration":
191                self.BLOCK2_CALIBRATION_EFUSES.append(efuse)
192                self.ALL_EFUSES[i] = None
193
194        f = Field()
195        f.name = "WAFER_VERSION_MINOR"
196        f.block = 0
197        f.bit_len = 4
198        f.type = f"uint:{f.bit_len}"
199        f.category = "identity"
200        f.class_type = "wafer"
201        f.description = "calc WAFER VERSION MINOR = WAFER_VERSION_MINOR_HI << 3 + WAFER_VERSION_MINOR_LO (read only)"
202        self.CALC.append(f)
203
204        for efuse in self.ALL_EFUSES:
205            if efuse is not None:
206                self.EFUSES.append(efuse)
207
208        self.ALL_EFUSES = []
209