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 "esp_efuse_utility.h"
16
17 #include "soc/efuse_periph.h"
18 #include "esp_log.h"
19 #include "assert.h"
20 #include "sdkconfig.h"
21 #include <sys/param.h>
22
23 static const char *TAG = "efuse";
24
25 // Array for emulate efuse registers.
26 #ifdef CONFIG_EFUSE_VIRTUAL
27 uint32_t virt_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK];
28
29 /* Call the update function to seed virtual efuses during initialization */
30 __attribute__((constructor)) void esp_efuse_utility_update_virt_blocks(void);
31 #endif
32
33 extern const esp_efuse_range_addr_t range_read_addr_blocks[];
34 extern const esp_efuse_range_addr_t range_write_addr_blocks[];
35
36 static int get_reg_num(int bit_start, int bit_count, int i_reg);
37 static int get_starting_bit_num_in_reg(int bit_start, int i_reg);
38 static uint32_t get_mask(unsigned int bit_count, unsigned int shift);
39 static int get_count_bits_in_reg(int bit_start, int bit_count, int i_reg);
40 static void write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint32_t value);
41 static uint32_t fill_reg(int bit_start_in_reg, int bit_count_in_reg, uint8_t* blob, int* filled_bits_blob);
42 static uint32_t set_cnt_in_reg(int bit_start_in_reg, int bit_count_used_in_reg, uint32_t reg_masked, size_t* cnt);
43 static bool check_range_of_bits(esp_efuse_block_t blk, int offset_in_bits, int size_bits);
44
45 // This function processes the field by calling the passed function.
esp_efuse_utility_process(const esp_efuse_desc_t * field[],void * ptr,size_t ptr_size_bits,efuse_func_proc_t func_proc)46 esp_err_t esp_efuse_utility_process(const esp_efuse_desc_t* field[], void* ptr, size_t ptr_size_bits, efuse_func_proc_t func_proc)
47 {
48 esp_err_t err = ESP_OK;
49 int bits_counter = 0;
50
51 // get and check size.
52 int field_len = esp_efuse_get_field_size(field);
53 int req_size = (ptr_size_bits == 0) ? field_len : MIN(ptr_size_bits, field_len);
54
55 int i = 0;
56 while (err == ESP_OK && req_size > bits_counter && field[i] != NULL) {
57 if (check_range_of_bits(field[i]->efuse_block, field[i]->bit_start, field[i]->bit_count) == false) {
58 ESP_EARLY_LOGE(TAG, "Range of data does not match the coding scheme");
59 err = ESP_ERR_CODING;
60 }
61 int i_reg = 0;
62 int num_reg;
63 while (err == ESP_OK && req_size > bits_counter &&
64 (num_reg = get_reg_num(field[i]->bit_start, field[i]->bit_count, i_reg)) != -1) {
65
66 int start_bit = get_starting_bit_num_in_reg(field[i]->bit_start, i_reg);
67 int num_bits = get_count_bits_in_reg(field[i]->bit_start, field[i]->bit_count, i_reg);
68 if ((bits_counter + num_bits) > req_size) { // Limits the length of the field.
69 num_bits = req_size - bits_counter;
70 }
71 ESP_EARLY_LOGD(TAG, "In EFUSE_BLK%d__DATA%d_REG is used %d bits starting with %d bit",
72 (int)field[i]->efuse_block, num_reg, num_bits, start_bit);
73 err = func_proc(num_reg, field[i]->efuse_block, start_bit, num_bits, ptr, &bits_counter);
74 ++i_reg;
75 }
76 i++;
77 }
78 assert(bits_counter <= req_size);
79 return err;
80 }
81
82
83 // Read efuse register and write this value to array.
esp_efuse_utility_fill_buff(unsigned int num_reg,esp_efuse_block_t efuse_block,int bit_start,int bit_count,void * arr_out,int * bits_counter)84 esp_err_t esp_efuse_utility_fill_buff(unsigned int num_reg, esp_efuse_block_t efuse_block, int bit_start, int bit_count, void* arr_out, int* bits_counter)
85 {
86 uint8_t* blob = (uint8_t *) arr_out;
87 uint32_t reg = esp_efuse_utility_read_reg(efuse_block, num_reg);
88 uint64_t reg_of_aligned_bits = (reg >> bit_start) & get_mask(bit_count, 0);
89
90 int shift_bit = (*bits_counter) % 8;
91 if (shift_bit != 0) {
92 blob[(*bits_counter) / 8] |= (uint8_t)(reg_of_aligned_bits << shift_bit);
93 shift_bit = ((8 - shift_bit) < bit_count) ? (8 - shift_bit) : bit_count;
94 (*bits_counter) += shift_bit;
95 bit_count -= shift_bit;
96 }
97
98 int sum_shift = 0;
99 while (bit_count > 0) {
100 sum_shift += shift_bit;
101 blob[(*bits_counter) / 8] |= (uint8_t)(reg_of_aligned_bits >> sum_shift);
102 shift_bit = (bit_count > 8) ? 8 : bit_count;
103 (*bits_counter) += shift_bit;
104 bit_count -= shift_bit;
105 };
106 return ESP_OK;
107 }
108
109 // Count a set bits.
esp_efuse_utility_count_once(unsigned int num_reg,esp_efuse_block_t efuse_block,int bit_start,int bit_count,void * out_cnt,int * bits_counter)110 esp_err_t esp_efuse_utility_count_once(unsigned int num_reg, esp_efuse_block_t efuse_block, int bit_start, int bit_count, void* out_cnt, int* bits_counter)
111 {
112 uint32_t reg = esp_efuse_utility_read_reg(efuse_block, num_reg);
113 *((size_t *)out_cnt) += __builtin_popcount(reg & get_mask(bit_count, bit_start)); // Returns the number of 1-bits in reg.
114 *bits_counter += bit_count;
115 return ESP_OK;
116 }
117
118 // Fill registers from array for writing.
esp_efuse_utility_write_blob(unsigned int num_reg,esp_efuse_block_t efuse_block,int bit_start,int bit_count,void * arr_in,int * bits_counter)119 esp_err_t esp_efuse_utility_write_blob(unsigned int num_reg, esp_efuse_block_t efuse_block, int bit_start, int bit_count, void* arr_in, int* bits_counter)
120 {
121 uint32_t reg_to_write = fill_reg(bit_start, bit_count, (uint8_t *)arr_in, bits_counter);
122 return esp_efuse_utility_write_reg(efuse_block, num_reg, reg_to_write);
123 }
124
125 // fill registers with the required number of bits for writing.
esp_efuse_utility_write_cnt(unsigned int num_reg,esp_efuse_block_t efuse_block,int bit_start,int bit_count,void * cnt,int * bits_counter)126 esp_err_t esp_efuse_utility_write_cnt(unsigned int num_reg, esp_efuse_block_t efuse_block, int bit_start, int bit_count, void* cnt, int* bits_counter)
127 {
128 esp_err_t err = ESP_OK;
129 uint32_t reg = esp_efuse_utility_read_reg(efuse_block, num_reg);
130 size_t* set_bits = (size_t*)cnt;
131 uint32_t mask = get_mask(bit_count, bit_start);
132 uint32_t reg_masked_bits = reg & mask;
133 if ((reg_masked_bits ^ mask) != 0) {// register has free bits to set them to 1?
134 uint32_t reg_to_write = set_cnt_in_reg(bit_start, bit_count, reg_masked_bits, set_bits);
135 write_reg(efuse_block, num_reg, reg_to_write);
136 }
137 *bits_counter += bit_count;
138 if ((*set_bits) == 0) {
139 err = ESP_OK_EFUSE_CNT;
140 }
141 return err;
142 }
143
144 // Reset efuse write registers
esp_efuse_utility_reset(void)145 void esp_efuse_utility_reset(void)
146 {
147 esp_efuse_utility_clear_program_registers();
148 for (int num_block = EFUSE_BLK0; num_block < EFUSE_BLK_MAX; num_block++) {
149 for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
150 REG_WRITE(addr_wr_block, 0);
151 }
152 }
153 }
154
155 // Erase the virt_blocks array.
esp_efuse_utility_erase_virt_blocks(void)156 void esp_efuse_utility_erase_virt_blocks(void)
157 {
158 #ifdef CONFIG_EFUSE_VIRTUAL
159 memset(virt_blocks, 0, sizeof(virt_blocks));
160 #endif
161 }
162
163 // Fills the virt_blocks array by values from efuse_Rdata.
esp_efuse_utility_update_virt_blocks(void)164 void esp_efuse_utility_update_virt_blocks(void)
165 {
166 #ifdef CONFIG_EFUSE_VIRTUAL
167 ESP_EARLY_LOGI(TAG, "Loading virtual efuse blocks from real efuses");
168 for (int num_block = EFUSE_BLK0; num_block < EFUSE_BLK_MAX; num_block++) {
169 int subblock = 0;
170 for (uint32_t addr_rd_block = range_read_addr_blocks[num_block].start; addr_rd_block <= range_read_addr_blocks[num_block].end; addr_rd_block += 4) {
171 virt_blocks[num_block][subblock++] = REG_READ(addr_rd_block);
172 }
173 ESP_EARLY_LOGD(TAG, "virt_blocks[%d] is filled by EFUSE_BLOCK%d", num_block, num_block);
174 }
175 #else
176 ESP_EARLY_LOGI(TAG, "Emulate efuse is disabled");
177 #endif
178 }
179
180 // Prints efuse values for all registers.
181 #ifndef BOOTLOADER_BUILD
esp_efuse_utility_debug_dump_blocks(void)182 void esp_efuse_utility_debug_dump_blocks(void)
183 {
184 printf("EFUSE_BLKx:\n");
185 #ifdef CONFIG_EFUSE_VIRTUAL
186 for (int num_block = EFUSE_BLK0; num_block < EFUSE_BLK_MAX; num_block++) {
187 int num_reg = 0;
188 printf("%d) ", num_block);
189 for (uint32_t addr_rd_block = range_read_addr_blocks[num_block].start; addr_rd_block <= range_read_addr_blocks[num_block].end; addr_rd_block += 4, num_reg++) {
190 printf("0x%08x ", virt_blocks[num_block][num_reg]);
191 }
192 printf("\n");
193 }
194 #else
195 for (int num_block = EFUSE_BLK0; num_block < EFUSE_BLK_MAX; num_block++) {
196 printf("%d) ", num_block);
197 for (uint32_t addr_rd_block = range_read_addr_blocks[num_block].start; addr_rd_block <= range_read_addr_blocks[num_block].end; addr_rd_block += 4) {
198 printf("0x%08x ", REG_READ(addr_rd_block));
199 }
200 printf("\n");
201 }
202 #endif
203 printf("\n");
204 }
205 #endif // BOOTLOADER_BUILD
206
207 // returns the number of array elements for placing these bits in an array with the length of each element equal to size_of_base.
esp_efuse_utility_get_number_of_items(int bits,int size_of_base)208 int esp_efuse_utility_get_number_of_items(int bits, int size_of_base)
209 {
210 return bits / size_of_base + (bits % size_of_base > 0 ? 1 : 0);
211 }
212
213 // Writing efuse register with checking of repeated programming of programmed bits.
esp_efuse_utility_write_reg(esp_efuse_block_t efuse_block,unsigned int num_reg,uint32_t reg_to_write)214 esp_err_t esp_efuse_utility_write_reg(esp_efuse_block_t efuse_block, unsigned int num_reg, uint32_t reg_to_write)
215 {
216 esp_err_t err = ESP_OK;
217 uint32_t reg = esp_efuse_utility_read_reg(efuse_block, num_reg);
218 if (reg & reg_to_write) {
219 ESP_EARLY_LOGE(TAG, "Repeated programming of programmed bits is strictly forbidden 0x%08x", reg & reg_to_write);
220 err = ESP_ERR_EFUSE_REPEATED_PROG;
221 } else {
222 write_reg(efuse_block, num_reg, reg_to_write);
223 }
224 return err;
225 }
226
227 // Reading efuse register.
esp_efuse_utility_read_reg(esp_efuse_block_t blk,unsigned int num_reg)228 uint32_t esp_efuse_utility_read_reg(esp_efuse_block_t blk, unsigned int num_reg)
229 {
230 assert(blk >= 0 && blk < EFUSE_BLK_MAX);
231 unsigned int max_num_reg = (range_read_addr_blocks[blk].end - range_read_addr_blocks[blk].start) / sizeof(uint32_t);
232 assert(num_reg <= max_num_reg);
233 uint32_t value;
234 #ifdef CONFIG_EFUSE_VIRTUAL
235 value = virt_blocks[blk][num_reg];
236 #else
237 value = REG_READ(range_read_addr_blocks[blk].start + num_reg * 4);
238 #endif
239 return value;
240 }
241
242 // Private functions
243
244 // writing efuse register.
write_reg(esp_efuse_block_t blk,unsigned int num_reg,uint32_t value)245 static void write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint32_t value)
246 {
247 assert(blk >= 0 && blk < EFUSE_BLK_MAX);
248 unsigned int max_num_reg = (range_read_addr_blocks[blk].end - range_read_addr_blocks[blk].start) / sizeof(uint32_t);
249 assert(num_reg <= max_num_reg);
250 uint32_t addr_wr_reg = range_write_addr_blocks[blk].start + num_reg * 4;
251 uint32_t reg_to_write = REG_READ(addr_wr_reg) | value;
252 // The register can be written in parts so we combine the new value with the one already available.
253 REG_WRITE(addr_wr_reg, reg_to_write);
254 }
255
256 // return mask with required the number of ones with shift.
get_mask(unsigned int bit_count,unsigned int shift)257 static uint32_t get_mask(unsigned int bit_count, unsigned int shift)
258 {
259 uint32_t mask;
260 if (bit_count != 32) {
261 mask = (1 << bit_count) - 1;
262 } else {
263 mask = 0xFFFFFFFF;
264 }
265 return mask << shift;
266 }
267
268 // return the register number in the array. return -1 if all registers for field was selected.
get_reg_num(int bit_start,int bit_count,int i_reg)269 static int get_reg_num(int bit_start, int bit_count, int i_reg)
270 {
271 int num_reg = i_reg + bit_start / 32;
272
273 if (num_reg > (bit_start + bit_count - 1) / 32) {
274 return -1;
275 }
276
277 return num_reg;
278 }
279
280 // returns the starting bit number in the register.
get_starting_bit_num_in_reg(int bit_start,int i_reg)281 static int get_starting_bit_num_in_reg(int bit_start, int i_reg)
282 {
283 return (i_reg == 0) ? bit_start % 32 : 0;
284 }
285
286 // Returns the number of bits in the register.
get_count_bits_in_reg(int bit_start,int bit_count,int i_reg)287 static int get_count_bits_in_reg(int bit_start, int bit_count, int i_reg)
288 {
289 int ret_count = 0;
290 int num_reg = 0;
291 int last_used_bit = (bit_start + bit_count - 1);
292 for (int num_bit = bit_start; num_bit <= last_used_bit; ++num_bit) {
293 ++ret_count;
294 if ((((num_bit + 1) % 32) == 0) || (num_bit == last_used_bit)) {
295 if (i_reg == num_reg++) {
296 return ret_count;
297 }
298 ret_count = 0;
299 }
300 }
301 return 0;
302 }
303
304 // fill efuse register from array.
fill_reg(int bit_start_in_reg,int bit_count_in_reg,uint8_t * blob,int * filled_bits_blob)305 static uint32_t fill_reg(int bit_start_in_reg, int bit_count_in_reg, uint8_t* blob, int* filled_bits_blob)
306 {
307 uint32_t reg_to_write = 0;
308 uint32_t temp_blob_32;
309 int shift_bit = (*filled_bits_blob) % 8;
310 if (shift_bit != 0) {
311 temp_blob_32 = blob[(*filled_bits_blob) / 8] >> shift_bit;
312 shift_bit = ((8 - shift_bit) < bit_count_in_reg) ? (8 - shift_bit) : bit_count_in_reg;
313 reg_to_write = temp_blob_32 & get_mask(shift_bit, 0);
314 (*filled_bits_blob) += shift_bit;
315 bit_count_in_reg -= shift_bit;
316 }
317
318 int shift_reg = shift_bit;
319 while (bit_count_in_reg > 0) {
320 temp_blob_32 = blob[(*filled_bits_blob) / 8];
321 shift_bit = (bit_count_in_reg > 8) ? 8 : bit_count_in_reg;
322 reg_to_write |= (temp_blob_32 & get_mask(shift_bit, 0)) << shift_reg;
323 (*filled_bits_blob) += shift_bit;
324 bit_count_in_reg -= shift_bit;
325 shift_reg += 8;
326 };
327 return reg_to_write << bit_start_in_reg;
328 }
329
330 // sets a required count of bits as "1".
set_cnt_in_reg(int bit_start_in_reg,int bit_count_used_in_reg,uint32_t reg_masked,size_t * cnt)331 static uint32_t set_cnt_in_reg(int bit_start_in_reg, int bit_count_used_in_reg, uint32_t reg_masked, size_t* cnt)
332 {
333 assert((bit_start_in_reg + bit_count_used_in_reg) <= 32);
334 uint32_t reg_to_write = 0;
335 for (int i = bit_start_in_reg; i < bit_start_in_reg + bit_count_used_in_reg; ++i) {
336 if ((reg_masked & (1 << i)) == 0) {
337 reg_to_write |= (1 << i);
338 if (--(*cnt) == 0) {
339 break;
340 }
341 }
342 }
343 return reg_to_write;
344 }
345
346 // check range of bits for any coding scheme.
check_range_of_bits(esp_efuse_block_t blk,int offset_in_bits,int size_bits)347 static bool check_range_of_bits(esp_efuse_block_t blk, int offset_in_bits, int size_bits)
348 {
349 int max_num_bit = offset_in_bits + size_bits;
350 if (max_num_bit > 256) {
351 return false;
352 } else {
353 ESP_EFUSE_FIELD_CORRESPONDS_CODING_SCHEME(blk, max_num_bit);
354 }
355 return true;
356 }
357