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 * Description: Provides efuse driver source \n
16 *
17 * History: \n
18 * 2022-10-20, Create file. \n
19 */
20
21 #include "efuse.h"
22 #include <stdio.h>
23 #include "securec.h"
24 #include "soc_osal.h"
25 #include "errcode.h"
26 #include "tcxo.h"
27 #include "hal_efuse.h"
28 #include "efuse_porting.h"
29
30 #define EFUSE_CHAR_BIT_WIDE 8
31 #define EFUSE_CALC_CRC_MAX_LEN 32
32
uapi_efuse_init(void)33 errcode_t uapi_efuse_init(void)
34 {
35 errcode_t ret = ERRCODE_FAIL;
36 efuse_port_register_hal_funcs();
37 hal_efuse_funcs_t *hal_funcs = hal_efuse_get_funcs();
38 ret = hal_funcs->init();
39 if (ret != ERRCODE_SUCC) {
40 return ret;
41 }
42 return ERRCODE_SUCC;
43 }
44
45 /*
46 * Removes power from the efuse system
47 */
uapi_efuse_deinit(void)48 errcode_t uapi_efuse_deinit(void)
49 {
50 hal_efuse_funcs_t *hal_funcs = hal_efuse_get_funcs();
51 if (hal_funcs != NULL) {
52 hal_funcs->deinit();
53 }
54 efuse_port_unregister_hal_funcs();
55 return ERRCODE_SUCC;
56 }
57
58 #ifdef EFUSE_BIT_OPERATION
59 /*
60 * Reads a bit from EFUSE memory
61 */
uapi_efuse_read_bit(uint8_t * value,uint32_t byte_number,uint8_t bit_pos)62 errcode_t uapi_efuse_read_bit(uint8_t *value, uint32_t byte_number, uint8_t bit_pos)
63 {
64 uint8_t read_value = 0;
65 if ((byte_number >= EFUSE_MAX_BYTES) || (value == NULL) || (bit_pos >= EFUSE_MAX_BIT_POS)) {
66 return ERRCODE_FAIL;
67 }
68 hal_efuse_funcs_t *hal_funcs = hal_efuse_get_funcs();
69 uint32_t irq_sts = osal_irq_lock();
70 if (hal_funcs->read_byte(byte_number, &read_value) == ERRCODE_SUCC) {
71 *value = (read_value >> bit_pos) & 1U;
72 osal_irq_restore(irq_sts);
73 return ERRCODE_SUCC;
74 }
75 osal_irq_restore(irq_sts);
76 return ERRCODE_FAIL;
77 }
78 #endif
79
80 /*
81 * Reads multiple bytes from EFUSE memory, into the provided buffer
82 */
uapi_efuse_read_buffer(uint8_t * buffer,uint32_t byte_number,uint16_t length)83 errcode_t uapi_efuse_read_buffer(uint8_t *buffer, uint32_t byte_number, uint16_t length)
84 {
85 if ((length == 0) || (byte_number >= EFUSE_MAX_BYTES) ||
86 ((byte_number + length) > EFUSE_MAX_BYTES) || (buffer == NULL)) {
87 return ERRCODE_FAIL;
88 }
89 hal_efuse_funcs_t *hal_funcs = hal_efuse_get_funcs();
90 uint32_t irq_sts = osal_irq_lock();
91 for (uint32_t i = 0; i < length; i++) {
92 if (hal_funcs->read_byte(byte_number + i, &buffer[i]) != ERRCODE_SUCC) {
93 osal_irq_restore(irq_sts);
94 return ERRCODE_FAIL;
95 }
96 }
97 osal_irq_restore(irq_sts);
98 return ERRCODE_SUCC;
99 }
100
101 #ifdef EFUSE_BIT_OPERATION
102 /*
103 * Writes a bit to EFUSE memory
104 */
uapi_efuse_write_bit(uint32_t byte_number,uint8_t bit_pos)105 errcode_t uapi_efuse_write_bit(uint32_t byte_number, uint8_t bit_pos)
106 {
107 if (byte_number >= EFUSE_MAX_BYTES || bit_pos >= EFUSE_MAX_BIT_POS) {
108 return ERRCODE_FAIL;
109 }
110
111 uint8_t write_value = 0;
112 hal_efuse_funcs_t *hal_funcs = hal_efuse_get_funcs();
113 uint32_t irq_sts = osal_irq_lock();
114 if (hal_funcs->read_byte(byte_number, &write_value) != ERRCODE_SUCC) {
115 osal_irq_restore(irq_sts);
116 return ERRCODE_FAIL;
117 }
118
119 if ((write_value & bit(bit_pos)) != 0) {
120 osal_irq_restore(irq_sts);
121 return ERRCODE_INVALID_PARAM;
122 }
123
124 hal_efuse_region_t region = hal_efuse_get_region(byte_number);
125 if (hal_funcs->write_op(byte_number, (uint8_t)bit(bit_pos), region) == ERRCODE_SUCC) {
126 osal_irq_restore(irq_sts);
127 return ERRCODE_SUCC;
128 }
129
130 osal_irq_restore(irq_sts);
131 return ERRCODE_FAIL;
132 }
133
uapi_efuse_write_bit_with_flag(uint32_t byte_number,uint8_t bit_pos,uint32_t flag)134 errcode_t uapi_efuse_write_bit_with_flag(uint32_t byte_number, uint8_t bit_pos, uint32_t flag)
135 {
136 if (flag != EFUSE_WRITE_PROTECT_FLAG) {
137 return ERRCODE_EFUSE_INVALID_PARAM;
138 }
139 if (byte_number >= EFUSE_MAX_BYTES || bit_pos >= EFUSE_MAX_BIT_POS) {
140 return ERRCODE_FAIL;
141 }
142
143 uint8_t write_value = 0;
144 hal_efuse_funcs_t *hal_funcs = hal_efuse_get_funcs();
145 uint32_t irq_sts = osal_irq_lock();
146 if (hal_funcs->read_byte(byte_number, &write_value) != ERRCODE_SUCC) {
147 osal_irq_restore(irq_sts);
148 return ERRCODE_FAIL;
149 }
150
151 if ((write_value & bit(bit_pos)) != 0) {
152 osal_irq_restore(irq_sts);
153 return ERRCODE_INVALID_PARAM;
154 }
155
156 hal_efuse_region_t region = hal_efuse_get_region(byte_number);
157 if (hal_funcs->write_op(byte_number, (uint8_t)bit(bit_pos), region) == ERRCODE_SUCC) {
158 osal_irq_restore(irq_sts);
159 return ERRCODE_SUCC;
160 }
161
162 osal_irq_restore(irq_sts);
163 return ERRCODE_FAIL;
164 }
165 #endif
166
efuse_write_param_check(uint32_t byte_number,const uint8_t * buffer,uint16_t length)167 static errcode_t efuse_write_param_check(uint32_t byte_number, const uint8_t *buffer, uint16_t length)
168 {
169 if ((length == 0) || (byte_number >= EFUSE_MAX_BYTES) ||
170 ((byte_number + length) > EFUSE_MAX_BYTES) || (buffer == NULL)) {
171 return ERRCODE_FAIL;
172 }
173
174 return ERRCODE_SUCC;
175 }
176
177 /*
178 * Writes multiple bytes to EFUSE memory, from the provided buffer
179 */
uapi_efuse_write_buffer(uint32_t byte_number,const uint8_t * buffer,uint16_t length)180 errcode_t uapi_efuse_write_buffer(uint32_t byte_number, const uint8_t *buffer, uint16_t length)
181 {
182 errcode_t ret;
183
184 ret = efuse_write_param_check(byte_number, buffer, length);
185 if (ret != ERRCODE_SUCC) {
186 return ERRCODE_EFUSE_INVALID_PARAM;
187 }
188 hal_efuse_funcs_t *hal_funcs = hal_efuse_get_funcs();
189 uint32_t irq_sts = osal_irq_lock();
190 if (hal_funcs->write_buffer_op(byte_number, buffer, length) != ERRCODE_SUCC) {
191 osal_irq_restore(irq_sts);
192 return ERRCODE_FAIL;
193 }
194
195 osal_irq_restore(irq_sts);
196 return ERRCODE_SUCC;
197 }
198
uapi_efuse_write_buffer_with_flag(uint32_t byte_number,const uint8_t * buffer,uint16_t length,uint32_t flag)199 errcode_t uapi_efuse_write_buffer_with_flag(uint32_t byte_number, const uint8_t *buffer, uint16_t length, uint32_t flag)
200 {
201 if (flag != EFUSE_WRITE_PROTECT_FLAG) {
202 return ERRCODE_EFUSE_INVALID_PARAM;
203 }
204 errcode_t ret;
205
206 ret = efuse_write_param_check(byte_number, buffer, length);
207 if (ret != ERRCODE_SUCC) {
208 return ERRCODE_EFUSE_INVALID_PARAM;
209 }
210 hal_efuse_funcs_t *hal_funcs = hal_efuse_get_funcs();
211 uint32_t irq_sts = osal_irq_lock();
212 if (hal_funcs->write_buffer_op(byte_number, buffer, length) != ERRCODE_SUCC) {
213 osal_irq_restore(irq_sts);
214 return ERRCODE_FAIL;
215 }
216
217 osal_irq_restore(irq_sts);
218 return ERRCODE_SUCC;
219 }
220
uapi_efuse_get_die_id(uint8_t * buffer,uint16_t length)221 errcode_t uapi_efuse_get_die_id(uint8_t *buffer, uint16_t length)
222 {
223 if ((length == 0) || (buffer == NULL)) {
224 return ERRCODE_FAIL;
225 }
226 hal_efuse_funcs_t *hal_funcs = hal_efuse_get_funcs();
227 errcode_t ret = hal_funcs->get_die_id(buffer, length);
228 if (ret != ERRCODE_SUCC) {
229 return ret;
230 }
231 return ERRCODE_SUCC;
232 }
233
uapi_efuse_get_chip_id(uint8_t * buffer,uint16_t length)234 errcode_t uapi_efuse_get_chip_id(uint8_t *buffer, uint16_t length)
235 {
236 if ((length == 0) || (buffer == NULL)) {
237 return ERRCODE_FAIL;
238 }
239 hal_efuse_funcs_t *hal_funcs = hal_efuse_get_funcs();
240 errcode_t ret = hal_funcs->get_chip_id(buffer, length);
241 if (ret != ERRCODE_SUCC) {
242 return ret;
243 }
244 return ERRCODE_SUCC;
245 }
246
efuse_count_zero_in_byte(uint8_t value)247 static uint8_t efuse_count_zero_in_byte(uint8_t value)
248 {
249 uint8_t num_zeroes = 0;
250 uint8_t count = value;
251 for (uint8_t i = 0; i < EFUSE_CHAR_BIT_WIDE; i++, count = count >> 1) {
252 if ((count & 1) == 0) {
253 num_zeroes++;
254 }
255 }
256 return num_zeroes;
257 }
258
259 /*
260 * Calculate OPT zero-counting CRC for a block upto 32 bytes (256 bits)
261 */
uapi_efuse_calc_crc(const uint8_t * buffer,uint8_t length,uint8_t * crc)262 errcode_t uapi_efuse_calc_crc(const uint8_t *buffer, uint8_t length, uint8_t *crc)
263 {
264 int i;
265 errcode_t ret_value = ERRCODE_SUCC;
266
267 if ((buffer == NULL) || (crc == NULL) || (length > EFUSE_CALC_CRC_MAX_LEN)) {
268 ret_value = ERRCODE_EFUSE_INVALID_PARAM;
269 } else {
270 *crc = 0;
271 for (i = 0; i < length; i++) {
272 *crc += efuse_count_zero_in_byte(buffer[i]);
273 }
274 }
275
276 return ret_value;
277 }
278
uapi_soc_read_id(uint8_t * id,uint16_t id_length)279 errcode_t uapi_soc_read_id(uint8_t *id, uint16_t id_length)
280 {
281 return uapi_efuse_get_die_id(id, id_length);
282 }
283
284 #ifndef CUSTOMER_RSVD_EFUSE_START_BIT
285 #define CUSTOMER_RSVD_EFUSE_START_BIT 0
286 #define CUSTOMER_RSVD_EFUSE_BIT_LEN 0
287 #endif
288
uapi_efuse_user_read_buffer(uint32_t offset,uint8_t * buffer,uint16_t length)289 errcode_t uapi_efuse_user_read_buffer(uint32_t offset, uint8_t *buffer, uint16_t length)
290 {
291 if (((length + offset) * EFUSE_CHAR_BIT_WIDE) > CUSTOMER_RSVD_EFUSE_BIT_LEN) {
292 return ERRCODE_EFUSE_INVALID_PARAM;
293 }
294 return uapi_efuse_read_buffer(buffer, (offset + CUSTOMER_RSVD_EFUSE_START_BIT / EFUSE_CHAR_BIT_WIDE), length);
295 }
296
297
uapi_efuse_user_write_buffer(uint32_t offset,const uint8_t * buffer,uint16_t length)298 errcode_t uapi_efuse_user_write_buffer(uint32_t offset, const uint8_t *buffer, uint16_t length)
299 {
300 if (((length + offset) * EFUSE_CHAR_BIT_WIDE) > CUSTOMER_RSVD_EFUSE_BIT_LEN) {
301 return ERRCODE_EFUSE_INVALID_PARAM;
302 }
303 return uapi_efuse_write_buffer((offset + CUSTOMER_RSVD_EFUSE_START_BIT / EFUSE_CHAR_BIT_WIDE), buffer, length);
304 }
305
306 #ifdef EFUSE_BIT_OPERATION
uapi_efuse_user_write_bit(uint32_t byte_offset,uint8_t bit_pos)307 errcode_t uapi_efuse_user_write_bit(uint32_t byte_offset, uint8_t bit_pos)
308 {
309 if ((byte_offset * EFUSE_CHAR_BIT_WIDE + bit_pos) > CUSTOMER_RSVD_EFUSE_BIT_LEN) {
310 return ERRCODE_EFUSE_INVALID_PARAM;
311 }
312 return uapi_efuse_write_bit((byte_offset + CUSTOMER_RSVD_EFUSE_START_BIT / EFUSE_CHAR_BIT_WIDE), bit_pos);
313 }
314
315
uapi_efuse_user_read_bit(uint32_t byte_offset,uint8_t bit_pos,uint8_t * value)316 errcode_t uapi_efuse_user_read_bit(uint32_t byte_offset, uint8_t bit_pos, uint8_t *value)
317 {
318 if ((byte_offset * EFUSE_CHAR_BIT_WIDE + bit_pos) > CUSTOMER_RSVD_EFUSE_BIT_LEN) {
319 return ERRCODE_EFUSE_INVALID_PARAM;
320 }
321 return uapi_efuse_read_bit(value, (byte_offset + CUSTOMER_RSVD_EFUSE_START_BIT / EFUSE_CHAR_BIT_WIDE), bit_pos);
322 }
323 #endif