• 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  * 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