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