1 /*
2 * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdint.h>
8 #include "soc/soc.h"
9 #include "soc/rtc.h"
10 #include "soc/regi2c_dig_reg.h"
11 #include "soc/regi2c_lp_bias.h"
12 #include "hal/efuse_hal.h"
13 #include "hal/efuse_ll.h"
14 #include "regi2c_ctrl.h"
15 #include "esp_hw_log.h"
16
17
18 static const char *TAG = "ocode_init";
19
set_ocode_by_efuse(int ocode_scheme_ver)20 static void set_ocode_by_efuse(int ocode_scheme_ver)
21 {
22 assert(ocode_scheme_ver == 1);
23 unsigned int ocode = efuse_ll_get_ocode();
24
25 //set ext_ocode
26 REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_EXT_CODE, ocode);
27 REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_CODE, 1);
28 }
29
calibrate_ocode(void)30 static void calibrate_ocode(void)
31 {
32 /*
33 Bandgap output voltage is not precise when calibrate o-code by hardware sometimes, so need software o-code calibration (must turn off PLL).
34 Method:
35 1. read current cpu config, save in old_config;
36 2. switch cpu to xtal because PLL will be closed when o-code calibration;
37 3. begin o-code calibration;
38 4. wait o-code calibration done flag(odone_flag & bg_odone_flag) or timeout;
39 5. set cpu to old-config.
40 */
41 soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
42 rtc_cal_sel_t cal_clk = RTC_CAL_RTC_MUX;
43 if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
44 cal_clk = RTC_CAL_32K_OSC_SLOW;
45 } else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
46 cal_clk = RTC_CAL_32K_XTAL;
47 }
48
49 uint64_t max_delay_time_us = 10000;
50 uint32_t slow_clk_period = rtc_clk_cal(cal_clk, 100);
51 uint64_t max_delay_cycle = rtc_time_us_to_slowclk(max_delay_time_us, slow_clk_period);
52 uint64_t cycle0 = rtc_time_get();
53 uint64_t timeout_cycle = cycle0 + max_delay_cycle;
54 uint64_t cycle1 = 0;
55
56 rtc_cpu_freq_config_t old_config;
57 rtc_clk_cpu_freq_get_config(&old_config);
58 rtc_clk_cpu_freq_set_xtal();
59
60 REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_RESETB, 0);
61 REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_RESETB, 1);
62 bool odone_flag = 0;
63 bool bg_odone_flag = 0;
64 while (1) {
65 odone_flag = REGI2C_READ_MASK(I2C_ULP, I2C_ULP_O_DONE_FLAG);
66 bg_odone_flag = REGI2C_READ_MASK(I2C_ULP, I2C_ULP_BG_O_DONE_FLAG);
67 cycle1 = rtc_time_get();
68 if (odone_flag && bg_odone_flag) {
69 break;
70 }
71 if (cycle1 >= timeout_cycle) {
72 ESP_HW_LOGW(TAG, "o_code calibration fail\n");
73 break;
74 }
75 }
76 rtc_clk_cpu_freq_set_config(&old_config);
77 }
78
esp_ocode_calib_init(void)79 void esp_ocode_calib_init(void)
80 {
81 if (efuse_hal_blk_version() >= 1) {
82 set_ocode_by_efuse(1);
83 } else {
84 calibrate_ocode();
85 }
86 }
87