1 /**
2   ******************************************************************************
3   * @file    bl602_ef_cfg.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 "bl602_ef_cfg.h"
37 #include "bl602_glb.h"
38 #include "hardware/ef_data_reg.h"
39 
40 extern int bflb_efuse_read_mac_address_opt(uint8_t slot, uint8_t mac[6], uint8_t reload);
41 
42 static bflb_ef_ctrl_com_trim_cfg_t trim_list[] = {
43     {
44         .name = "rc32m",
45         .en_addr = 0x78 * 8 + 1,
46         .parity_addr = 0x78 * 8 + 0,
47         .value_addr = 0x7C * 8 + 4,
48         .value_len = 8,
49     },
50     {
51         .name = "rc32k",
52         .en_addr = 0xEC * 8 + 19,
53         .parity_addr = 0xEC * 8 + 18,
54         .value_addr = 0xEC * 8 + 8,
55         .value_len = 10,
56     },
57     {
58         .name = "gpadc_gain",
59         .en_addr = 0xF0 * 8 + 27,
60         .parity_addr = 0xF0 * 8 + 26,
61         .value_addr = 0xF0 * 8 + 14,
62         .value_len = 12,
63     },
64     {
65         .name = "tsen",
66         .en_addr = 0xF0 * 8 + 13,
67         .parity_addr = 0xF0 * 8 + 12,
68         .value_addr = 0xF0 * 8 + 0,
69         .value_len = 12,
70     }
71 };
72 
73 static GLB_ROOT_CLK_Type rtClk;
74 static uint8_t bdiv, hdiv;
75 
76 /****************************************************************************/ /**
77  * @brief  Efuse read write switch clock save
78  *
79  * @param  deviceInfo: info pointer
80  *
81  * @return None
82  *
83 *******************************************************************************/
bflb_efuse_switch_cpu_clock_save(void)84 void ATTR_TCM_SECTION bflb_efuse_switch_cpu_clock_save(void)
85 {
86     /* all API should be place at tcm section */
87     bdiv = GLB_Get_BCLK_Div();
88     hdiv = GLB_Get_HCLK_Div();
89     rtClk = GLB_Get_Root_CLK_Sel();
90     HBN_Set_ROOT_CLK_Sel(HBN_ROOT_CLK_RC32M);
91     GLB_Set_System_CLK_Div(0, 0);
92 }
93 
94 /****************************************************************************/ /**
95  * @brief  Efuse read write switch clock restore
96  *
97  * @param  deviceInfo: info pointer
98  *
99  * @return None
100  *
101 *******************************************************************************/
bflb_efuse_switch_cpu_clock_restore(void)102 void ATTR_TCM_SECTION bflb_efuse_switch_cpu_clock_restore(void)
103 {
104     /* all API should be place at tcm section */
105     GLB_Set_System_CLK_Div(hdiv, bdiv);
106     HBN_Set_ROOT_CLK_Sel(rtClk);
107 }
108 
109 /****************************************************************************/ /**
110  * @brief  Efuse get trim list
111  *
112  * @param  trim_list: Trim list pointer
113  *
114  * @return Trim list count
115  *
116 *******************************************************************************/
bflb_ef_ctrl_get_common_trim_list(const bflb_ef_ctrl_com_trim_cfg_t ** ptrim_list)117 uint32_t bflb_ef_ctrl_get_common_trim_list(const bflb_ef_ctrl_com_trim_cfg_t **ptrim_list)
118 {
119     *ptrim_list = &trim_list[0];
120     return sizeof(trim_list) / sizeof(trim_list[0]);
121 }
122 
123 /****************************************************************************/ /**
124  * @brief  Efuse read device info
125  *
126  * @param  deviceInfo: info pointer
127  *
128  * @return None
129  *
130 *******************************************************************************/
bflb_ef_ctrl_get_device_info(bflb_efuse_device_info_type * deviceInfo)131 void bflb_ef_ctrl_get_device_info(bflb_efuse_device_info_type *deviceInfo)
132 {
133     uint32_t *p = (uint32_t *)deviceInfo;
134     uint32_t tmpval;
135 
136     bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_WIFI_MAC_HIGH_OFFSET, p, 1, 1);
137 
138     bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_CFG_0_OFFSET, &tmpval, 1, 1);
139     deviceInfo->chip_ver = (tmpval >> 8) & 0x7;
140 }
141 
bflb_efuse_get_chipid(uint8_t chipid[8])142 void bflb_efuse_get_chipid(uint8_t chipid[8])
143 {
144     bflb_efuse_read_mac_address_opt(0, chipid, 1);
145     chipid[6] = 0;
146     chipid[7] = 0;
147 }
148 
149 /****************************************************************************/ /**
150  * @brief  Whether MAC address slot is empty
151  *
152  * @param  slot: MAC address slot
153  * @param  reload: whether  reload to check
154  *
155  * @return 0 for all slots full,1 for others
156  *
157 *******************************************************************************/
bflb_efuse_is_mac_address_slot_empty(uint8_t slot,uint8_t reload)158 uint8_t bflb_efuse_is_mac_address_slot_empty(uint8_t slot, uint8_t reload)
159 {
160     uint32_t tmp1 = 0xffffffff, tmp2 = 0xffffffff;
161     uint32_t part1Empty = 0, part2Empty = 0;
162 
163     if (slot == 0) {
164         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_WIFI_MAC_LOW_OFFSET, &tmp1, 1, reload);
165         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_WIFI_MAC_HIGH_OFFSET, &tmp2, 1, reload);
166     } else if (slot == 1) {
167         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_KEY_SLOT_5_W0_OFFSET, &tmp1, 1, reload);
168         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_KEY_SLOT_5_W1_OFFSET, &tmp2, 1, reload);
169     } else if (slot == 2) {
170         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_DBG_PWD_LOW_OFFSET, &tmp1, 1, reload);
171         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_DBG_PWD_HIGH_OFFSET, &tmp2, 1, reload);
172     }
173 
174     part1Empty = (bflb_ef_ctrl_is_all_bits_zero(tmp1, 0, 32));
175     part2Empty = (bflb_ef_ctrl_is_all_bits_zero(tmp2, 0, 22));
176 
177     return (part1Empty && part2Empty);
178 }
179 
180 /****************************************************************************/ /**
181  * @brief  Efuse write optional MAC address
182  *
183  * @param  slot: MAC address slot
184  * @param  mac[6]: MAC address buffer
185  * @param  program: Whether program
186  *
187  * @return 0 or -1
188  *
189 *******************************************************************************/
bflb_efuse_write_mac_address_opt(uint8_t slot,uint8_t mac[6],uint8_t program)190 int bflb_efuse_write_mac_address_opt(uint8_t slot, uint8_t mac[6], uint8_t program)
191 {
192     uint8_t *maclow = (uint8_t *)mac;
193     uint8_t *machigh = (uint8_t *)(mac + 4);
194     uint32_t tmpval;
195     uint32_t i = 0, cnt;
196 
197     if (slot >= 3) {
198         return -1;
199     }
200 
201     /* Change to local order */
202     for (i = 0; i < 3; i++) {
203         tmpval = mac[i];
204         mac[i] = mac[5 - i];
205         mac[5 - i] = tmpval;
206     }
207 
208     /* The low 32 bits */
209     tmpval = BL_RDWD_FRM_BYTEP(maclow);
210 
211     if (slot == 0) {
212         bflb_ef_ctrl_write_direct(NULL, EF_DATA_EF_WIFI_MAC_LOW_OFFSET, &tmpval, 1, program);
213     } else if (slot == 1) {
214         bflb_ef_ctrl_write_direct(NULL, EF_DATA_EF_KEY_SLOT_5_W0_OFFSET, &tmpval, 1, program);
215     } else if (slot == 2) {
216         bflb_ef_ctrl_write_direct(NULL, EF_DATA_EF_DBG_PWD_LOW_OFFSET, &tmpval, 1, program);
217     }
218 
219     /* The high 16 bits */
220     tmpval = machigh[0] + (machigh[1] << 8);
221     cnt = 0;
222 
223     for (i = 0; i < 6; i++) {
224         cnt += bflb_ef_ctrl_get_byte_zero_cnt(mac[i]);
225     }
226 
227     tmpval |= ((cnt & 0x3f) << 16);
228 
229     if (slot == 0) {
230         bflb_ef_ctrl_write_direct(NULL, EF_DATA_EF_WIFI_MAC_HIGH_OFFSET, &tmpval, 1, program);
231     } else if (slot == 1) {
232         bflb_ef_ctrl_write_direct(NULL, EF_DATA_EF_KEY_SLOT_5_W1_OFFSET, &tmpval, 1, program);
233     } else if (slot == 2) {
234         bflb_ef_ctrl_write_direct(NULL, EF_DATA_EF_DBG_PWD_HIGH_OFFSET, &tmpval, 1, program);
235     }
236 
237     return 0;
238 }
239 
240 /****************************************************************************/ /**
241  * @brief  Efuse read optional MAC address
242  *
243  * @param  slot: MAC address slot
244  * @param  mac[6]: MAC address buffer
245  * @param  reload: Whether reload
246  *
247  * @return 0 or -1
248  *
249 *******************************************************************************/
bflb_efuse_read_mac_address_opt(uint8_t slot,uint8_t mac[6],uint8_t reload)250 int bflb_efuse_read_mac_address_opt(uint8_t slot, uint8_t mac[6], uint8_t reload)
251 {
252     uint8_t *maclow = (uint8_t *)mac;
253     uint8_t *machigh = (uint8_t *)(mac + 4);
254     uint32_t tmpval = 0;
255     uint32_t i = 0;
256     uint32_t cnt = 0;
257 
258     if (slot >= 3) {
259         return -1;
260     }
261 
262     if (slot == 0) {
263         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_WIFI_MAC_LOW_OFFSET, &tmpval, 1, reload);
264     } else if (slot == 1) {
265         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_KEY_SLOT_5_W0_OFFSET, &tmpval, 1, reload);
266     } else if (slot == 2) {
267         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_DBG_PWD_LOW_OFFSET, &tmpval, 1, reload);
268     }
269 
270     BL_WRWD_TO_BYTEP(maclow, tmpval);
271 
272     if (slot == 0) {
273         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_WIFI_MAC_HIGH_OFFSET, &tmpval, 1, reload);
274     } else if (slot == 1) {
275         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_KEY_SLOT_5_W1_OFFSET, &tmpval, 1, reload);
276     } else if (slot == 2) {
277         bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_DBG_PWD_HIGH_OFFSET, &tmpval, 1, reload);
278     }
279 
280     machigh[0] = tmpval & 0xff;
281     machigh[1] = (tmpval >> 8) & 0xff;
282 
283     /* Check parity */
284     for (i = 0; i < 6; i++) {
285         cnt += bflb_ef_ctrl_get_byte_zero_cnt(mac[i]);
286     }
287 
288     if ((cnt & 0x3f) == ((tmpval >> 16) & 0x3f)) {
289         /* Change to network order */
290         for (i = 0; i < 3; i++) {
291             tmpval = mac[i];
292             mac[i] = mac[5 - i];
293             mac[5 - i] = tmpval;
294         }
295         return 0;
296     } else {
297         return -1;
298     }
299 }
300 
bflb_efuse_get_adc_trim(void)301 float bflb_efuse_get_adc_trim(void)
302 {
303     bflb_ef_ctrl_com_trim_t trim;
304     uint32_t tmp;
305 
306     float coe = 1.0;
307 
308     bflb_ef_ctrl_read_common_trim(NULL, "gpadc_gain", &trim, 1);
309 
310     if (trim.en) {
311         if (trim.parity == bflb_ef_ctrl_get_trim_parity(trim.value, trim.len)) {
312             tmp = trim.value;
313 
314             if (tmp & 0x800) {
315                 tmp = ~tmp;
316                 tmp += 1;
317                 tmp = tmp & 0xfff;
318                 coe = (1.0 + ((float)tmp / 2048.0));
319             } else {
320                 coe = (1.0 - ((float)tmp / 2048.0));
321             }
322         }
323     }
324 
325     return coe;
326 }
327 
bflb_efuse_get_adc_tsen_trim(void)328 uint32_t bflb_efuse_get_adc_tsen_trim(void)
329 {
330     bflb_ef_ctrl_com_trim_t trim;
331 
332     bflb_ef_ctrl_read_common_trim(NULL, "tsen", &trim, 1);
333     if (trim.en) {
334         if (trim.parity == bflb_ef_ctrl_get_trim_parity(trim.value, trim.len)) {
335             return trim.value;
336         }
337     }
338 
339     return 2042;
340 }
341 
bflb_efuse_read_secure_boot(uint8_t * sign,uint8_t * aes)342 void bflb_efuse_read_secure_boot(uint8_t *sign, uint8_t *aes)
343 {
344     uint32_t tmpval = 0;
345 
346     bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_CFG_0_OFFSET, &tmpval, 1, 1);
347     *sign = ((tmpval & EF_DATA_EF_SBOOT_SIGN_MODE_MSK) >> EF_DATA_EF_SBOOT_SIGN_MODE_POS) & 0x01;
348     *aes = ((tmpval & EF_DATA_EF_SF_AES_MODE_MSK) >> EF_DATA_EF_SF_AES_MODE_POS);
349 }
350 
bflb_efuse_write_aes_key(uint8_t index,uint8_t * data,uint32_t len)351 void bflb_efuse_write_aes_key(uint8_t index, uint8_t *data, uint32_t len)
352 {
353     if (index > 5) {
354         return;
355     }
356 
357     bflb_ef_ctrl_write_direct(NULL, 0x1C + index * 4, (uint32_t *)data, len, 1);
358 }
359 
bflb_efuse_read_aes_key(uint8_t index,uint8_t * data,uint32_t len)360 void bflb_efuse_read_aes_key(uint8_t index, uint8_t *data, uint32_t len)
361 {
362     if (index > 5) {
363         return;
364     }
365 
366     bflb_ef_ctrl_read_direct(NULL, 0x1C + index * 4, (uint32_t *)data, len, 1);
367 }
368 
bflb_efuse_lock_aes_key_write(uint8_t index)369 void bflb_efuse_lock_aes_key_write(uint8_t index)
370 {
371     uint32_t lock = 0;
372 
373     if (index > 5) {
374         return;
375     }
376     /* write lock */
377     if (index <= 3) {
378         lock |= (1 << (index + 19));
379     } else {
380         lock |= (1 << (index + 19));
381         lock |= (1 << (index - 4 + 13));
382     }
383     bflb_ef_ctrl_write_direct(NULL, 0x7c, &lock, 1, 1);
384 }
385 
bflb_efuse_lock_aes_key_read(uint8_t index)386 void bflb_efuse_lock_aes_key_read(uint8_t index)
387 {
388     uint32_t lock = 0;
389 
390     if (index > 5) {
391         return;
392     }
393     /* read lock */
394     lock |= (1 << (index + 26));
395 
396     bflb_ef_ctrl_write_direct(NULL, 0x7c, &lock, 1, 1);
397 }
398 
bflb_efuse_write_sw_usage(uint32_t index,uint32_t usage,uint8_t program)399 void bflb_efuse_write_sw_usage(uint32_t index, uint32_t usage, uint8_t program)
400 {
401     if (index != 0) {
402         return;
403     }
404     bflb_ef_ctrl_write_direct(NULL, EF_DATA_EF_SW_USAGE_0_OFFSET + index * 4, &usage, 1, program);
405 }
406 
bflb_efuse_read_sw_usage(uint32_t index,uint32_t * usage)407 void bflb_efuse_read_sw_usage(uint32_t index, uint32_t *usage)
408 {
409     if (index != 0) {
410         return;
411     }
412     bflb_ef_ctrl_read_direct(NULL, EF_DATA_EF_SW_USAGE_0_OFFSET + index * 4, (uint32_t *)usage, 1, 1);
413 }