1 /**
2   ******************************************************************************
3   * @file    bl616_ef_ctrl.c
4   * @version V1.0
5   * @date
6   * @brief   This file is the standard driver c file
7   ******************************************************************************
8   * @attention
9   *
10   * <h2><center>&copy; COPYRIGHT(c) 2020 Bouffalo Lab</center></h2>
11   *
12   * Redistribution and use in source and binary forms, with or without modification,
13   * are permitted provided that the following conditions are met:
14   *   1. Redistributions of source code must retain the above copyright notice,
15   *      this list of conditions and the following disclaimer.
16   *   2. Redistributions in binary form must reproduce the above copyright notice,
17   *      this list of conditions and the following disclaimer in the documentation
18   *      and/or other materials provided with the distribution.
19   *   3. Neither the name of Bouffalo Lab nor the names of its contributors
20   *      may be used to endorse or promote products derived from this software
21   *      without specific prior written permission.
22   *
23   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
27   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33   *
34   ******************************************************************************
35   */
36 #include "bl616_ef_cfg.h"
37 #include "hardware/ef_data_reg.h"
38 
39 extern int bflb_efuse_read_mac_address_opt(uint8_t slot, uint8_t mac[6], uint8_t reload);
40 
41 static const bflb_ef_ctrl_com_trim_cfg_t trim_list[] = {
42     {
43         .name = "ldo15",
44         .en_addr = 0x68 * 8 + 31,
45         .parity_addr = 0x68 * 8 + 30,
46         .value_addr = 0x68 * 8 + 27,
47         .value_len = 3,
48     },
49     {
50         .name = "iptat",
51         .en_addr = 0x74 * 8 + 31,
52         .parity_addr = 0x74 * 8 + 30,
53         .value_addr = 0x68 * 8 + 22,
54         .value_len = 5,
55     },
56     {
57         .name = "icx",
58         .en_addr = 0x74 * 8 + 29,
59         .parity_addr = 0x74 * 8 + 28,
60         .value_addr = 0x74 * 8 + 22,
61         .value_len = 6,
62     },
63     {
64         .name = "dcdc_trim",
65         .en_addr = 0x78 * 8 + 31,
66         .parity_addr = 0x78 * 8 + 30,
67         .value_addr = 0x78 * 8 + 26,
68         .value_len = 4,
69     },
70     {
71         .name = "ldo18_sel",
72         .en_addr = 0x78 * 8 + 25,
73         .parity_addr = 0x78 * 8 + 24,
74         .value_addr = 0x78 * 8 + 20,
75         .value_len = 4,
76     },
77     {
78         .name = "ldo18_trim",
79         .en_addr = 0x78 * 8 + 19,
80         .parity_addr = 0x78 * 8 + 18,
81         .value_addr = 0x78 * 8 + 14,
82         .value_len = 4,
83     },
84     {
85         .name = "ldo33_trim",
86         .en_addr = 0x78 * 8 + 13,
87         .parity_addr = 0x78 * 8 + 12,
88         .value_addr = 0x78 * 8 + 8,
89         .value_len = 4,
90     },
91     {
92         .name = "ldo11_tirm",
93         .en_addr = 0x78 * 8 + 7,
94         .parity_addr = 0x78 * 8 + 6,
95         .value_addr = 0x78 * 8 + 2,
96         .value_len = 4,
97     },
98     {
99         .name = "rc32m",
100         .en_addr = 0x78 * 8 + 1,
101         .parity_addr = 0x78 * 8 + 0,
102         .value_addr = 0x7C * 8 + 4,
103         .value_len = 8,
104     },
105     {
106         .name = "hp_poffset0",
107         .en_addr = 0xCC * 8 + 26,
108         .parity_addr = 0xC0 * 8 + 15,
109         .value_addr = 0xC0 * 8 + 0,
110         .value_len = 15,
111     },
112     {
113         .name = "hp_poffset1",
114         .en_addr = 0xCC * 8 + 27,
115         .parity_addr = 0xC0 * 8 + 31,
116         .value_addr = 0xC0 * 8 + 16,
117         .value_len = 15,
118     },
119     {
120         .name = "hp_poffset2",
121         .en_addr = 0xCC * 8 + 28,
122         .parity_addr = 0xC4 * 8 + 15,
123         .value_addr = 0xC4 * 8 + 0,
124         .value_len = 15,
125     },
126     {
127         .name = "lp_poffset0",
128         .en_addr = 0xCC * 8 + 29,
129         .parity_addr = 0xC4 * 8 + 31,
130         .value_addr = 0xC4 * 8 + 16,
131         .value_len = 15,
132     },
133     {
134         .name = "lp_poffset1",
135         .en_addr = 0xCC * 8 + 30,
136         .parity_addr = 0xC8 * 8 + 15,
137         .value_addr = 0xC8 * 8 + 0,
138         .value_len = 15,
139     },
140     {
141         .name = "lp_poffset2",
142         .en_addr = 0xCC * 8 + 31,
143         .parity_addr = 0xC8 * 8 + 31,
144         .value_addr = 0xC8 * 8 + 16,
145         .value_len = 15,
146     },
147     {
148         .name = "bz_poffset0",
149         .en_addr = 0xD0 * 8 + 26,
150         .parity_addr = 0xCC * 8 + 25,
151         .value_addr = 0xCC * 8 + 0,
152         .value_len = 25,
153     },
154     {
155         .name = "bz_poffset1",
156         .en_addr = 0xD0 * 8 + 27,
157         .parity_addr = 0xD0 * 8 + 25,
158         .value_addr = 0xD0 * 8 + 0,
159         .value_len = 25,
160     },
161     {
162         .name = "bz_poffset2",
163         .en_addr = 0xD0 * 8 + 28,
164         .parity_addr = 0xD4 * 8 + 25,
165         .value_addr = 0xD4 * 8 + 0,
166         .value_len = 25,
167     },
168     {
169         .name = "tmp_mp0",
170         .en_addr = 0xD8 * 8 + 9,
171         .parity_addr = 0xD8 * 8 + 8,
172         .value_addr = 0xD8 * 8 + 0,
173         .value_len = 8,
174     },
175     {
176         .name = "tmp_mp1",
177         .en_addr = 0xD8 * 8 + 19,
178         .parity_addr = 0xD8 * 8 + 18,
179         .value_addr = 0xD8 * 8 + 10,
180         .value_len = 8,
181     },
182     {
183         .name = "tmp_mp2",
184         .en_addr = 0xD8 * 8 + 29,
185         .parity_addr = 0xD8 * 8 + 28,
186         .value_addr = 0xD8 * 8 + 20,
187         .value_len = 8,
188     },
189     {
190         .name = "auadc_gain",
191         .en_addr = 0xDC * 8 + 25,
192         .parity_addr = 0xDC * 8 + 24,
193         .value_addr = 0xDC * 8 + 0,
194         .value_len = 24,
195     },
196     {
197         .name = "auadc_offset",
198         .en_addr = 0xE0 * 8 + 25,
199         .parity_addr = 0xE0 * 8 + 24,
200         .value_addr = 0xE0 * 8 + 0,
201         .value_len = 24,
202     },
203     {
204         .name = "psram_trim",
205         .en_addr = 0xE8 * 8 + 12,
206         .parity_addr = 0xE8 * 8 + 11,
207         .value_addr = 0xE8 * 8 + 0,
208         .value_len = 11,
209     },
210     {
211         .name = "rc32k",
212         .en_addr = 0xEC * 8 + 19,
213         .parity_addr = 0xEC * 8 + 18,
214         .value_addr = 0xEC * 8 + 8,
215         .value_len = 10,
216     },
217     {
218         .name = "xtal0",
219         .en_addr = 0xEC * 8 + 7,
220         .parity_addr = 0xEC * 8 + 6,
221         .value_addr = 0xEC * 8 + 0,
222         .value_len = 6,
223     },
224     {
225         .name = "xtal1",
226         .en_addr = 0xF0 * 8 + 31,
227         .parity_addr = 0xF0 * 8 + 30,
228         .value_addr = 0xF4 * 8 + 26,
229         .value_len = 6,
230     },
231     {
232         .name = "xtal2",
233         .en_addr = 0xF0 * 8 + 29,
234         .parity_addr = 0xF0 * 8 + 28,
235         .value_addr = 0xF4 * 8 + 20,
236         .value_len = 6,
237     },
238     {
239         .name = "gpadc_gain",
240         .en_addr = 0xF0 * 8 + 27,
241         .parity_addr = 0xF0 * 8 + 26,
242         .value_addr = 0xF0 * 8 + 14,
243         .value_len = 12,
244     },
245     {
246         .name = "tsen",
247         .en_addr = 0xF0 * 8 + 13,
248         .parity_addr = 0xF0 * 8 + 12,
249         .value_addr = 0xF0 * 8 + 0,
250         .value_len = 12,
251     },
252     {
253         .name = "dcdc_dis",
254         .en_addr = 0xF4 * 8 + 19,
255         .parity_addr = 0xF4 * 8 + 18,
256         .value_addr = 0xF4 * 8 + 17,
257         .value_len = 1,
258     },
259     {
260         .name = "dcdc_vout",
261         .en_addr = 0xF4 * 8 + 16,
262         .parity_addr = 0xF4 * 8 + 15,
263         .value_addr = 0xF4 * 8 + 10,
264         .value_len = 5,
265     },
266     {
267         .name = "ldo18_bypass",
268         .en_addr = 0xF4 * 8 + 9,
269         .parity_addr = 0xF4 * 8 + 8,
270         .value_addr = 0xF4 * 8 + 4,
271         .value_len = 1,
272     },
273     {
274         .name = "usb20",
275         .en_addr = 0xF8 * 8 + 15,
276         .parity_addr = 0xF8 * 8 + 14,
277         .value_addr = 0xF8 * 8 + 8,
278         .value_len = 6,
279     }
280 };
281 
282 /****************************************************************************/ /**
283  * @brief  Efuse get trim list
284  *
285  * @param  trim_list: Trim list pointer
286  *
287  * @return Trim list count
288  *
289 *******************************************************************************/
bflb_ef_ctrl_get_common_trim_list(const bflb_ef_ctrl_com_trim_cfg_t ** ptrim_list)290 uint32_t bflb_ef_ctrl_get_common_trim_list(const bflb_ef_ctrl_com_trim_cfg_t **ptrim_list)
291 {
292     *ptrim_list = &trim_list[0];
293     return sizeof(trim_list) / sizeof(trim_list[0]);
294 }
295 
296 /****************************************************************************/ /**
297  * @brief  Efuse read device info
298  *
299  * @param  deviceInfo: info pointer
300  *
301  * @return None
302  *
303 *******************************************************************************/
bflb_ef_ctrl_get_device_info(bflb_efuse_device_info_type * deviceInfo)304 void bflb_ef_ctrl_get_device_info(bflb_efuse_device_info_type *deviceInfo)
305 {
306     uint32_t *p = (uint32_t *)deviceInfo;
307 
308     bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_WIFI_MAC_HIGH_OFFSET, p, 1, 1);
309 }
310 
bflb_efuse_get_chipid(uint8_t chipid[8])311 void bflb_efuse_get_chipid(uint8_t chipid[8])
312 {
313     bflb_efuse_read_mac_address_opt(0, chipid, 1);
314     chipid[6] = 0;
315     chipid[7] = 0;
316 }
317 
318 /****************************************************************************/ /**
319  * @brief  Whether MAC address slot is empty
320  *
321  * @param  slot: MAC address slot
322  * @param  reload: whether  reload to check
323  *
324  * @return 0 for all slots full,1 for others
325  *
326 *******************************************************************************/
bflb_efuse_is_mac_address_slot_empty(uint8_t slot,uint8_t reload)327 uint8_t bflb_efuse_is_mac_address_slot_empty(uint8_t slot, uint8_t reload)
328 {
329     uint32_t tmp1 = 0xffffffff, tmp2 = 0xffffffff;
330     uint32_t part1Empty = 0, part2Empty = 0;
331 
332     if (slot == 0) {
333         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_WIFI_MAC_LOW_OFFSET, &tmp1, 1, reload);
334         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_WIFI_MAC_HIGH_OFFSET, &tmp2, 1, reload);
335     } else if (slot == 1) {
336         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_SW_USAGE_2_OFFSET, &tmp1, 1, reload);
337         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_SW_USAGE_3_OFFSET, &tmp2, 1, reload);
338     } else if (slot == 2) {
339         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_KEY_SLOT_11_W1_OFFSET, &tmp1, 1, reload);
340         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_KEY_SLOT_11_W2_OFFSET, &tmp2, 1, reload);
341     }
342 
343     part1Empty = (bflb_ef_ctrl_is_all_bits_zero(tmp1, 0, 32));
344     part2Empty = (bflb_ef_ctrl_is_all_bits_zero(tmp2, 0, 22));
345 
346     return (part1Empty && part2Empty);
347 }
348 
349 /****************************************************************************/ /**
350  * @brief  Efuse write optional MAC address
351  *
352  * @param  slot: MAC address slot
353  * @param  mac[6]: MAC address buffer
354  * @param  program: Whether program
355  *
356  * @return 0 or -1
357  *
358 *******************************************************************************/
bflb_efuse_write_mac_address_opt(uint8_t slot,uint8_t mac[6],uint8_t program)359 int bflb_efuse_write_mac_address_opt(uint8_t slot, uint8_t mac[6], uint8_t program)
360 {
361     uint8_t *maclow = (uint8_t *)mac;
362     uint8_t *machigh = (uint8_t *)(mac + 4);
363     uint32_t tmpval;
364     uint32_t i = 0, cnt;
365 
366     if (slot >= 3) {
367         return -1;
368     }
369 
370     /* Change to local order */
371     for (i = 0; i < 3; i++) {
372         tmpval = mac[i];
373         mac[i] = mac[5 - i];
374         mac[5 - i] = tmpval;
375     }
376 
377     /* The low 32 bits */
378     tmpval = BL_RDWD_FRM_BYTEP(maclow);
379 
380     if (slot == 0) {
381         bflb_ef_ctrl_write_direct(NULL, EF_DATA_EF_WIFI_MAC_LOW_OFFSET, &tmpval, 1, program);
382     } else if (slot == 1) {
383         bflb_ef_ctrl_write_direct(NULL, EF_DATA_EF_SW_USAGE_2_OFFSET, &tmpval, 1, program);
384     } else if (slot == 2) {
385         bflb_ef_ctrl_write_direct(NULL, EF_DATA_EF_KEY_SLOT_11_W1_OFFSET, &tmpval, 1, program);
386     }
387 
388     /* The high 16 bits */
389     tmpval = machigh[0] + (machigh[1] << 8);
390     cnt = 0;
391 
392     for (i = 0; i < 6; i++) {
393         cnt += bflb_ef_ctrl_get_byte_zero_cnt(mac[i]);
394     }
395 
396     tmpval |= ((cnt & 0x3f) << 16);
397 
398     if (slot == 0) {
399         bflb_ef_ctrl_write_direct(NULL, EF_DATA_EF_WIFI_MAC_HIGH_OFFSET, &tmpval, 1, program);
400     } else if (slot == 1) {
401         bflb_ef_ctrl_write_direct(NULL, EF_DATA_EF_SW_USAGE_3_OFFSET, &tmpval, 1, program);
402     } else if (slot == 2) {
403         bflb_ef_ctrl_write_direct(NULL, EF_DATA_EF_KEY_SLOT_11_W2_OFFSET, &tmpval, 1, program);
404     }
405 
406     return 0;
407 }
408 
409 /****************************************************************************/ /**
410  * @brief  Efuse read optional MAC address
411  *
412  * @param  slot: MAC address slot
413  * @param  mac[6]: MAC address buffer
414  * @param  reload: Whether reload
415  *
416  * @return 0 or -1
417  *
418 *******************************************************************************/
bflb_efuse_read_mac_address_opt(uint8_t slot,uint8_t mac[6],uint8_t reload)419 int bflb_efuse_read_mac_address_opt(uint8_t slot, uint8_t mac[6], uint8_t reload)
420 {
421     uint8_t *maclow = (uint8_t *)mac;
422     uint8_t *machigh = (uint8_t *)(mac + 4);
423     uint32_t tmpval = 0;
424     uint32_t i = 0;
425     uint32_t cnt = 0;
426 
427     if (slot >= 3) {
428         return -1;
429     }
430 
431     if (slot == 0) {
432         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_WIFI_MAC_LOW_OFFSET, &tmpval, 1, reload);
433     } else if (slot == 1) {
434         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_SW_USAGE_2_OFFSET, &tmpval, 1, reload);
435     } else if (slot == 2) {
436         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_KEY_SLOT_11_W1_OFFSET, &tmpval, 1, reload);
437     }
438 
439     BL_WRWD_TO_BYTEP(maclow, tmpval);
440 
441     if (slot == 0) {
442         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_WIFI_MAC_HIGH_OFFSET, &tmpval, 1, reload);
443     } else if (slot == 1) {
444         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_SW_USAGE_3_OFFSET, &tmpval, 1, reload);
445     } else if (slot == 2) {
446         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_KEY_SLOT_11_W2_OFFSET, &tmpval, 1, reload);
447     }
448 
449     machigh[0] = tmpval & 0xff;
450     machigh[1] = (tmpval >> 8) & 0xff;
451 
452     /* Check parity */
453     for (i = 0; i < 6; i++) {
454         cnt += bflb_ef_ctrl_get_byte_zero_cnt(mac[i]);
455     }
456 
457     if ((cnt & 0x3f) == ((tmpval >> 16) & 0x3f)) {
458         /* Change to network order */
459         for (i = 0; i < 3; i++) {
460             tmpval = mac[i];
461             mac[i] = mac[5 - i];
462             mac[5 - i] = tmpval;
463         }
464         return 0;
465     } else {
466         return -1;
467     }
468 }
469 
bflb_efuse_get_adc_trim(void)470 float bflb_efuse_get_adc_trim(void)
471 {
472     bflb_ef_ctrl_com_trim_t trim;
473     uint32_t tmp;
474 
475     float coe = 1.0;
476 
477     bflb_ef_ctrl_read_common_trim(NULL, "gpadc_gain", &trim, 1);
478 
479     if (trim.en) {
480         if (trim.parity == bflb_ef_ctrl_get_trim_parity(trim.value, trim.len)) {
481             tmp = trim.value;
482 
483             if (tmp & 0x800) {
484                 tmp = ~tmp;
485                 tmp += 1;
486                 tmp = tmp & 0xfff;
487                 coe = (1.0 + ((float)tmp / 2048.0));
488             } else {
489                 coe = (1.0 - ((float)tmp / 2048.0));
490             }
491         }
492     }
493 
494     return coe;
495 }
496 
bflb_efuse_get_adc_tsen_trim(void)497 uint32_t bflb_efuse_get_adc_tsen_trim(void)
498 {
499     bflb_ef_ctrl_com_trim_t trim;
500 
501     bflb_ef_ctrl_read_common_trim(NULL, "tsen", &trim, 1);
502     if (trim.en) {
503         if (trim.parity == bflb_ef_ctrl_get_trim_parity(trim.value, trim.len)) {
504             return trim.value;
505         }
506     }
507 
508     return 2042;
509 }
510 
bflb_efuse_read_secure_boot(uint8_t * sign,uint8_t * aes)511 void bflb_efuse_read_secure_boot(uint8_t *sign, uint8_t *aes)
512 {
513     uint32_t tmpval = 0;
514 
515     bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_CFG_0_OFFSET, &tmpval, 1, 1);
516     *sign = ((tmpval & EF_DATA_EF_SBOOT_SIGN_MODE_MSK) >> EF_DATA_EF_SBOOT_SIGN_MODE_POS) & 0x01;
517     *aes = ((tmpval & EF_DATA_EF_SF_AES_MODE_MSK) >> EF_DATA_EF_SF_AES_MODE_POS);
518 }
519 
bflb_efuse_write_aes_key(uint8_t index,uint8_t * data,uint32_t len)520 void bflb_efuse_write_aes_key(uint8_t index, uint8_t *data, uint32_t len)
521 {
522     if ((index <= 3) || (index == 11)) {
523         index = ((index == 11) ? 5 : index);
524         /* Every key is 4 words len*/
525         bflb_ef_ctrl_write_direct(NULL, 0x1C + index * 4, (uint32_t *)data, len, 1);
526     } else if ((index < 11) && (index > 3)) {
527         index = index - 4;
528         /* Every key is 4 words len*/
529         bflb_ef_ctrl_write_direct(NULL, 0x80 + index * 4, (uint32_t *)data, len, 1);
530     }
531 }
532 
bflb_efuse_read_aes_key(uint8_t index,uint8_t * data,uint32_t len)533 void bflb_efuse_read_aes_key(uint8_t index, uint8_t *data, uint32_t len)
534 {
535     if ((index <= 3) || (index == 11)) {
536         index = ((index == 11) ? 5 : index);
537         /* Every key is 4 words len*/
538         bflb_ef_ctrl_read_direct(NULL, 0x1C + index * 4, (uint32_t *)data, len, 1);
539     } else if ((index < 11) && (index > 3)) {
540         index = index - 4;
541         /* Every key is 4 words len*/
542         bflb_ef_ctrl_read_direct(NULL, 0x80 + index * 4, (uint32_t *)data, len, 1);
543     }
544 }
545 
bflb_efuse_lock_aes_key_write(uint8_t index)546 void bflb_efuse_lock_aes_key_write(uint8_t index)
547 {
548     uint32_t lock = 0;
549 
550     if ((index <= 3) || (index == 11)) {
551         index = ((index == 11) ? 8 : index);
552         lock |= (1 << (index + 17));
553         bflb_ef_ctrl_write_direct(NULL, 0x7c, &lock, 1, 1);
554     } else if ((index < 11) && (index > 3)) {
555         index = index - 4;
556         lock |= (1 << (index + 15));
557         bflb_ef_ctrl_write_direct(NULL, 0xfc, &lock, 1, 1);
558     }
559 }
560 
bflb_efuse_lock_aes_key_read(uint8_t index)561 void bflb_efuse_lock_aes_key_read(uint8_t index)
562 {
563     uint32_t lock = 0;
564 
565     if ((index <= 3) || (index == 11)) {
566         index = ((index == 11) ? 4 : index);
567         lock |= (1 << (index + 27));
568         bflb_ef_ctrl_write_direct(NULL, 0x7c, (uint32_t *)lock, 1, 1);
569     } else if ((index < 11) && (index > 3)) {
570         index = index - 4;
571         lock |= (1 << (index + 25));
572         bflb_ef_ctrl_write_direct(NULL, 0xfc, (uint32_t *)lock, 1, 1);
573     }
574 }
575 
bflb_efuse_write_sw_usage(uint32_t index,uint32_t usage,uint8_t program)576 void bflb_efuse_write_sw_usage(uint32_t index, uint32_t usage, uint8_t program)
577 {
578     bflb_ef_ctrl_write_direct(NULL, EF_DATA_EF_SW_USAGE_0_OFFSET + index * 4, &usage, 1, program);
579 }
580 
bflb_efuse_read_sw_usage(uint32_t index,uint32_t * usage)581 void bflb_efuse_read_sw_usage(uint32_t index, uint32_t *usage)
582 {
583     bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_SW_USAGE_0_OFFSET + index * 4, (uint32_t *)usage, 1, 1);
584 }