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 copy
8import os
9
10import yaml
11
12from ..mem_definition_base import (
13    EfuseBlocksBase,
14    EfuseFieldsBase,
15    EfuseRegistersBase,
16    Field,
17)
18
19
20class EfuseDefineRegisters(EfuseRegistersBase):
21    EFUSE_MEM_SIZE = 0x011C + 4
22
23    # EFUSE registers & command/conf values
24    DR_REG_EFUSE_BASE = 0x3FF5A000
25    EFUSE_REG_CONF = DR_REG_EFUSE_BASE + 0x0FC
26    EFUSE_CONF_WRITE = 0x5A5A
27    EFUSE_CONF_READ = 0x5AA5
28    EFUSE_REG_CMD = DR_REG_EFUSE_BASE + 0x104
29    EFUSE_CMD_OP_MASK = 0x3
30    EFUSE_CMD_WRITE = 0x2
31    EFUSE_CMD_READ = 0x1
32
33    # 3/4 Coding scheme warnings registers
34    EFUSE_REG_DEC_STATUS = DR_REG_EFUSE_BASE + 0x11C
35    EFUSE_REG_DEC_STATUS_MASK = 0xFFF
36
37    # Coding Scheme
38    EFUSE_CODING_SCHEME_WORD = 6
39    EFUSE_CODING_SCHEME_MASK = 0x3
40
41    # Efuse clock control
42    EFUSE_DAC_CONF_REG = DR_REG_EFUSE_BASE + 0x118
43    EFUSE_CLK_REG = DR_REG_EFUSE_BASE + 0x0F8
44    EFUSE_DAC_CLK_DIV_MASK = 0xFF
45    EFUSE_CLK_SEL0_MASK = 0x00FF
46    EFUSE_CLK_SEL1_MASK = 0xFF00
47
48    EFUSE_CLK_SETTINGS = {
49        # APB freq: clk_sel0, clk_sel1, dac_clk_div
50        # Taken from TRM chapter "eFuse Controller": Timing Configuration
51        # 80 is here for completeness only as esptool never sets an 80MHz APB clock
52        26: (250, 255, 52),
53        40: (160, 255, 80),
54        80: (80, 128, 100),
55    }
56
57    DR_REG_SYSCON_BASE = 0x3FF66000
58    APB_CTL_DATE_ADDR = DR_REG_SYSCON_BASE + 0x7C
59    APB_CTL_DATE_V = 0x1
60    APB_CTL_DATE_S = 31
61
62    EFUSE_BLK0_RDATA3_REG = DR_REG_EFUSE_BASE + 0x00C
63    EFUSE_RD_CHIP_VER_REV1 = 1 << 15
64
65    EFUSE_BLK0_RDATA5_REG = DR_REG_EFUSE_BASE + 0x014
66    EFUSE_RD_CHIP_VER_REV2 = 1 << 20
67
68
69class EfuseDefineBlocks(EfuseBlocksBase):
70    __base_regs = EfuseDefineRegisters.DR_REG_EFUSE_BASE
71    # List of efuse blocks
72    # fmt: off
73    BLOCKS = [
74        # Name, Alias, Index, Read address, Write address, Write protect bit, Read protect bit, Len, key_purpose
75        ("BLOCK0",    [],                                     0, __base_regs + 0x000, __base_regs + 0x01C, None, None, 7, None),
76        ("BLOCK1",    ["flash_encryption"],                   1, __base_regs + 0x038, __base_regs + 0x098, 7,    0,    8, None),
77        ("BLOCK2",    ["secure_boot_v1", "secure_boot_v2"],   2, __base_regs + 0x058, __base_regs + 0x0B8, 8,    1,    8, None),
78        ("BLOCK3",    [],                                     3, __base_regs + 0x078, __base_regs + 0x0D8, 9,    2,    8, None),
79    ]
80    # fmt: on
81
82    def get_burn_block_data_names(self):
83        list_of_names = []
84        for block in self.BLOCKS:
85            blk = self.get(block)
86            if blk.name:
87                list_of_names.append(blk.name)
88        return list_of_names
89
90
91class EfuseDefineFields(EfuseFieldsBase):
92    def __init__(self, extend_efuse_table) -> None:
93        self.EFUSES = []
94        # if MAC_VERSION is set "1", these efuse fields are in BLOCK3:
95        self.CUSTOM_MAC = []
96        # The len of fields depends on coding scheme: for CODING_SCHEME_NONE
97        self.KEYBLOCKS_256 = []
98        # The len of fields depends on coding scheme: for CODING_SCHEME_34
99        self.KEYBLOCKS_192 = []
100        # if BLK3_PART_RESERVE is set, these efuse fields are in BLOCK3:
101        self.ADC_CALIBRATION = []
102
103        self.CALC = []
104
105        dir_name = os.path.dirname(os.path.abspath(__file__))
106        dir_name, file_name = os.path.split(dir_name)
107        file_name = file_name + ".yaml"
108        dir_name, _ = os.path.split(dir_name)
109        efuse_file = os.path.join(dir_name, "efuse_defs", file_name)
110        with open(f"{efuse_file}", "r") as r_file:
111            e_desc = yaml.safe_load(r_file)
112        super().__init__(e_desc, extend_efuse_table)
113
114        for i, efuse in enumerate(self.ALL_EFUSES):
115            if efuse.name == "BLOCK1" or efuse.name == "BLOCK2":
116                self.KEYBLOCKS_256.append(efuse)
117                BLOCK = copy.deepcopy(efuse)
118                BLOCK.type = "bytes:24"
119                BLOCK.bit_len = 24 * 8
120                self.KEYBLOCKS_192.append(BLOCK)
121                self.ALL_EFUSES[i] = None
122
123            elif efuse.name == "MAC_VERSION":
124                # A field from BLOCK3, It is used as a template
125                BLOCK3 = copy.deepcopy(efuse)
126                BLOCK3.name = "BLOCK3"
127                BLOCK3.block = 3
128                BLOCK3.word = 0
129                BLOCK3.pos = 0
130                BLOCK3.bit_len = 32 * 8
131                BLOCK3.type = "bytes:32"
132                BLOCK3.category = "security"
133                BLOCK3.class_type = "keyblock"
134                BLOCK3.description = "Variable Block 3"
135                self.KEYBLOCKS_256.append(BLOCK3)
136
137                BLOCK3 = copy.deepcopy(BLOCK3)
138                BLOCK3.type = "bytes:24"
139                BLOCK3.bit_len = 24 * 8
140                self.KEYBLOCKS_192.append(BLOCK3)
141
142            elif efuse.category == "calibration" and efuse.block == 3:
143                self.ADC_CALIBRATION.append(efuse)
144                self.ALL_EFUSES[i] = None
145
146            elif efuse.name in ["CUSTOM_MAC_CRC", "CUSTOM_MAC"]:
147                self.CUSTOM_MAC.append(efuse)
148                self.ALL_EFUSES[i] = None
149
150            elif efuse.category == "spi pad":
151                efuse.class_type = "spipin"
152
153        f = Field()
154        f.name = "WAFER_VERSION_MAJOR"
155        f.block = 0
156        f.bit_len = 3
157        f.type = f"uint:{f.bit_len}"
158        f.category = "identity"
159        f.class_type = "wafer"
160        f.description = "calc WAFER VERSION MAJOR from CHIP_VER_REV1 and CHIP_VER_REV2 and apb_ctl_date (read only)"
161        self.CALC.append(f)
162
163        f = Field()
164        f.name = "PKG_VERSION"
165        f.block = 0
166        f.bit_len = 4
167        f.type = f"uint:{f.bit_len}"
168        f.category = "identity"
169        f.class_type = "pkg"
170        f.description = (
171            "calc Chip package = CHIP_PACKAGE_4BIT << 3 + CHIP_PACKAGE (read only)"
172        )
173        self.CALC.append(f)
174
175        for efuse in self.ALL_EFUSES:
176            if efuse is not None:
177                self.EFUSES.append(efuse)
178
179        self.ALL_EFUSES = []
180