• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "efuse.h"
17 #include "efuse_drv.h"
18 
efuse_start_addr_unaligned_read(hi_u16 start_bit,hi_u16 size,hi_u8 diff_head_read,hi_u8 * data)19 hi_u32 efuse_start_addr_unaligned_read(hi_u16 start_bit, hi_u16 size, hi_u8 diff_head_read, hi_u8 *data)
20 {
21     hi_u32 ret = HI_ERR_FAILURE;
22     hi_u32 check_sum;
23 
24     if (size == SIZE_8_BITS) {
25         ret = efuse_read_bits(start_bit, size, data);
26         if (ret == HI_ERR_SUCCESS) {
27             data[0] = data[0] >> diff_head_read;
28         }
29     } else if (size == SIZE_16_BITS) {
30         hi_u16 tmp_data = 0;
31         ret = efuse_read_bits(start_bit, size, (hi_u8 *)&tmp_data);
32         if (ret == HI_ERR_SUCCESS) {
33             tmp_data = tmp_data >> diff_head_read;
34             if (start_bit == 0xE0) {
35                 *data = (hi_u8)(tmp_data & 0xFF);
36             } else {
37                 *(hi_u16 *)data = tmp_data;
38             }
39         }
40     } else if (size == SIZE_24_BITS) {
41         hi_u32 tmp_data = 0;
42         ret = efuse_read_bits(start_bit, SIZE_24_BITS, (hi_u8 *)&tmp_data);
43         if (ret == HI_ERR_SUCCESS) {
44             tmp_data = tmp_data >> diff_head_read;
45             check_sum = (uintptr_t)data ^ DATA_LENGTH ^ (uintptr_t)(hi_u8 *)&tmp_data ^ DATA_LENGTH;
46             if (memcpy_s(data, DATA_LENGTH, (hi_u8 *)&tmp_data, DATA_LENGTH, check_sum) != EOK) {
47                 return HI_ERR_FAILURE;
48             }
49         }
50     } else if (size == SIZE_72_BITS) {
51         hi_u8 tmp_data[SIZE_72_BITS / SIZE_8_BITS] = { 0 };
52         hi_u32 data_u32[2]; /* U64 is divided into 2 U32 */
53         hi_u8 end_u8;
54         ret = efuse_read_bits(start_bit, SIZE_72_BITS, &tmp_data[0]);
55         if (ret == HI_ERR_SUCCESS) {
56             data_u32[0] = *(hi_u32 *)&tmp_data[0];  /* first U32 offset is 0 */
57             data_u32[1] = *(hi_u32 *)&tmp_data[4];  /* sencond U32 offset is 4 */
58             end_u8 = *(hi_u8 *)&tmp_data[8]; /* the last u8 bit */
59             data_u32[0] = data_u32[0] >> diff_head_read;
60             data_u32[0] = data_u32[0] | (data_u32[1] << (SIZE_32_BITS - diff_head_read));
61             data_u32[1] = data_u32[1] >> diff_head_read;
62             data_u32[1] = data_u32[1] | ((hi_u32)end_u8 << (SIZE_32_BITS - diff_head_read));
63             *(hi_u64 *)data = (((hi_u64)data_u32[1] << SIZE_32_BITS) | data_u32[0]);
64         }
65     }
66     return ret;
67 }
68 
efuse_bits_read(hi_u16 start_bit,hi_u16 size,hi_u8 * data,hi_u32 data_len)69 hi_u32 efuse_bits_read(hi_u16 start_bit, hi_u16 size, hi_u8 *data, hi_u32 data_len)
70 {
71     hi_u8 diff_head_read = 0;
72     hi_u32 origine_size;
73     hi_u32 ret;
74     if (data_len > EFUSE_MAX_INDEX_SIZE) {
75         return HI_ERR_FAILURE;
76     }
77 
78     origine_size = size;
79     if ((start_bit & 0x7) != 0x0) {
80         diff_head_read = start_bit % SIZE_8_BITS;
81         /* The start address of the chip must be 8-bit aligned. */
82         start_bit = start_bit - diff_head_read;
83         size = size + diff_head_read;
84     }
85 
86     if ((size & 0x7) != 0x0) {
87         size = ((size >> THREE_BITS_OFFSET) + 1) << THREE_BITS_OFFSET;
88     }
89 
90     if (diff_head_read == 0) {
91         /* The start address is 8-bit aligned. */
92         ret = efuse_read_bits(start_bit, size, data);
93         if (ret != HI_ERR_SUCCESS) {
94             return ret;
95         }
96     } else {
97         /* The start address is 8-bit aligned. */
98         ret = efuse_start_addr_unaligned_read(start_bit, size, diff_head_read, data);
99         if (ret != HI_ERR_SUCCESS) {
100             return ret;
101         }
102     }
103 
104     if (origine_size <= SIZE_8_BITS) {
105         *data &= ((1 << origine_size) - 1);
106     } else if (origine_size <= SIZE_16_BITS) {
107         *(hi_u16 *)data &= ((1 << origine_size) - 1);
108     } else if (origine_size < SIZE_32_BITS) {
109         *(hi_u32 *)data &= (((hi_u32)1 << origine_size) - 1);
110     }
111 
112     return HI_ERR_SUCCESS;
113 }
114 
hi_efuse_read(hi_efuse_idx efuse_id,hi_u8 * data,hi_u8 data_len)115 hi_u32 hi_efuse_read(hi_efuse_idx efuse_id, hi_u8 *data, hi_u8 data_len)
116 {
117     hi_u16 start_bit = 0;
118     hi_u16 size = 0;
119     hi_u16 align_size;
120     hi_u8 flag = EFUSE_IDX_NRW;
121 
122     if (efuse_id >= HI_EFUSE_IDX_MAX || data == HI_NULL) {
123         return HI_ERR_EFUSE_INVALIDATE_PARA;
124     }
125 
126     get_efuse_cfg_by_id(efuse_id, &start_bit, &size, &flag);
127 
128     if (flag == EFUSE_IDX_WO) {
129         return HI_ERR_EFUSE_INVALIDATE_AUTH;
130     }
131 
132     align_size = ((size & 0x7) != 0x0) ? (((size >> THREE_BITS_OFFSET) + 1) << THREE_BITS_OFFSET) : size;
133 
134     if (align_size > ((hi_u16)data_len * EIGHT_BITS)) {
135         return HI_ERR_EFUSE_INVALIDATE_PARA;
136     }
137 
138     return efuse_bits_read(start_bit, size, data, data_len);
139 }
140 
hi_efuse_write(hi_efuse_idx efuse_id,const hi_u8 * data)141 hi_u32 hi_efuse_write(hi_efuse_idx efuse_id, const hi_u8 *data)
142 {
143     hi_u16 start_bit = 0;
144     hi_u16 size = 0;
145     hi_u8 flag = EFUSE_IDX_NRW;
146     hi_char err_state[EFUSE_MAX_INDEX_SIZE] = {
147         0,
148     };
149     hi_u32 i;
150     hi_u32 ret;
151 
152     if (efuse_id >= HI_EFUSE_IDX_MAX || data == HI_NULL) {
153         boot_msg1("parameter err !", efuse_id);
154         return HI_ERR_EFUSE_INVALIDATE_PARA;
155     }
156 
157     get_efuse_cfg_by_id(efuse_id, &start_bit, &size, &flag);
158     if (flag == EFUSE_IDX_RO) {
159         boot_msg1("This section can not be write !flag = ", flag);
160         return HI_ERR_EFUSE_INVALIDATE_AUTH;
161     }
162 
163     ret = efuse_write_bits(start_bit, size, data, (hi_u8 *)&err_state[0]);
164     if (ret != HI_ERR_SUCCESS) {
165         boot_msg0("efuse write err");
166         return ret;
167     }
168 
169     for (i = 0; i < EFUSE_MAX_INDEX_SIZE; i++) {
170         if (err_state[i]) {
171             boot_msg1("errstate num is", i);
172             return HI_ERR_EFUSE_WRITE_ERR;
173         }
174     }
175 
176     return HI_ERR_SUCCESS;
177 }
178 
hi_efuse_lock(hi_efuse_lock_id lock_id)179 hi_u32 hi_efuse_lock(hi_efuse_lock_id lock_id)
180 {
181     hi_u16 err_stat = 0;
182     hi_u32 ret;
183     hi_u16 start_bit;
184     hi_u8 lock_val = 1;
185 
186     if (lock_id >= HI_EFUSE_LOCK_MAX) {
187         return HI_ERR_EFUSE_INVALIDATE_ID;
188     }
189 
190     if (lock_id < HI_EFUSE_LOCK_FLASH_ENCPY_CNT3_ID) {
191         start_bit = EFUSE_LOCK_START_BITS + lock_id;
192     } else {
193         start_bit = EFUSE_LOCK_FIELD2_START_BITS + lock_id - HI_EFUSE_LOCK_FLASH_ENCPY_CNT3_ID;
194     }
195 
196     ret = efuse_write_bits(start_bit, 1, &lock_val, (hi_u8 *)&err_stat);
197     if ((ret == HI_ERR_SUCCESS) && (err_stat == 0)) {
198         return HI_ERR_SUCCESS;
199     } else if (err_stat != 0) {
200         return HI_ERR_EFUSE_WRITE_ERR;
201     }
202 
203     return ret;
204 }
205 
hi_efuse_get_lockstat(hi_u64 * lock_stat)206 hi_u32 hi_efuse_get_lockstat(hi_u64 *lock_stat)
207 {
208     hi_u16 start_bit = EFUSE_LOCK_START_BITS;
209     hi_u16 size = EFUSE_LOCK_SIZE;
210     hi_u8 diff_head_read;
211     hi_u64 tmp_data = 0;
212     hi_u64 tmp_data_filed_two = 0;
213     hi_u32 ret;
214 
215     if (lock_stat == HI_NULL) {
216         return HI_ERR_FAILURE;
217     }
218 
219     /* start address and size 8 bits align. */
220     diff_head_read = start_bit % EIGHT_BITS;
221     start_bit = start_bit - diff_head_read;
222     size = size + diff_head_read;
223 
224     ret = efuse_read_bits(start_bit, size, (hi_u8 *)&tmp_data);
225     if (ret == HI_ERR_SUCCESS) {
226         tmp_data = tmp_data >> diff_head_read;
227     } else {
228         return HI_ERR_FAILURE;
229     }
230 
231     start_bit = EFUSE_LOCK_FIELD2_START_BITS;
232     size = EFUSE_LOCK_FIELD2_SIZE;
233 
234     /* start address and size 8 bits align. */
235     diff_head_read = start_bit % EIGHT_BITS;
236     start_bit = start_bit - diff_head_read;
237     size = size + diff_head_read;
238 
239     ret = efuse_read_bits(start_bit, size, (hi_u8 *)&tmp_data_filed_two);
240     if (ret == HI_ERR_SUCCESS) {
241         tmp_data_filed_two = tmp_data_filed_two >> diff_head_read;
242     } else {
243         return HI_ERR_FAILURE;
244     }
245 
246     *lock_stat = (((tmp_data_filed_two << EFUSE_LOCK_SIZE) & 0x1F000000000) | (tmp_data & 0xFFFFFFFFF));
247 
248     return HI_ERR_SUCCESS;
249 }
250 
hi_efuse_usr_read(hi_u16 start_bit,hi_u16 size,hi_u8 * key_data)251 hi_u32 hi_efuse_usr_read(hi_u16 start_bit, hi_u16 size, hi_u8 *key_data)
252 {
253     hi_u16 real_size = size;
254 
255     if ((start_bit >= EFUSE_PGM_ADDR_SIZE) || ((start_bit & 0x7) != 0) || (key_data == HI_NULL) || (size == 0)) {
256         return HI_ERR_FAILURE;
257     }
258 
259     /* The start address of the chip must be 8-bit aligned. */
260     if ((size & 0x7) != 0x0) {
261         real_size = ((size >> 3) + 1) << 3; /* right shift 3bit;add;then left shift 3bit */
262     }
263 
264     if ((start_bit + real_size) > EFUSE_PGM_ADDR_SIZE) {
265         return HI_ERR_FAILURE;
266     }
267 
268     return efuse_read_bits(start_bit, real_size, key_data);
269 }
270 
hi_efuse_usr_write(hi_u16 start_bit,hi_u16 size,const hi_u8 * key_data)271 hi_u32 hi_efuse_usr_write(hi_u16 start_bit, hi_u16 size, const hi_u8 *key_data)
272 {
273     hi_u8 usr_err_stat[EFUSE_MAX_INDEX_SIZE];
274     hi_u32 i;
275     hi_u32 ret;
276 
277     if (size > (EFUSE_MAX_INDEX_SIZE * SIZE_8_BITS) || key_data == HI_NULL || size == 0) {
278         return HI_ERR_FAILURE;
279     }
280     hi_u32 check_sum = (uintptr_t)usr_err_stat ^ EFUSE_MAX_INDEX_SIZE ^ 0 ^ EFUSE_MAX_INDEX_SIZE;
281     memset_s(usr_err_stat, EFUSE_MAX_INDEX_SIZE, 0, EFUSE_MAX_INDEX_SIZE, check_sum);
282 
283     ret = efuse_write_bits(start_bit, size, key_data, (hi_u8 *)&usr_err_stat[0]);
284     if (ret != HI_ERR_SUCCESS) {
285         return ret;
286     }
287 
288     for (i = 0; i < EFUSE_MAX_INDEX_SIZE; i++) {
289         if (usr_err_stat[i]) {
290             return HI_ERR_FAILURE;
291         }
292     }
293 
294     return HI_ERR_SUCCESS;
295 }
296 
297