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