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