• 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 
efuse_start_addr_unaligned_read(hi_u16 start_bit,hi_u16 size,hi_u8 diff_head_read,hi_u8 * data)18 hi_u32 efuse_start_addr_unaligned_read(hi_u16 start_bit, hi_u16 size, hi_u8 diff_head_read, hi_u8 *data)
19 {
20     if (size == SIZE_8_BITS) {
21         if (efuse_read_bits(start_bit, size, data) != HI_ERR_SUCCESS) {
22             return HI_ERR_FAILURE;
23         }
24 
25         data[0] = data[0] >> diff_head_read;
26     } else if (size == SIZE_16_BITS) {
27         hi_u16 tmp_data = 0;
28         if (efuse_read_bits(start_bit, size, (hi_u8 *)&tmp_data) != HI_ERR_SUCCESS) {
29             return HI_ERR_FAILURE;
30         }
31 
32         tmp_data = tmp_data >> diff_head_read;
33         if (start_bit == 0xE0) {
34             *data = (hi_u8)(tmp_data & 0xFF);
35         } else {
36             *(hi_u16 *)data = tmp_data;
37         }
38     } else if (size == SIZE_24_BITS) {
39         hi_u32 tmp_data = 0;
40         if (efuse_read_bits(start_bit, SIZE_24_BITS, (hi_u8 *)&tmp_data) != HI_ERR_SUCCESS) {
41             return HI_ERR_FAILURE;
42         }
43 
44         tmp_data = tmp_data >> diff_head_read;
45         hi_u32 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     } else if (size == SIZE_72_BITS) {
50         hi_u8 tmp_data[SIZE_72_BITS / SIZE_8_BITS] = { 0 };
51         hi_u32 data_u32[2]; /* U64 is divided into 2 U32 */
52         hi_u8 end_u8;
53         if (efuse_read_bits(start_bit, SIZE_72_BITS, &tmp_data[0]) != HI_ERR_SUCCESS) {
54             return HI_ERR_FAILURE;
55         }
56 
57         data_u32[0] = *(hi_u32 *)&tmp_data[0];  /* first U32 offset is 0 */
58         data_u32[1] = *(hi_u32 *)&tmp_data[4];  /* sencond U32 offset is 4 */
59         end_u8 = *(hi_u8 *)&tmp_data[8]; /* the last u8 bit */
60         data_u32[0] = data_u32[0] >> diff_head_read;
61         data_u32[0] = data_u32[0] | (data_u32[1] << (SIZE_32_BITS - diff_head_read));
62         data_u32[1] = data_u32[1] >> diff_head_read;
63         data_u32[1] = data_u32[1] | ((hi_u32)end_u8 << (SIZE_32_BITS - diff_head_read));
64         *(hi_u64 *)data = (((hi_u64)data_u32[1] << SIZE_32_BITS) | data_u32[0]);
65     } else {
66         return HI_ERR_FAILURE;
67     }
68 
69     return HI_ERR_SUCCESS;
70 }
71 
efuse_bits_read(hi_u16 start_bit,hi_u16 size,hi_u8 * data,hi_u32 data_len)72 hi_u32 efuse_bits_read(hi_u16 start_bit, hi_u16 size, hi_u8 *data, hi_u32 data_len)
73 {
74     hi_u8 diff_head_read = 0;
75     hi_u32 origine_size;
76     hi_u32 ret;
77     if (data_len > EFUSE_MAX_INDEX_SIZE) {
78         return HI_ERR_FAILURE;
79     }
80 
81     origine_size = size;
82     if ((start_bit & 0x7) != 0x0) {
83         diff_head_read = start_bit % SIZE_8_BITS;
84         start_bit = start_bit - diff_head_read; /* Reads the 8-bit aligned start address. */
85         size = size + diff_head_read;
86     }
87 
88     if ((size & 0x7) != 0x0) {
89         size = ((size >> THREE_BITS_OFFSET) + 1) << THREE_BITS_OFFSET; /* Reads data in 8-bit unit. */
90     }
91 
92     if (diff_head_read == 0) {
93         /* Reads the 8-bit aligned start address. */
94         ret = efuse_read_bits(start_bit, size, data);
95         if (ret != HI_ERR_SUCCESS) {
96             return ret;
97         }
98     } else {
99         /* The start address is not 8-bit-aligned. */
100         ret = efuse_start_addr_unaligned_read(start_bit, size, diff_head_read, data);
101         if (ret != HI_ERR_SUCCESS) {
102             return ret;
103         }
104     }
105 
106     if (origine_size <= SIZE_8_BITS) {
107         *data &= ((1 << origine_size) - 1);
108     } else if (origine_size <= SIZE_16_BITS) {
109         *(hi_u16 *)data &= ((1 << origine_size) - 1);
110     } else if (origine_size < SIZE_32_BITS) {
111         *(hi_u32 *)data &= (((hi_u32)1 << origine_size) - 1);
112     }
113 
114     return HI_ERR_SUCCESS;
115 }
116 
hi_efuse_read(hi_efuse_idx efuse_id,hi_u8 * data,hi_u8 data_len)117 hi_u32 hi_efuse_read(hi_efuse_idx efuse_id, hi_u8 *data, hi_u8 data_len)
118 {
119     hi_u16 start_bit = 0;
120     hi_u16 size = 0;
121     hi_u16 align_size;
122     hi_u8 flag = EFUSE_IDX_NRW;
123 
124     if (efuse_id >= HI_EFUSE_IDX_MAX || data == HI_NULL) {
125         return HI_ERR_EFUSE_INVALIDATE_PARA;
126     }
127 
128     get_efuse_cfg_by_id(efuse_id, &start_bit, &size, &flag);
129 
130     if (flag == EFUSE_IDX_WO) {
131         return HI_ERR_EFUSE_INVALIDATE_AUTH;
132     }
133 
134     align_size = ((size & 0x7) != 0x0) ? (((size >> THREE_BITS_OFFSET) + 1) << THREE_BITS_OFFSET) : size;
135 
136     if (align_size > ((hi_u16)data_len * EIGHT_BITS)) {
137         return HI_ERR_EFUSE_INVALIDATE_PARA;
138     }
139 
140     return efuse_bits_read(start_bit, size, data, data_len);
141 }
142 
hi_efuse_write(hi_efuse_idx efuse_id,const hi_u8 * data)143 hi_u32 hi_efuse_write(hi_efuse_idx efuse_id, const hi_u8 *data)
144 {
145     hi_u16 start_bit = 0;
146     hi_u16 size = 0;
147     hi_u8 flag = EFUSE_IDX_NRW;
148     hi_char err_state[EFUSE_MAX_INDEX_SIZE] = {
149         0,
150     };
151     hi_u32 i;
152     hi_u32 ret;
153 
154     if (efuse_id >= HI_EFUSE_IDX_MAX || data == HI_NULL) {
155         boot_msg1("parameter err !", efuse_id);
156         return HI_ERR_EFUSE_INVALIDATE_PARA;
157     }
158 
159     get_efuse_cfg_by_id(efuse_id, &start_bit, &size, &flag);
160     if (flag == EFUSE_IDX_RO) {
161         boot_msg1("This section can not be write !flag = ", flag);
162         return HI_ERR_EFUSE_INVALIDATE_AUTH;
163     }
164 
165     ret = efuse_write_bits(start_bit, size, data, (hi_u8 *)&err_state[0]);
166     if (ret != HI_ERR_SUCCESS) {
167         boot_msg0("efuse write err");
168         return ret;
169     }
170 
171     for (i = 0; i < EFUSE_MAX_INDEX_SIZE; i++) {
172         if (err_state[i]) {
173             boot_msg1("errstate num is", i);
174             return HI_ERR_EFUSE_WRITE_ERR;
175         }
176     }
177 
178     return HI_ERR_SUCCESS;
179 }
180 
efuse_bits_write(hi_u16 start_bit,hi_u16 size,const hi_u8 * key_data)181 hi_u32 efuse_bits_write(hi_u16 start_bit, hi_u16 size, const hi_u8 *key_data)
182 {
183     hi_u8 usr_err_stat[EFUSE_MAX_INDEX_SIZE];
184     hi_u32 i;
185     hi_u32 ret;
186 
187     if (size > (EFUSE_MAX_INDEX_SIZE * SIZE_8_BITS) || key_data == HI_NULL || size == 0) {
188         return HI_ERR_FAILURE;
189     }
190     hi_u32 check_sum = (uintptr_t)usr_err_stat ^ EFUSE_MAX_INDEX_SIZE ^ 0 ^ EFUSE_MAX_INDEX_SIZE;
191     memset_s(usr_err_stat, EFUSE_MAX_INDEX_SIZE, 0, EFUSE_MAX_INDEX_SIZE, check_sum);
192 
193     ret = efuse_write_bits(start_bit, size, key_data, (hi_u8 *)&usr_err_stat[0]);
194     if (ret != HI_ERR_SUCCESS) {
195         return ret;
196     }
197 
198     for (i = 0; i < EFUSE_MAX_INDEX_SIZE; i++) {
199         if (usr_err_stat[i]) {
200             return HI_ERR_FAILURE;
201         }
202     }
203 
204     return HI_ERR_SUCCESS;
205 }
206 
hi_efuse_get_lockstat(hi_u64 * lock_stat)207 hi_u32 hi_efuse_get_lockstat(hi_u64 *lock_stat)
208 {
209     hi_u16 start_bit = EFUSE_LOCK_START_BITS;
210     hi_u16 size = EFUSE_LOCK_SIZE;
211     hi_u8 diff_head_read;
212     hi_u64 tmp_data = 0;
213     hi_u64 tmp_data_filed_two = 0;
214     hi_u32 ret;
215 
216     if (lock_stat == HI_NULL) {
217         return HI_ERR_FAILURE;
218     }
219 
220     /* start address and size 8 bits align. */
221     diff_head_read = start_bit % EIGHT_BITS;
222     start_bit = start_bit - diff_head_read;
223     size = size + diff_head_read;
224 
225     ret = efuse_read_bits(start_bit, size, (hi_u8 *)&tmp_data);
226     if (ret == HI_ERR_SUCCESS) {
227         tmp_data = tmp_data >> diff_head_read;
228     } else {
229         return HI_ERR_FAILURE;
230     }
231 
232     start_bit = EFUSE_LOCK_FIELD2_START_BITS;
233     size = EFUSE_LOCK_FIELD2_SIZE;
234 
235     /* start address and size 8 bits align. */
236     diff_head_read = start_bit % EIGHT_BITS;
237     start_bit = start_bit - diff_head_read;
238     size = size + diff_head_read;
239 
240     ret = efuse_read_bits(start_bit, size, (hi_u8 *)&tmp_data_filed_two);
241     if (ret == HI_ERR_SUCCESS) {
242         tmp_data_filed_two = tmp_data_filed_two >> diff_head_read;
243     } else {
244         return HI_ERR_FAILURE;
245     }
246 
247     *lock_stat = (((tmp_data_filed_two << EFUSE_LOCK_SIZE) & 0x1F000000000) | (tmp_data & 0xFFFFFFFFF));
248 
249     return HI_ERR_SUCCESS;
250 }
251