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>© 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 }