1 #include "bflb_ef_ctrl.h"
2 #include "include/hardware/ef_ctrl_reg.h"
3
4 #if defined(BL602) || defined(BL702) || defined(BL702L)
5 #define BFLB_EF_CTRL_BASE ((uint32_t)0x40007000)
6 #elif defined(BL616) || defined(BL808) || defined(BL606P)
7 #define BFLB_EF_CTRL_BASE ((uint32_t)0x20056000)
8 #elif defined(BL628)
9 #define BFLB_EF_CTRL_BASE ((uint32_t)0x2000C000)
10 #endif
11
12 #define EF_CTRL_EFUSE_CYCLE_PROTECT (0xbf << 24)
13 #define EF_CTRL_EFUSE_CTRL_PROTECT (0xbf << 8)
14 #define EF_CTRL_OP_MODE_AUTO 0
15 #define EF_CTRL_PARA_DFT 0
16 #if defined(BL702) || defined(BL602) || defined(BL702L)
17 #define EF_CTRL_EF_CLK 0
18 #define EF_CTRL_SAHB_CLK 1
19 #endif
20 #define EF_CTRL_DFT_TIMEOUT_VAL (160 * 1000)
21
22 #if defined(BL702) || defined(BL602) || defined(BL702L)
23 #define EF_CTRL_EFUSE_R0_SIZE 128
24 #elif defined(BL606P) || defined(BL808)
25 #define EF_CTRL_EFUSE_R0_SIZE 128
26 #define EF_CTRL_EFUSE_R1_SIZE 128
27 #elif defined(BL616) || defined(BL628)
28 #define EF_CTRL_EFUSE_R0_SIZE 512
29 #else
30 #define EF_CTRL_EFUSE_R0_SIZE 128
31 #endif
32
33 #ifndef BOOTROM
34 #define EF_CTRL_LOAD_BEFORE_READ_R0 bflb_ef_ctrl_load_efuse_r0(dev)
35 #define EF_CTRL_LOAD_BEFORE_READ_R1 bflb_ef_ctrl_load_efuse_r1(dev)
36 #else
37 #define EF_CTRL_LOAD_BEFORE_READ_R0
38 #define EF_CTRL_LOAD_BEFORE_READ_R1
39 #endif
40 #define EF_CTRL_DATA0_CLEAR bflb_ef_ctrl_clear_data_reg0(dev)
41 #define EF_CTRL_DATA1_CLEAR bflb_ef_ctrl_clear_data_reg1(dev)
42
43 static int ATTR_TCM_SECTION bflb_ef_ctrl_busy(struct bflb_device_s *dev);
44 #if defined(BL702) || defined(BL602) || defined(BL702L)
45 extern void bflb_efuse_switch_cpu_clock_save(void);
46 extern void bflb_efuse_switch_cpu_clock_restore(void);
47 #endif
48
49
50 /****************************************************************************/ /**
51 * @brief Switch efuse region 0 control to AHB clock
52 *
53 * @param dev ef control device pointer
54 *
55 * @return None
56 *
57 *******************************************************************************/
bflb_ef_ctrl_switch_ahb_clk_r0(struct bflb_device_s * dev)58 static void ATTR_TCM_SECTION bflb_ef_ctrl_switch_ahb_clk_r0(struct bflb_device_s *dev)
59 {
60 uint32_t reg_val;
61 uint32_t timeout = EF_CTRL_DFT_TIMEOUT_VAL;
62
63 while (bflb_ef_ctrl_busy(dev) == 1) {
64 timeout--;
65 if (timeout == 0) {
66 break;
67 }
68 }
69
70 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
71 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_0_MANUAL_EN_POS) |
72 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_0_CYC_MODIFY_POS) |
73 #if defined(BL702) || defined(BL602) || defined(BL702L)
74 (EF_CTRL_SAHB_CLK << EF_CTRL_EF_CLK_SAHB_DATA_SEL_POS) |
75 #endif
76 (1 << EF_CTRL_EF_IF_AUTO_RD_EN_POS) |
77 (0 << EF_CTRL_EF_IF_POR_DIG_POS) |
78 (1 << EF_CTRL_EF_IF_0_INT_CLR_POS) |
79 (0 << EF_CTRL_EF_IF_0_RW_POS) |
80 (0 << EF_CTRL_EF_IF_0_TRIG_POS);
81
82 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_0_OFFSET);
83
84 /* Add delay for CLK to be stable */
85 arch_delay_us(4);
86 }
87
88 /****************************************************************************/ /**
89 * @brief Switch efuse region 1 control to AHB clock
90 *
91 * @param dev ef control device pointer
92 *
93 * @return None
94 *
95 *******************************************************************************/
96 #ifdef EF_CTRL_EFUSE_R1_SIZE
bflb_ef_ctrl_switch_ahb_clk_r1(struct bflb_device_s * dev)97 static void ATTR_TCM_SECTION bflb_ef_ctrl_switch_ahb_clk_r1(struct bflb_device_s *dev)
98 {
99 uint32_t reg_val;
100 uint32_t timeout = EF_CTRL_DFT_TIMEOUT_VAL;
101
102 while (bflb_ef_ctrl_busy(dev) == 1) {
103 timeout--;
104 if (timeout == 0) {
105 break;
106 }
107 }
108
109 /* Note:ef_if_ctrl_1 has no EF_CTRL_EF_CLK_SAHB_DATA_SEL_POS bit as ef_if_ctrl_0,
110 so we select it(them) in ef_if_ctrl_0 */
111 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
112 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_0_MANUAL_EN_POS) |
113 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_0_CYC_MODIFY_POS) |
114 (1 << EF_CTRL_EF_IF_AUTO_RD_EN_POS) |
115 (0 << EF_CTRL_EF_IF_POR_DIG_POS) |
116 (1 << EF_CTRL_EF_IF_0_INT_CLR_POS) |
117 (0 << EF_CTRL_EF_IF_0_RW_POS) |
118 (0 << EF_CTRL_EF_IF_0_TRIG_POS);
119
120 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_0_OFFSET);
121
122 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
123 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_1_MANUAL_EN_POS) |
124 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_1_CYC_MODIFY_POS) |
125 (1 << EF_CTRL_EF_IF_1_INT_CLR_POS) |
126 (0 << EF_CTRL_EF_IF_1_RW_POS) |
127 (0 << EF_CTRL_EF_IF_1_TRIG_POS);
128
129 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_1_OFFSET);
130
131 /* Add delay for CLK to be stable */
132 arch_delay_us(4);
133 }
134 #endif
135
136 /****************************************************************************/ /**
137 * @brief Program efuse region 0
138 *
139 * @param dev ef control device pointer
140 *
141 * @return None
142 *
143 *******************************************************************************/
bflb_ef_ctrl_program_efuse_r0(struct bflb_device_s * dev)144 static void ATTR_TCM_SECTION bflb_ef_ctrl_program_efuse_r0(struct bflb_device_s *dev)
145 {
146 uint32_t reg_val;
147
148 /* Select auto mode and select ef clock */
149 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
150 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_0_MANUAL_EN_POS) |
151 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_0_CYC_MODIFY_POS) |
152 #if defined(BL702) || defined(BL602) || defined(BL702L)
153 (EF_CTRL_EF_CLK << EF_CTRL_EF_CLK_SAHB_DATA_SEL_POS) |
154 #endif
155 (1 << EF_CTRL_EF_IF_AUTO_RD_EN_POS) |
156 (0 << EF_CTRL_EF_IF_POR_DIG_POS) |
157 (1 << EF_CTRL_EF_IF_0_INT_CLR_POS) |
158 (0 << EF_CTRL_EF_IF_0_RW_POS) |
159 (0 << EF_CTRL_EF_IF_0_TRIG_POS);
160
161 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_0_OFFSET);
162
163 /* Program */
164 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
165 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_0_MANUAL_EN_POS) |
166 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_0_CYC_MODIFY_POS) |
167 #if defined(BL702) || defined(BL602) || defined(BL702L)
168 (EF_CTRL_EF_CLK << EF_CTRL_EF_CLK_SAHB_DATA_SEL_POS) |
169 #endif
170 (1 << EF_CTRL_EF_IF_AUTO_RD_EN_POS) |
171 (1 << EF_CTRL_EF_IF_POR_DIG_POS) |
172 (1 << EF_CTRL_EF_IF_0_INT_CLR_POS) |
173 (1 << EF_CTRL_EF_IF_0_RW_POS) |
174 (0 << EF_CTRL_EF_IF_0_TRIG_POS);
175
176 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_0_OFFSET);
177
178 /* Add delay for POR to be stable */
179 arch_delay_us(4);
180
181 /* Trigger */
182 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
183 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_0_MANUAL_EN_POS) |
184 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_0_CYC_MODIFY_POS) |
185 #if defined(BL702) || defined(BL602) || defined(BL702L)
186 (EF_CTRL_EF_CLK << EF_CTRL_EF_CLK_SAHB_DATA_SEL_POS) |
187 #endif
188 (1 << EF_CTRL_EF_IF_AUTO_RD_EN_POS) |
189 (1 << EF_CTRL_EF_IF_POR_DIG_POS) |
190 (1 << EF_CTRL_EF_IF_0_INT_CLR_POS) |
191 (1 << EF_CTRL_EF_IF_0_RW_POS) |
192 (1 << EF_CTRL_EF_IF_0_TRIG_POS);
193
194 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_0_OFFSET);
195 }
196
197 /****************************************************************************/ /**
198 * @brief Program efuse region 1
199 *
200 * @param dev ef control device pointer
201 *
202 * @return None
203 *
204 *******************************************************************************/
205 #ifdef EF_CTRL_EFUSE_R1_SIZE
bflb_ef_ctrl_program_efuse_r1(struct bflb_device_s * dev)206 static void ATTR_TCM_SECTION bflb_ef_ctrl_program_efuse_r1(struct bflb_device_s *dev)
207 {
208 uint32_t reg_val;
209
210 /* Select auto mode and select ef clock */
211 /* Note:ef_if_ctrl_1 has no EF_CTRL_EF_CLK_SAHB_DATA_SEL_POS bit as ef_if_ctrl_0,
212 so we select it(them) in ef_if_ctrl_0 */
213 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
214 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_0_MANUAL_EN_POS) |
215 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_0_CYC_MODIFY_POS) |
216 (1 << EF_CTRL_EF_IF_AUTO_RD_EN_POS) |
217 (0 << EF_CTRL_EF_IF_POR_DIG_POS) |
218 (1 << EF_CTRL_EF_IF_0_INT_CLR_POS) |
219 (0 << EF_CTRL_EF_IF_0_RW_POS) |
220 (0 << EF_CTRL_EF_IF_0_TRIG_POS);
221
222 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_0_OFFSET);
223
224 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
225 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_1_MANUAL_EN_POS) |
226 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_1_CYC_MODIFY_POS) |
227 (1 << EF_CTRL_EF_IF_1_INT_CLR_POS) |
228 (0 << EF_CTRL_EF_IF_1_RW_POS) |
229 (0 << EF_CTRL_EF_IF_1_TRIG_POS);
230
231 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_1_OFFSET);
232
233 /* Program */
234 /* Note:ef_if_ctrl_1 has no EF_CTRL_EF_CLK_SAHB_DATA_SEL_POS bit as ef_if_ctrl_0,
235 so we select it(them) in ef_if_ctrl_0 */
236 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
237 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_0_MANUAL_EN_POS) |
238 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_0_CYC_MODIFY_POS) |
239 (1 << EF_CTRL_EF_IF_AUTO_RD_EN_POS) |
240 (1 << EF_CTRL_EF_IF_POR_DIG_POS) |
241 (1 << EF_CTRL_EF_IF_0_INT_CLR_POS) |
242 (0 << EF_CTRL_EF_IF_0_RW_POS) |
243 (0 << EF_CTRL_EF_IF_0_TRIG_POS);
244
245 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_0_OFFSET);
246
247 /* Add delay for POR to be stable */
248 arch_delay_us(4);
249
250 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
251 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_1_MANUAL_EN_POS) |
252 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_1_CYC_MODIFY_POS) |
253 (1 << EF_CTRL_EF_IF_1_INT_CLR_POS) |
254 (1 << EF_CTRL_EF_IF_1_RW_POS) |
255 (0 << EF_CTRL_EF_IF_1_TRIG_POS);
256
257 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_1_OFFSET);
258
259 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
260 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_1_MANUAL_EN_POS) |
261 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_1_CYC_MODIFY_POS) |
262 (1 << EF_CTRL_EF_IF_1_INT_CLR_POS) |
263 (1 << EF_CTRL_EF_IF_1_RW_POS) |
264 (1 << EF_CTRL_EF_IF_1_TRIG_POS);
265
266 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_1_OFFSET);
267 }
268 #endif
269
270 /****************************************************************************/ /**
271 * @brief Clear efuse region 0 data register
272 *
273 * @param dev ef control device pointer
274 *
275 * @return None
276 *
277 *******************************************************************************/
bflb_ef_ctrl_clear_data_reg0(struct bflb_device_s * dev)278 static void ATTR_TCM_SECTION bflb_ef_ctrl_clear_data_reg0(struct bflb_device_s *dev)
279 {
280 uint32_t *pefuse_start = (uint32_t *)(BFLB_EF_CTRL_BASE + 0x00);
281 uint32_t i = 0;
282
283 /* Switch to AHB clock */
284 bflb_ef_ctrl_switch_ahb_clk_r0(dev);
285
286 /* Clear data */
287 for (i = 0; i < EF_CTRL_EFUSE_R0_SIZE / 4; i++) {
288 pefuse_start[i] = 0;
289 }
290 }
291
292 /****************************************************************************/ /**
293 * @brief Clear efuse region 1 data register
294 *
295 * @param dev ef control device pointer
296 *
297 * @return None
298 *
299 *******************************************************************************/
300 #ifdef EF_CTRL_EFUSE_R1_SIZE
bflb_ef_ctrl_clear_data_reg1(struct bflb_device_s * dev)301 static void ATTR_TCM_SECTION bflb_ef_ctrl_clear_data_reg1(struct bflb_device_s *dev)
302 {
303 uint32_t *pefuse_start = (uint32_t *)(BFLB_EF_CTRL_BASE + EF_CTRL_EFUSE_R0_SIZE);
304 uint32_t i = 0;
305
306 /* Switch to AHB clock */
307 bflb_ef_ctrl_switch_ahb_clk_r1(dev);
308
309 /* Clear data */
310 for (i = 0; i < EF_CTRL_EFUSE_R1_SIZE / 4; i++) {
311 pefuse_start[i] = 0;
312 }
313 }
314 #endif
315
316 /****************************************************************************/ /**
317 * @brief Load efuse region 0
318 *
319 * @param dev ef control device pointer
320 *
321 * @return None
322 *
323 *******************************************************************************/
bflb_ef_ctrl_load_efuse_r0(struct bflb_device_s * dev)324 static void ATTR_TCM_SECTION bflb_ef_ctrl_load_efuse_r0(struct bflb_device_s *dev)
325 {
326 uint32_t reg_val;
327 uint32_t timeout = EF_CTRL_DFT_TIMEOUT_VAL;
328
329 EF_CTRL_DATA0_CLEAR;
330
331 /* Trigger read */
332 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
333 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_0_MANUAL_EN_POS) |
334 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_0_CYC_MODIFY_POS) |
335 #if defined(BL702) || defined(BL602) || defined(BL702L)
336 (EF_CTRL_EF_CLK << EF_CTRL_EF_CLK_SAHB_DATA_SEL_POS) |
337 #endif
338 (1 << EF_CTRL_EF_IF_AUTO_RD_EN_POS) |
339 (0 << EF_CTRL_EF_IF_POR_DIG_POS) |
340 (1 << EF_CTRL_EF_IF_0_INT_CLR_POS) |
341 (0 << EF_CTRL_EF_IF_0_RW_POS) |
342 (0 << EF_CTRL_EF_IF_0_TRIG_POS);
343
344 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_0_OFFSET);
345
346 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
347 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_0_MANUAL_EN_POS) |
348 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_0_CYC_MODIFY_POS) |
349 #if defined(BL702) || defined(BL602) || defined(BL702L)
350 (EF_CTRL_EF_CLK << EF_CTRL_EF_CLK_SAHB_DATA_SEL_POS) |
351 #endif
352 (1 << EF_CTRL_EF_IF_AUTO_RD_EN_POS) |
353 (0 << EF_CTRL_EF_IF_POR_DIG_POS) |
354 (1 << EF_CTRL_EF_IF_0_INT_CLR_POS) |
355 (0 << EF_CTRL_EF_IF_0_RW_POS) |
356 (1 << EF_CTRL_EF_IF_0_TRIG_POS);
357
358 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_0_OFFSET);
359
360 arch_delay_us(10);
361
362 /* Wait for efuse control idle */
363 do {
364 reg_val = getreg32(BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_0_OFFSET);
365 timeout--;
366
367 if (timeout == 0) {
368 break;
369 }
370 } while ((reg_val & EF_CTRL_EF_IF_0_BUSY_MASK) || (!(reg_val & EF_CTRL_EF_IF_0_AUTOLOAD_DONE_MASK)));
371
372 /* Switch to AHB clock */
373 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
374 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_0_MANUAL_EN_POS) |
375 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_0_CYC_MODIFY_POS) |
376 #if defined(BL702) || defined(BL602) || defined(BL702L)
377 (EF_CTRL_EF_CLK << EF_CTRL_EF_CLK_SAHB_DATA_SEL_POS) |
378 #endif
379 (1 << EF_CTRL_EF_IF_AUTO_RD_EN_POS) |
380 (0 << EF_CTRL_EF_IF_POR_DIG_POS) |
381 (1 << EF_CTRL_EF_IF_0_INT_CLR_POS) |
382 (0 << EF_CTRL_EF_IF_0_RW_POS) |
383 (0 << EF_CTRL_EF_IF_0_TRIG_POS);
384
385 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_0_OFFSET);
386 }
387
388 /****************************************************************************/ /**
389 * @brief Load efuse region 0
390 *
391 * @param dev ef control device pointer
392 *
393 * @return None
394 *
395 *******************************************************************************/
396 #ifdef EF_CTRL_EFUSE_R1_SIZE
bflb_ef_ctrl_load_efuse_r1(struct bflb_device_s * dev)397 static void ATTR_TCM_SECTION bflb_ef_ctrl_load_efuse_r1(struct bflb_device_s *dev)
398 {
399 uint32_t reg_val;
400
401 EF_CTRL_DATA1_CLEAR;
402
403 /* Trigger read */
404 /* Note:ef_if_ctrl_1 has no EF_CTRL_EF_CLK_SAHB_DATA_SEL_POS bit as ef_if_ctrl_0,
405 so we select it(them) in ef_if_ctrl_0 */
406 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
407 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_0_MANUAL_EN_POS) |
408 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_0_CYC_MODIFY_POS) |
409 (1 << EF_CTRL_EF_IF_AUTO_RD_EN_POS) |
410 (0 << EF_CTRL_EF_IF_POR_DIG_POS) |
411 (1 << EF_CTRL_EF_IF_0_INT_CLR_POS) |
412 (0 << EF_CTRL_EF_IF_0_RW_POS) |
413 (0 << EF_CTRL_EF_IF_0_TRIG_POS);
414
415 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_0_OFFSET);
416
417 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
418 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_1_MANUAL_EN_POS) |
419 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_1_CYC_MODIFY_POS) |
420 (1 << EF_CTRL_EF_IF_1_INT_CLR_POS) |
421 (0 << EF_CTRL_EF_IF_1_RW_POS) |
422 (0 << EF_CTRL_EF_IF_1_TRIG_POS);
423
424 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_1_OFFSET);
425
426 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
427 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_1_MANUAL_EN_POS) |
428 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_1_CYC_MODIFY_POS) |
429 (1 << EF_CTRL_EF_IF_1_INT_CLR_POS) |
430 (0 << EF_CTRL_EF_IF_1_RW_POS) |
431 (1 << EF_CTRL_EF_IF_1_TRIG_POS);
432
433 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_1_OFFSET);
434
435 arch_delay_us(10);
436
437 /* Wait for efuse control idle */
438 do {
439 reg_val = getreg32(BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_1_OFFSET);
440 } while (reg_val & EF_CTRL_EF_IF_1_BUSY_MASK);
441
442 do {
443 reg_val = getreg32(BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_0_OFFSET);
444 } while (!(reg_val & EF_CTRL_EF_IF_0_AUTOLOAD_DONE_MASK));
445
446 /* Switch to AHB clock since often read efuse data after load */
447 /* Note:ef_if_ctrl_1 has no EF_CTRL_EF_CLK_SAHB_DATA_SEL_POS bit as ef_if_ctrl_0,
448 so we select it(them) in ef_if_ctrl_0 */
449 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
450 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_0_MANUAL_EN_POS) |
451 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_0_CYC_MODIFY_POS) |
452 (1 << EF_CTRL_EF_IF_AUTO_RD_EN_POS) |
453 (0 << EF_CTRL_EF_IF_POR_DIG_POS) |
454 (1 << EF_CTRL_EF_IF_0_INT_CLR_POS) |
455 (0 << EF_CTRL_EF_IF_0_RW_POS) |
456 (0 << EF_CTRL_EF_IF_0_TRIG_POS);
457
458 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_0_OFFSET);
459
460 reg_val = (EF_CTRL_EFUSE_CTRL_PROTECT) |
461 (EF_CTRL_OP_MODE_AUTO << EF_CTRL_EF_IF_1_MANUAL_EN_POS) |
462 (EF_CTRL_PARA_DFT << EF_CTRL_EF_IF_1_CYC_MODIFY_POS) |
463 (1 << EF_CTRL_EF_IF_1_INT_CLR_POS) |
464 (0 << EF_CTRL_EF_IF_1_RW_POS) |
465 (0 << EF_CTRL_EF_IF_1_TRIG_POS);
466
467 putreg32(reg_val, BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_1_OFFSET);
468 }
469 #endif
470
471 /****************************************************************************/ /**
472 * @brief Check efuse busy status
473 *
474 * @param dev ef control device pointer
475 *
476 * @return 1 for busy 0 for not
477 *
478 *******************************************************************************/
bflb_ef_ctrl_busy(struct bflb_device_s * dev)479 static int ATTR_TCM_SECTION bflb_ef_ctrl_busy(struct bflb_device_s *dev)
480 {
481 uint32_t reg_val;
482
483 reg_val = getreg32(BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_0_OFFSET);
484
485 if (reg_val & EF_CTRL_EF_IF_0_BUSY_MASK) {
486 return 1;
487 }
488
489 return 0;
490 }
491
492 /****************************************************************************/ /**
493 * @brief Check efuse auto load done
494 *
495 * @param dev ef control device pointer
496 *
497 * @return 1 for auto load done 0 for not
498 *
499 *******************************************************************************/
bflb_ef_ctrl_autoload_done(struct bflb_device_s * dev)500 int ATTR_TCM_SECTION bflb_ef_ctrl_autoload_done(struct bflb_device_s *dev)
501 {
502 uint32_t reg_val;
503
504 // if (dev == NULL) {
505 // dev = bflb_device_get_by_name("ef_ctrl");
506 // }
507
508 /* Switch to AHB clock */
509 bflb_ef_ctrl_switch_ahb_clk_r0(dev);
510
511 reg_val = getreg32(BFLB_EF_CTRL_BASE + EF_CTRL_EF_IF_CTRL_0_OFFSET);
512
513 if (reg_val & EF_CTRL_EF_IF_0_AUTOLOAD_DONE_MASK) {
514 return 1;
515 }
516
517 return 0;
518 }
519
520 /****************************************************************************/ /**
521 * @brief write data to efuse
522 *
523 * @param dev ef control device pointer
524 * @param offset: offset of efuse address to write
525 * @param pword: data pointer to buffer which is aligned to word
526 * @param count: count of data in words to write
527 * @param program: 1 for program to efuse,0 for not program now
528 *
529 * @return None
530 *
531 *******************************************************************************/
bflb_ef_ctrl_write_direct(struct bflb_device_s * dev,uint32_t offset,uint32_t * pword,uint32_t count,uint8_t program)532 void ATTR_TCM_SECTION bflb_ef_ctrl_write_direct(struct bflb_device_s *dev, uint32_t offset, uint32_t *pword, uint32_t count, uint8_t program)
533 {
534 uint32_t *pefuse_start = NULL;
535 uint32_t region0_count = 0, region1_count = 0;
536 uint32_t total_size = EF_CTRL_EFUSE_R0_SIZE;
537 uintptr_t irq_stat;
538
539 #ifdef EF_CTRL_EFUSE_R1_SIZE
540 total_size += EF_CTRL_EFUSE_R1_SIZE;
541 #else
542 (void)region1_count;
543 #endif
544
545 if (offset > total_size || (offset + count * 4) > total_size || pword == NULL) {
546 return;
547 }
548
549 if (offset < EF_CTRL_EFUSE_R0_SIZE) {
550 if (offset + count * 4 <= EF_CTRL_EFUSE_R0_SIZE) {
551 region0_count = count;
552 } else {
553 region0_count = (EF_CTRL_EFUSE_R0_SIZE - offset) / 4;
554 region1_count = (offset + count * 4 - EF_CTRL_EFUSE_R0_SIZE) / 4;
555 }
556 } else {
557 region1_count = count;
558 }
559
560 // if (dev == NULL) {
561 // dev = bflb_device_get_by_name("ef_ctrl");
562 // }
563 pefuse_start = (uint32_t *)(BFLB_EF_CTRL_BASE + offset);
564
565 irq_stat = bflb_irq_save();
566 #if defined(BL702) || defined(BL602) || defined(BL702L)
567 bflb_efuse_switch_cpu_clock_save();
568 #endif
569 if (region0_count > 0) {
570 /* Switch to AHB clock */
571 bflb_ef_ctrl_switch_ahb_clk_r0(dev);
572
573 arch_memcpy4(pefuse_start, pword, region0_count);
574 pefuse_start += region0_count;
575 pword += region0_count;
576
577 if (program) {
578 bflb_ef_ctrl_program_efuse_r0(dev);
579 arch_delay_us(100);
580 }
581 }
582 #ifdef EF_CTRL_EFUSE_R1_SIZE
583 if (region1_count > 0) {
584 /* Switch to AHB clock */
585 bflb_ef_ctrl_switch_ahb_clk_r1(dev);
586
587 /* Add delay for CLK to be stable */
588 arch_delay_us(4);
589
590 arch_memcpy4(pefuse_start, pword, region1_count);
591
592 if (program) {
593 bflb_ef_ctrl_program_efuse_r1(dev);
594 arch_delay_us(100);
595 }
596 }
597 #endif
598 #if defined(BL702) || defined(BL602) || defined(BL702L)
599 bflb_efuse_switch_cpu_clock_restore();
600 #endif
601
602 bflb_irq_restore(irq_stat);
603 }
604
605 /****************************************************************************/ /**
606 * @brief Read data from efuse
607 *
608 * @param dev ef control device pointer
609 * @param offset: offset of efuse address to read
610 * @param pword: data pointer to buffer which is aligned to word
611 * @param count: count of data in words to read
612 * @param reload: 1 for reload before read,0 for not
613 *
614 * @return None
615 *
616 *******************************************************************************/
bflb_ef_ctrl_read_direct(struct bflb_device_s * dev,uint32_t offset,uint32_t * pword,uint32_t count,uint8_t reload)617 void ATTR_TCM_SECTION bflb_ef_ctrl_read_direct(struct bflb_device_s *dev, uint32_t offset, uint32_t *pword, uint32_t count, uint8_t reload)
618 {
619 uint32_t *pefuse_start = NULL;
620 uint32_t region0_count = 0, region1_count = 0;
621 uint32_t total_size = EF_CTRL_EFUSE_R0_SIZE;
622 uintptr_t irq_stat;
623
624 #ifdef EF_CTRL_EFUSE_R1_SIZE
625 total_size += EF_CTRL_EFUSE_R1_SIZE;
626 #else
627 (void)region1_count;
628 #endif
629
630 if (offset > total_size || (offset + count * 4) > total_size || pword == NULL) {
631 return;
632 }
633
634 if (offset < EF_CTRL_EFUSE_R0_SIZE) {
635 if (offset + count * 4 <= EF_CTRL_EFUSE_R0_SIZE) {
636 region0_count = count;
637 } else {
638 region0_count = (EF_CTRL_EFUSE_R0_SIZE - offset) / 4;
639 region1_count = (offset + count * 4 - EF_CTRL_EFUSE_R0_SIZE) / 4;
640 }
641 } else {
642 region1_count = count;
643 }
644
645 // if (dev == NULL) {
646 // dev = bflb_device_get_by_name("ef_ctrl");
647 // }
648 pefuse_start = (uint32_t *)(BFLB_EF_CTRL_BASE + offset);
649
650 irq_stat = bflb_irq_save();
651 #if defined(BL702) || defined(BL602) || defined(BL702L)
652 bflb_efuse_switch_cpu_clock_save();
653 #endif
654 if (region0_count > 0) {
655 if (reload) {
656 bflb_ef_ctrl_load_efuse_r0(dev);
657 } else {
658 bflb_ef_ctrl_switch_ahb_clk_r0(dev);
659 }
660 arch_memcpy4(pword, pefuse_start, region0_count);
661 pword += region0_count;
662 pefuse_start += region0_count;
663 }
664 #ifdef EF_CTRL_EFUSE_R1_SIZE
665 if (region1_count > 0) {
666 if (reload) {
667 bflb_ef_ctrl_load_efuse_r1(dev);
668 } else {
669 bflb_ef_ctrl_switch_ahb_clk_r1(dev);
670 }
671 arch_memcpy4(pword, pefuse_start, region0_count);
672 }
673 #endif
674
675 #if defined(BL702) || defined(BL602) || defined(BL702L)
676 bflb_efuse_switch_cpu_clock_restore();
677 #endif
678
679 bflb_irq_restore(irq_stat);
680 }
681
682 /****************************************************************************/ /**
683 * @brief Efuse read common trim value
684 *
685 * @param dev ef control device pointer
686 * @param name: Trim name
687 * @param trim: Trim data pointer
688 * @param reload: Reload efuse data before read
689 * @return None
690 *
691 *******************************************************************************/
bflb_ef_ctrl_read_common_trim(struct bflb_device_s * dev,char * name,bflb_ef_ctrl_com_trim_t * trim,uint8_t reload)692 void ATTR_TCM_SECTION bflb_ef_ctrl_read_common_trim(struct bflb_device_s *dev, char *name, bflb_ef_ctrl_com_trim_t *trim, uint8_t reload)
693 {
694 uint32_t reg_val;
695 uint32_t i = 0;
696 const bflb_ef_ctrl_com_trim_cfg_t *trim_list = NULL;
697 uint32_t trim_list_len;
698 uintptr_t irq_stat;
699
700 // if (dev == NULL) {
701 // dev = bflb_device_get_by_name("ef_ctrl");
702 // }
703
704 irq_stat = bflb_irq_save();
705 #if defined(BL702) || defined(BL602) || defined(BL702L)
706 bflb_efuse_switch_cpu_clock_save();
707 #endif
708 if (reload) {
709 /* Trigger read data from efuse */
710 bflb_ef_ctrl_load_efuse_r0(dev);
711 #ifdef EF_CTRL_EFUSE_R1_SIZE
712 bflb_ef_ctrl_load_efuse_r1(dev);
713 #endif
714 }
715
716 trim->en = 0;
717 trim->parity = 0;
718 trim->empty = 1;
719 trim->len = 0;
720
721 trim_list_len = bflb_ef_ctrl_get_common_trim_list(&trim_list);
722
723 for (i = 0; i < trim_list_len; i++) {
724 if (arch_memcmp(name, trim_list[i].name, strlen(name)) == 0) {
725 /* switch clock */
726 if (trim_list[i].en_addr <= EF_CTRL_EFUSE_R0_SIZE) {
727 /* Switch to AHB clock */
728 bflb_ef_ctrl_switch_ahb_clk_r0(dev);
729 }
730 #ifdef EF_CTRL_EFUSE_R1_SIZE
731 if (trim_list[i].en_addr > EF_CTRL_EFUSE_R0_SIZE) {
732 /* Switch to AHB clock */
733 bflb_ef_ctrl_switch_ahb_clk_r1(dev);
734 }
735 #endif
736 trim->len = trim_list[i].value_len;
737 reg_val = getreg32(BFLB_EF_CTRL_BASE + (trim_list[i].en_addr / 32) * 4);
738 if (reg_val & (1 << (trim_list[i].en_addr % 32))) {
739 trim->en = 1;
740 }
741 reg_val = getreg32(BFLB_EF_CTRL_BASE + (trim_list[i].parity_addr / 32) * 4);
742 if (reg_val & (1 << (trim_list[i].parity_addr % 32))) {
743 trim->parity = 1;
744 }
745
746 if (((trim_list[i].value_addr % 32) + trim_list[i].value_len) > 32) {
747 uint64_t tmpval64 = (uint64_t)getreg32(BFLB_EF_CTRL_BASE + (trim_list[i].value_addr / 32) * 4);
748 tmpval64 |= (((uint64_t)getreg32(BFLB_EF_CTRL_BASE + (trim_list[i].value_addr / 32) * 4 + 4)) << 32);
749 tmpval64 = tmpval64 >> (trim_list[i].value_addr % 32);
750 trim->value = (uint32_t)(tmpval64 & (((uint64_t)1 << trim_list[i].value_len) - 1));
751 } else {
752 reg_val = getreg32(BFLB_EF_CTRL_BASE + (trim_list[i].value_addr / 32) * 4);
753 reg_val = reg_val >> (trim_list[i].value_addr % 32);
754 trim->value = reg_val & ((1 << trim_list[i].value_len) - 1);
755 }
756
757 if (trim->en == 0 && trim->parity == 0 && trim->value == 0) {
758 trim->empty = 1;
759 } else {
760 trim->empty = 0;
761 }
762
763 break;
764 }
765 }
766 #if defined(BL702) || defined(BL602) || defined(BL702L)
767 bflb_efuse_switch_cpu_clock_restore();
768 #endif
769 bflb_irq_restore(irq_stat);
770 }
771
772 /****************************************************************************/ /**
773 * @brief Efuse write common trim value
774 *
775 * @param dev ef control device pointer
776 * @param name: Trim name
777 * @param trim: Trim data pointer
778 * @param program: program to efuse entity or not
779 *
780 * @return None
781 *
782 *******************************************************************************/
bflb_ef_ctrl_write_common_trim(struct bflb_device_s * dev,char * name,uint32_t value,uint8_t program)783 void ATTR_TCM_SECTION bflb_ef_ctrl_write_common_trim(struct bflb_device_s *dev, char *name, uint32_t value, uint8_t program)
784 {
785 uint32_t reg_val;
786 uint32_t i = 0;
787 uint8_t parity = 0;
788 const bflb_ef_ctrl_com_trim_cfg_t *trim_list = NULL;
789 uint32_t trim_list_len;
790 uintptr_t irq_stat;
791
792 // if (dev == NULL) {
793 // dev = bflb_device_get_by_name("ef_ctrl");
794 // }
795
796 trim_list_len = bflb_ef_ctrl_get_common_trim_list(&trim_list);
797
798 irq_stat = bflb_irq_save();
799 for (i = 0; i < trim_list_len; i++) {
800 if (memcmp(name, trim_list[i].name, strlen(name)) == 0) {
801 #if defined(BL702) || defined(BL602) || defined(BL702L)
802 bflb_efuse_switch_cpu_clock_save();
803 #endif
804 /* switch clock */
805 if (trim_list[i].en_addr <= EF_CTRL_EFUSE_R0_SIZE) {
806 /* Switch to AHB clock */
807 bflb_ef_ctrl_switch_ahb_clk_r0(dev);
808 }
809 #ifdef EF_CTRL_EFUSE_R1_SIZE
810 if (trim_list[i].en_addr > EF_CTRL_EFUSE_R0_SIZE) {
811 /* Switch to AHB clock */
812 bflb_ef_ctrl_switch_ahb_clk_r1(dev);
813 }
814 #endif
815 reg_val = getreg32(BFLB_EF_CTRL_BASE + (trim_list[i].en_addr / 32) * 4);
816 reg_val |= (1 << (trim_list[i].en_addr % 32));
817 putreg32(BFLB_EF_CTRL_BASE + (trim_list[i].en_addr / 32) * 4, reg_val);
818
819 parity = bflb_ef_ctrl_get_trim_parity(value, trim_list[i].value_len);
820 if (parity) {
821 reg_val = getreg32(BFLB_EF_CTRL_BASE + (trim_list[i].parity_addr / 32) * 4);
822 reg_val |= (1 << (trim_list[i].parity_addr % 32));
823 putreg32(BFLB_EF_CTRL_BASE + (trim_list[i].parity_addr / 32) * 4, reg_val);
824 }
825
826 if (((trim_list[i].value_addr % 32) + trim_list[i].value_len) > 32) {
827 reg_val = getreg32(BFLB_EF_CTRL_BASE + (trim_list[i].value_addr / 32) * 4);
828 reg_val |= (value << (trim_list[i].value_addr % 32));
829 putreg32(BFLB_EF_CTRL_BASE + (trim_list[i].value_addr / 32) * 4, reg_val);
830
831 reg_val = getreg32(BFLB_EF_CTRL_BASE + (trim_list[i].value_addr / 32) * 4) + 4;
832 reg_val |= (value >> (32 - (trim_list[i].value_addr % 32)));
833 putreg32(BFLB_EF_CTRL_BASE + (trim_list[i].value_addr / 32) * 4 + 4, reg_val);
834 } else {
835 reg_val = getreg32(BFLB_EF_CTRL_BASE + (trim_list[i].value_addr / 32) * 4);
836 reg_val |= (value << (trim_list[i].value_addr % 32));
837 putreg32(BFLB_EF_CTRL_BASE + (trim_list[i].value_addr / 32) * 4, reg_val);
838 }
839
840 if (program) {
841 /* program */
842 if (trim_list[i].en_addr <= EF_CTRL_EFUSE_R0_SIZE) {
843 bflb_ef_ctrl_program_efuse_r0(dev);
844 }
845 #ifdef EF_CTRL_EFUSE_R1_SIZE
846 if (trim_list[i].en_addr > EF_CTRL_EFUSE_R0_SIZE) {
847 bflb_ef_ctrl_program_efuse_r1(dev);
848 }
849 #endif
850 }
851 #if defined(BL702) || defined(BL602) || defined(BL702L)
852 bflb_efuse_switch_cpu_clock_restore();
853 #endif
854 break;
855 }
856 }
857 bflb_irq_restore(irq_stat);
858 }
859
860 /****************************************************************************/ /**
861 * @brief Whether a value bits is all zero
862 *
863 * @param val: value to check
864 * @param start: start bit
865 * @param len: total length of bits to check
866 *
867 * @return 1 for all bits zero 0 for others
868 *
869 *******************************************************************************/
bflb_ef_ctrl_is_all_bits_zero(uint32_t val,uint8_t start,uint8_t len)870 uint8_t ATTR_TCM_SECTION bflb_ef_ctrl_is_all_bits_zero(uint32_t val, uint8_t start, uint8_t len)
871 {
872 uint32_t mask = 0;
873
874 val = (val >> start);
875
876 if (len >= 32) {
877 mask = 0xffffffff;
878 } else {
879 mask = (1 << len) - 1;
880 }
881
882 if ((val & mask) == 0) {
883 return 1;
884 } else {
885 return 0;
886 }
887 }
888
889 /****************************************************************************/ /**
890 * @brief Efuse Ctrl get zero bit count
891 *
892 * @param val: Value to count
893 *
894 * @return Zero bit count
895 *
896 *******************************************************************************/
bflb_ef_ctrl_get_byte_zero_cnt(uint8_t val)897 uint32_t ATTR_TCM_SECTION bflb_ef_ctrl_get_byte_zero_cnt(uint8_t val)
898 {
899 uint32_t cnt = 0;
900 uint32_t i = 0;
901
902 for (i = 0; i < 8; i++) {
903 if ((val & (1 << i)) == 0) {
904 cnt += 1;
905 }
906 }
907
908 return cnt;
909 }
910
911 /****************************************************************************/ /**
912 * @brief Analog Trim parity calculate
913 *
914 * @param val: Value of efuse trim data
915 * @param len: Length of bit to calculate
916 *
917 * @return Parity bit value
918 *
919 *******************************************************************************/
bflb_ef_ctrl_get_trim_parity(uint32_t val,uint8_t len)920 uint8_t ATTR_CLOCK_SECTION bflb_ef_ctrl_get_trim_parity(uint32_t val, uint8_t len)
921 {
922 uint8_t cnt = 0;
923 uint8_t i = 0;
924
925 for (i = 0; i < len; i++) {
926 if (val & (1 << i)) {
927 cnt++;
928 }
929 }
930
931 return cnt & 0x01;
932 }
933