1 /*
2 * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdbool.h>
8 #include "esp_efuse_rtc_table.h"
9 #include "esp_efuse.h"
10 #include "esp_efuse_table.h"
11 #include "esp_log.h"
12 #include "soc/soc_caps.h"
13
14 #define RTC_TBL_LOG_TAG "efuse_rtc_table"
15
16
17
18 /* Note on definition of tags
19 *
20 * For adc calibration, value = raw * multiplier + offset, but these values are kind of arbitrary so
21 * we use a lookup table to do the bookkeeping.
22 *
23 * The offset of an item can be calculated as follows:
24 * PARAM_OFFSET + ADC_NUM(which is the UNIT_COUNT minus 1) * ATTEN_NUM + ATTEN_NUM
25 * where PARAM_OFFSET is the index of the first item.
26 *
27 * ADC, ATTEN form a 2-dim array. For each (version number, extra parameters) tuple we keep a such array,
28 * and use if-else statements to choose which array we use.
29 * */
30
31 #define RTCCALIB_V1_ADCREADINGLOW_OFFSET RTCCALIB_V1IDX_A10L
32 #define RTCCALIB_V1_ADCREADINGHIGH_OFFSET RTCCALIB_V1IDX_A10H
33 #define RTCCALIB_V2_ADCREADINGHIGH_OFFSET RTCCALIB_V2IDX_A10H
34 #define RTCCALIB_V2_ADCREADINGINIT_OFFSET RTCCALIB_V2IDX_A10I
35
36 typedef struct {
37 const int tag; // should be the same as the index in adc_efuse_raw_map
38 const int block;
39 const int begin_bit;
40 const int length;
41 const int multiplier;
42 const int base;
43 const int depends;
44 } efuse_map_info_t;
45
46 static const efuse_map_info_t adc_efuse_raw_map[] = {
47 {0},
48 // INDEXING TAG, BLOCK, BEGIN_BIT, LENGTH, MULTIPLIER, OFFSET BASE, OFFSET DEP
49 {RTCCALIB_V1IDX_A10L, 2, 208, 6, 4, 2231, 0},
50 {RTCCALIB_V1IDX_A11L, 2, 214, 6, 4, 1643, 0},
51 {RTCCALIB_V1IDX_A12L, 2, 220, 6, 4, 1290, 0},
52 {RTCCALIB_V1IDX_A13L, 2, 226, 6, 4, 701, 0},
53 {RTCCALIB_V1IDX_A20L, 2, 232, 6, 4, 2305, 0},
54 {RTCCALIB_V1IDX_A21L, 2, 238, 6, 4, 1693, 0},
55 {RTCCALIB_V1IDX_A22L, 2, 244, 6, 4, 1343, 0},
56 {RTCCALIB_V1IDX_A23L, 2, 250, 6, 4, 723, 0},
57
58 {RTCCALIB_V1IDX_A10H, 2, 144, 8, 4, 5775, 0},
59 {RTCCALIB_V1IDX_A11H, 2, 152, 8, 4, 5693, 0},
60 {RTCCALIB_V1IDX_A12H, 2, 160, 8, 4, 5723, 0},
61 {RTCCALIB_V1IDX_A13H, 2, 168, 8, 4, 6209, 0},
62 {RTCCALIB_V1IDX_A20H, 2, 176, 8, 4, 5817, 0},
63 {RTCCALIB_V1IDX_A21H, 2, 184, 8, 4, 5703, 0},
64 {RTCCALIB_V1IDX_A22H, 2, 192, 8, 4, 5731, 0},
65 {RTCCALIB_V1IDX_A23H, 2, 200, 8, 4, 6157, 0},
66
67 {RTCCALIB_V2IDX_A10H, 2, 197, 6, 2, 169, RTCCALIB_V2IDX_A12H},
68 {RTCCALIB_V2IDX_A11H, 2, 203, 6, 2, -26, RTCCALIB_V2IDX_A12H},
69 {RTCCALIB_V2IDX_A12H, 2, 209, 9, 2, 126, RTCCALIB_V2IDX_A21H},
70 {RTCCALIB_V2IDX_A13H, 2, 218, 7, 2, 387, RTCCALIB_V2IDX_A12H},
71 {RTCCALIB_V2IDX_A20H, 2, 225, 7, 2, 177, RTCCALIB_V2IDX_A21H},
72 {RTCCALIB_V2IDX_A21H, 2, 232, 10, 2, 5815, 0},
73 {RTCCALIB_V2IDX_A22H, 2, 242, 7, 2, 27, RTCCALIB_V2IDX_A21H},
74 {RTCCALIB_V2IDX_A23H, 2, 249, 7, 2, 410, RTCCALIB_V2IDX_A21H},
75
76 {RTCCALIB_V2IDX_A10I, 2, 147, 8, 2, 1519, 0},
77 {RTCCALIB_V2IDX_A11I, 2, 155, 6, 2, 88, RTCCALIB_V2IDX_A10I},
78 {RTCCALIB_V2IDX_A12I, 2, 161, 5, 2, 8, RTCCALIB_V2IDX_A11I},
79 {RTCCALIB_V2IDX_A13I, 2, 166, 6, 2, 70, RTCCALIB_V2IDX_A12I},
80 {RTCCALIB_V2IDX_A20I, 2, 172, 8, 2, 1677, 0},
81 {RTCCALIB_V2IDX_A21I, 2, 180, 6, 2, 23, RTCCALIB_V2IDX_A20I},
82 {RTCCALIB_V2IDX_A22I, 2, 186, 5, 2, 6, RTCCALIB_V2IDX_A21I},
83 {RTCCALIB_V2IDX_A23I, 2, 191, 6, 2, 13, RTCCALIB_V2IDX_A22I},
84
85 {RTCCALIB_IDX_TMPSENSOR, 2, 135, 9, 1, 0, 0},
86
87 };
88
89
esp_efuse_rtc_table_read_calib_version(void)90 int esp_efuse_rtc_table_read_calib_version(void)
91 {
92 uint32_t result = 0;
93 esp_efuse_read_field_blob(ESP_EFUSE_BLOCK2_VERSION, &result, 32);
94 return result;
95 }
96
esp_efuse_rtc_table_get_tag(int version,int adc_num,int atten,int extra_params)97 int esp_efuse_rtc_table_get_tag(int version, int adc_num, int atten, int extra_params)
98 {
99 int param_offset; // used to index which (adc_num, atten) array to use.
100 if (version == 1 && extra_params == RTCCALIB_V1_PARAM_VLOW) { // Volage LOW, Version 1
101 param_offset = RTCCALIB_V1_ADCREADINGLOW_OFFSET;
102 } else if (version == 1 && extra_params == RTCCALIB_V1_PARAM_VHIGH) {
103 param_offset = RTCCALIB_V1_ADCREADINGHIGH_OFFSET;
104 } else if (version == 2 && extra_params == RTCCALIB_V2_PARAM_VHIGH) {
105 param_offset = RTCCALIB_V2_ADCREADINGHIGH_OFFSET;
106 } else if (version == 2 && extra_params == RTCCALIB_V2_PARAM_VINIT) {
107 param_offset = RTCCALIB_V2_ADCREADINGINIT_OFFSET;
108 } else {
109 return -1;
110 }
111
112 int result = param_offset + (adc_num - 1) * RTCCALIB_ESP32S2_ATTENCOUNT + atten;
113 ESP_EARLY_LOGV(RTC_TBL_LOG_TAG, "V%d ADC%d ATTEN%d PARAM%d -> %d", version, adc_num, atten, extra_params, result);
114 return result;
115 }
116
117 /*
118 * Converts a signed-bit int to a normal (2-complement) int.
119 * */
signed_bit_to_int(uint32_t number,int len)120 static int signed_bit_to_int(uint32_t number, int len)
121 {
122 if (number >> (len - 1)) {
123 // first bit is set, unset that bit and negate the number.
124 number = -(number ^ (1 << (len - 1)));
125 }
126 return number;
127 }
128
esp_efuse_rtc_table_get_raw_efuse_value(int tag)129 int esp_efuse_rtc_table_get_raw_efuse_value(int tag)
130 {
131 assert(tag > 0);
132 if (tag == 0) {
133 return 0;
134 }
135 uint32_t val = 0;
136 esp_efuse_read_block(adc_efuse_raw_map[tag].block, &val, adc_efuse_raw_map[tag].begin_bit, adc_efuse_raw_map[tag].length);
137 int result = signed_bit_to_int(val, adc_efuse_raw_map[tag].length);
138 ESP_EARLY_LOGV(RTC_TBL_LOG_TAG, "Fetching raw for tag %d @blk%d bit%d len%d: %d", tag, adc_efuse_raw_map[tag].block, adc_efuse_raw_map[tag].begin_bit, adc_efuse_raw_map[tag].length,
139 result);
140 return result;
141 }
142
esp_efuse_rtc_table_get_parsed_efuse_value(int tag,bool skip_efuse_reading)143 int esp_efuse_rtc_table_get_parsed_efuse_value(int tag, bool skip_efuse_reading)
144 {
145 assert(tag >= 0);
146 if (tag == 0) {
147 return 0; // tag 0 is the dummy tag and has no value. (used by depends)
148 }
149
150 int efuse_val = 0;
151 if (!skip_efuse_reading) {
152 efuse_val = esp_efuse_rtc_table_get_raw_efuse_value(tag) * adc_efuse_raw_map[tag].multiplier;
153 }
154 int result = efuse_val + adc_efuse_raw_map[tag].base +
155 esp_efuse_rtc_table_get_parsed_efuse_value(adc_efuse_raw_map[tag].depends, skip_efuse_reading);
156
157 ESP_EARLY_LOGV(RTC_TBL_LOG_TAG, "Parsed efuse val for tag %d: %d", tag, result);
158 return result;
159 }
160