• 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_drv.h"
17 #define THREE_BITS_OFFSET 3
18 
19 hi_efuse_stru g_efuse_cfg[HI_EFUSE_IDX_MAX] = {
20     { 0,    8,   EFUSE_IDX_RW },
21     { 8,    192, EFUSE_IDX_RW },
22     { 200,  10,  EFUSE_IDX_RW },
23     { 210,  10,  EFUSE_IDX_RW },
24     { 220,  2,   EFUSE_IDX_RW },
25     { 222,  2,   EFUSE_IDX_RW },
26     { 224,  2,   EFUSE_IDX_RW },
27     { 234,  1,   EFUSE_IDX_RW },
28     { 240,  256, EFUSE_IDX_RW },
29     { 496,  256, EFUSE_IDX_WO },
30     { 752,  256, EFUSE_IDX_RW },
31     { 1008, 32,  EFUSE_IDX_RW },
32     { 1040, 8,   EFUSE_IDX_RW },
33     { 1048, 24,  EFUSE_IDX_RW },
34     { 1072, 1,   EFUSE_IDX_RW },
35     { 1073, 1,   EFUSE_IDX_RW },
36     { 1074, 1,   EFUSE_IDX_RW },
37     { 1075, 1,   EFUSE_IDX_RW },
38     { 1076, 1,   EFUSE_IDX_RW },
39     { 1077, 1,   EFUSE_IDX_RW },
40     { 1078, 1,   EFUSE_IDX_RW },
41     { 1079, 1,   EFUSE_IDX_RW },
42     { 1080, 2,   EFUSE_IDX_RW },
43     { 1082, 2,   EFUSE_IDX_RW },
44     { 1084, 4,   EFUSE_IDX_RW },
45     { 1088, 8,   EFUSE_IDX_RW },
46     { 1096, 48,  EFUSE_IDX_RW },
47     { 1144, 128, EFUSE_IDX_RW },
48     { 1272, 32,  EFUSE_IDX_RW },
49     { 1304, 32,  EFUSE_IDX_RW },
50     { 1336, 32,  EFUSE_IDX_RW },
51     { 1368, 32,  EFUSE_IDX_RW },
52     { 1400, 32,  EFUSE_IDX_RW },
53     { 1432, 32,  EFUSE_IDX_RW },
54     { 1464, 32,  EFUSE_IDX_RW },
55     { 1496, 32,  EFUSE_IDX_RW },
56     { 1528, 32,  EFUSE_IDX_RW },
57     { 1560, 32,  EFUSE_IDX_RW },
58     { 1592, 32,  EFUSE_IDX_RW },
59     { 1624, 32,  EFUSE_IDX_RW },
60     { 1656, 16,  EFUSE_IDX_RW },
61     { 1672, 48,  EFUSE_IDX_RW },
62     { 1720, 128, EFUSE_IDX_RW },
63     { 1848, 2,   EFUSE_IDX_RW },
64     { 1850, 2,   EFUSE_IDX_RW },
65     { 1852, 2,   EFUSE_IDX_RW },
66     { 1854, 1,   EFUSE_IDX_RW },
67     { 1855, 1,   EFUSE_IDX_RW },
68     { 1856, 10,  EFUSE_IDX_RW },
69     { 1866, 18,  EFUSE_IDX_RW },
70     { 1884, 64,  EFUSE_IDX_RW },
71     { 1948, 64,  EFUSE_IDX_RW },
72     { 226,  8,   EFUSE_IDX_RW },
73 };
74 
75 
get_efuse_cfg(hi_void)76 hi_efuse_stru *get_efuse_cfg(hi_void)
77 {
78     return &g_efuse_cfg[0];
79 }
80 
get_efuse_cfg_by_id(hi_efuse_idx idx,hi_u16 * start_bit,hi_u16 * size,hi_u8 * attr)81 hi_void get_efuse_cfg_by_id(hi_efuse_idx idx, hi_u16 *start_bit, hi_u16 *size, hi_u8 *attr)
82 {
83     hi_efuse_stru *efuse_cfg = get_efuse_cfg();
84 
85     /* Internal interface, which does not check input parameters. */
86     if (start_bit != HI_NULL) {
87         *start_bit = efuse_cfg[idx].id_start_bit;
88     }
89 
90     if (size != HI_NULL) {
91         *size = efuse_cfg[idx].id_size;
92     }
93 
94     if (attr != HI_NULL) {
95         *attr = efuse_cfg[idx].attr;
96     }
97 }
98 
check_efuse_isbusy(hi_void)99 hi_bool check_efuse_isbusy(hi_void)
100 {
101     hi_u32 val = 0;
102     hi_u32 cnt = 0;
103 
104     while (cnt < EFUSE_TIMEOUT_DEFAULT) {
105         hi_reg_read(EFUSE_STATUS, val);
106         if ((!(val & EFUSE_STATUS_READY)) && (val & EFUSE_PO_STATUS_READY)) {
107             return HI_FALSE;
108         }
109         udelay(EFUSE_TIMECNT_TICK);
110         cnt += EFUSE_TIMECNT_TICK;
111     }
112     return HI_TRUE;
113 }
114 
efuse_write_bit(hi_u16 addr)115 hi_u32 efuse_write_bit(hi_u16 addr)
116 {
117     hi_u32 val;
118     hi_u32 cnt = 0;
119 
120     if (addr >= EFUSE_PGM_ADDR_SIZE) {
121         return HI_ERR_EFUSE_INVALIDATE_PARA;
122     }
123 
124     if (check_efuse_isbusy() == HI_TRUE) {
125         boot_msg0("efuse is busy !");
126         return HI_ERR_EFUSE_BUSY;
127     }
128 
129     hi_reg_write(EFUSE_PGM_ADDR, addr);
130     hi_reg_write(EFUSE_PGM_EN, HI_TRUE);
131 
132     /* Query the current status. */
133     while (cnt < EFUSE_TIMEOUT_DEFAULT) {
134         hi_reg_read(EFUSE_PGM_EN, val);
135         if ((val & EFUSE_EN_SWITCH) == EFUSE_EN_OK) {
136             break;
137         }
138 
139         udelay(EFUSE_TIMECNT_TICK);
140         cnt += EFUSE_TIMECNT_TICK;
141     }
142 
143     if (cnt >= EFUSE_TIMEOUT_DEFAULT) {
144         boot_msg0("timeout");
145         return HI_ERR_EFUSE_TIMEOUT;
146     }
147 
148     return HI_ERR_SUCCESS;
149 }
150 
efuse_read_bits(hi_u16 start_bit,hi_u16 size,hi_u8 * key_data)151 hi_u32 efuse_read_bits(hi_u16 start_bit, hi_u16 size, hi_u8 *key_data)
152 {
153     hi_u32 i;
154     hi_u32 val;
155     hi_u16 free_area_addr_start = start_bit;
156     hi_u32 free_area_addr_end = start_bit + size;
157     hi_u32 cnt;
158 
159     /* The start position and length must be 8-pixel aligned. */
160     if (((start_bit & 0x7) != 0x0) || ((size & 0x7) != 0x0)) {
161         boot_msg0("start_bits and lenth should be ALIGN_8!");
162         return HI_ERR_EFUSE_INVALIDATE_PARA;
163     }
164 
165     if (check_efuse_isbusy() == HI_TRUE) {
166         boot_msg0("EFUSE is busy!");
167         return HI_ERR_EFUSE_BUSY;
168     }
169 
170     free_area_addr_start = free_area_addr_start >> 3; /* right shift 3bit */
171     free_area_addr_end = free_area_addr_end >> 3;     /* right shift 3bit */
172 
173     for (i = free_area_addr_start; i < free_area_addr_end; i++) {
174         hi_reg_write(EFUSE_RD_ADDR, i);
175         hi_reg_write(EFUSE_RD_EN, HI_TRUE);
176         /* Query the current status. */
177         cnt = 0;
178         while (cnt < EFUSE_TIMEOUT_DEFAULT) {
179             hi_reg_read(EFUSE_RD_EN, val);
180             if (((val & EFUSE_EN_SWITCH) == EFUSE_EN_OK) &&
181                 ((hi_reg_read_val32(EFUSE_STATUS) & EFUSE_READ_READY_STATUS) != EFUSE_EN_OK)) {
182                 cnt = 0;
183                 break;
184             }
185             udelay(1);
186             cnt++;
187         }
188 
189         if (cnt >= (EFUSE_TIMEOUT_DEFAULT)) {
190             boot_msg0("timeout\r\n");
191             return HI_ERR_EFUSE_TIMEOUT;
192         }
193 
194         hi_reg_read(EFUSE_RDATA, val);
195         key_data[i - free_area_addr_start] = (hi_u8)val;
196     }
197 
198     return HI_ERR_SUCCESS;
199 }
200 
efuse_get_errstate(hi_u16 byte_id,hi_u16 bit_id,hi_u8 * err_state)201 hi_void efuse_get_errstate(hi_u16 byte_id, hi_u16 bit_id, hi_u8 *err_state)
202 {
203     hi_u32 val = 0;
204 
205     hi_reg_read(EFUSE_STATUS, val);
206 
207     if (val & EFUSE_CTRL_ST) {
208         err_state[byte_id] |= (hi_u8)(1 << bit_id);
209     } else {
210         err_state[byte_id] &= (~(hi_u8)(1 << bit_id));
211     }
212 }
213 
efuse_write_bits(hi_u16 start_bit,hi_u16 size,const hi_u8 * key_data,hi_u8 * err_state)214 hi_u32 efuse_write_bits(hi_u16 start_bit, hi_u16 size, const hi_u8 *key_data, hi_u8 *err_state)
215 {
216     hi_u16 i;
217     hi_u16 j;
218     hi_u16 a;
219     hi_u16 b;
220     hi_u32 ret;
221     hi_u16 zero_count = 0;
222 
223     /* j: the current bit offset of key_data. */
224     for (i = start_bit, j = 0; i < (start_bit + size); i++, j++) {
225         a = j >> THREE_BITS_OFFSET; /* subscript of receive array. */
226         b = j & 0x7;                /* bit offset in one byte. */
227 
228         if (key_data[a] & (hi_u8)(1 << b)) {
229             ret = efuse_write_bit(i);
230             if (ret != HI_ERR_SUCCESS) {
231                 return ret;
232             } else if (err_state != HI_NULL) {
233                 efuse_get_errstate(a, b, err_state);
234             }
235         } else {
236             zero_count++;
237         }
238     }
239 
240     if (zero_count == size) {
241         return HI_ERR_FAILURE;
242     }
243     return HI_ERR_SUCCESS;
244 }
245 
246