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