1 /*
2  * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "sdkconfig.h"
8 #include <sys/param.h>
9 #include "soc/soc_caps.h"
10 #include "hal/efuse_ll.h"
11 #include "hal/assert.h"
12 #include "hal/efuse_hal.h"
13 #include "soc/syscon_reg.h"
14 #include "esp_attr.h"
15 
efuse_hal_get_major_chip_version(void)16 IRAM_ATTR uint32_t efuse_hal_get_major_chip_version(void)
17 {
18     uint8_t eco_bit0 = efuse_ll_get_chip_ver_rev1();
19     uint8_t eco_bit1 = efuse_ll_get_chip_ver_rev2();
20     uint8_t eco_bit2 = (REG_READ(SYSCON_DATE_REG) & 0x80000000) >> 31;
21     uint32_t combine_value = (eco_bit2 << 2) | (eco_bit1 << 1) | eco_bit0;
22     uint32_t chip_ver = 0;
23     switch (combine_value) {
24     case 0:
25         chip_ver = 0;
26         break;
27     case 1:
28         chip_ver = 1;
29         break;
30     case 3:
31         chip_ver = 2;
32         break;
33 #if CONFIG_IDF_ENV_FPGA
34     case 4: /* Empty efuses, but SYSCON_DATE_REG bit is set */
35         chip_ver = 3;
36         break;
37 #endif // CONFIG_IDF_ENV_FPGA
38     case 7:
39         chip_ver = 3;
40         break;
41     default:
42         chip_ver = 0;
43         break;
44     }
45     return chip_ver;
46 }
47 
efuse_hal_get_minor_chip_version(void)48 IRAM_ATTR uint32_t efuse_hal_get_minor_chip_version(void)
49 {
50     return efuse_ll_get_chip_wafer_version_minor();
51 }
52 
efuse_hal_get_rated_freq_mhz(void)53 uint32_t efuse_hal_get_rated_freq_mhz(void)
54 {
55     //Check if ESP32 is rated for a CPU frequency of 160MHz only
56     if (efuse_ll_get_chip_cpu_freq_rated() && efuse_ll_get_chip_cpu_freq_low()) {
57         return 160;
58     }
59     return 240;
60 }
61 
62 /******************* eFuse control functions *************************/
63 
efuse_hal_set_timing(uint32_t apb_freq_mhz)64 void efuse_hal_set_timing(uint32_t apb_freq_mhz)
65 {
66     uint32_t clk_sel0;
67     uint32_t clk_sel1;
68     uint32_t dac_clk_div;
69     if (apb_freq_mhz <= 26) {
70         clk_sel0 = 250;
71         clk_sel1 = 255;
72         dac_clk_div = 52;
73     } else if (apb_freq_mhz <= 40) {
74         clk_sel0 = 160;
75         clk_sel1 = 255;
76         dac_clk_div = 80;
77     } else {
78         clk_sel0 = 80;
79         clk_sel1 = 128;
80         dac_clk_div = 100;
81     }
82     efuse_ll_set_dac_clk_div(dac_clk_div);
83     efuse_ll_set_dac_clk_sel0(clk_sel0);
84     efuse_ll_set_dac_clk_sel1(clk_sel1);
85 }
86 
efuse_hal_read(void)87 void efuse_hal_read(void)
88 {
89     efuse_ll_set_conf_read_op_code();
90     efuse_ll_set_read_cmd();
91     while (efuse_ll_get_cmd() != 0) { };
92 }
93 
efuse_hal_clear_program_registers(void)94 void efuse_hal_clear_program_registers(void)
95 {
96     for (uint32_t r = EFUSE_BLK0_WDATA0_REG; r <= EFUSE_BLK0_WDATA6_REG; r += 4) {
97         REG_WRITE(r, 0);
98     }
99     for (uint32_t r = EFUSE_BLK1_WDATA0_REG; r <= EFUSE_BLK1_WDATA7_REG; r += 4) {
100         REG_WRITE(r, 0);
101     }
102     for (uint32_t r = EFUSE_BLK2_WDATA0_REG; r <= EFUSE_BLK2_WDATA7_REG; r += 4) {
103         REG_WRITE(r, 0);
104     }
105     for (uint32_t r = EFUSE_BLK3_WDATA0_REG; r <= EFUSE_BLK3_WDATA7_REG; r += 4) {
106         REG_WRITE(r, 0);
107     }
108 }
109 
efuse_hal_program(uint32_t block)110 void efuse_hal_program(uint32_t block)
111 {
112     (void) block;
113     // Permanently update values written to the efuse write registers
114     efuse_ll_set_conf_write_op_code();
115     efuse_ll_set_pgm_cmd();
116     while (efuse_ll_get_cmd() != 0) { };
117 
118     efuse_hal_read();
119 }
120 
121 /******************* eFuse control functions *************************/
122 
efuse_hal_is_coding_error_in_block(unsigned block)123 bool efuse_hal_is_coding_error_in_block(unsigned block)
124 {
125     return block > 0 &&
126            efuse_ll_get_coding_scheme() == 1 && // 3/4 coding scheme
127            efuse_ll_get_dec_warnings(block);
128 }
129