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