1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include "hal_efuse.h"
20 #include "drv_osal_lib.h"
21
22 #ifdef EFUSE_SUPPORT
23 hi_u8 *g_efuse_otp_reg_base = HI_NULL;
24
25 #define EFUSE_REG_BASE_ADDR g_efuse_otp_reg_base
26 #define CIPHER_KD_WKEY0 (EFUSE_REG_BASE_ADDR + 0x00)
27 #define CIPHER_KD_WKEY1 (EFUSE_REG_BASE_ADDR + 0x04)
28 #define CIPHER_KD_WKEY2 (EFUSE_REG_BASE_ADDR + 0x08)
29 #define CIPHER_KD_WKEY3 (EFUSE_REG_BASE_ADDR + 0x0c)
30 #define CIPHER_KD_CTRL (EFUSE_REG_BASE_ADDR + 0x10)
31 #define CIPHER_KD_STA (EFUSE_REG_BASE_ADDR + 0x14)
32 #define OTP_PGM_TIME (EFUSE_REG_BASE_ADDR + 0x18)
33 #define OTP_RD_TIME (EFUSE_REG_BASE_ADDR + 0x1c)
34 #define OTP_LOGIC_LEVEL (EFUSE_REG_BASE_ADDR + 0x20)
35 #define kd_ctl_mode_cipher_key_addr(chn_id) (chn_id << 8)
36 #define kd_ctl_mode_opt_key_addr(opt_id) (opt_id << 4)
37 #define KD_CTL_MODE_HASH_KL 0x8
38 #define KD_CTL_MODE_OPT_KD 0x4
39 #define KD_CTL_MODE_CIPHER_KL 0x2
40 #define KD_CTL_MODE_START 0x1
41 #define KD_TIME_OUT 1000
42
43 #define REG_SYS_EFUSE_CLK_ADDR_PHY 0x120100D8
44
45 /* Define the union cipher_kd_sta */
46 typedef union {
47 /* Define the struct bits */
48 struct {
49 hi_u32 cipher_kl_finish : 1; /* [0] */
50 hi_u32 hash_key_read_busy : 1; /* [1] */
51 hi_u32 reserved_3 : 25; /* [26..2] */
52 hi_u32 ctrl_rdy : 1; /* [27] */
53 hi_u32 ctrl_busy0 : 1; /* [28] */
54 hi_u32 ctrl_busy1 : 1; /* [29] */
55 hi_u32 key_wt_error : 1; /* [30] */
56 hi_u32 key_wt_finish : 1; /* [31] */
57 } bits;
58
59 /* Define an unsigned member */
60 hi_u32 u32;
61 } cipher_kd_sta;
62
63 static hi_u32 g_is_efuse_busy_flag = HI_FALSE;
64
hal_efuse_otp_init(hi_void)65 hi_s32 hal_efuse_otp_init(hi_void)
66 {
67 hi_u32 crg_value;
68 hi_u32 *sys_addr;
69
70 sys_addr = crypto_ioremap_nocache(REG_SYS_EFUSE_CLK_ADDR_PHY, 0x100); // 0x100 for phy addr
71 if (sys_addr == HI_NULL) {
72 hi_log_error("Error! addr ioremap failed!\n");
73 return HI_ERR_CIPHER_FAILED_MEM;
74 }
75
76 hal_cipher_read_reg(sys_addr, &crg_value);
77 crg_value |= 0x01; /* reset */
78 crg_value |= 0x02; /* set the bit 0, clock opened */
79 hal_cipher_write_reg(sys_addr, crg_value);
80
81 /* clock select and cancel reset 0x30100. */
82 crg_value &= (~0x01); /* cancel reset. */
83 crg_value |= 0x02; /* set the bit 0, clock opened */
84 hal_cipher_write_reg(sys_addr, crg_value);
85
86 crypto_iounmap(sys_addr, 0x100);
87
88 g_efuse_otp_reg_base = crypto_ioremap_nocache(ENFUSE_REG_BASE_ADDR_PHY, 0x100);
89 if (g_efuse_otp_reg_base == HI_NULL) {
90 hi_log_error("ERROR: osal_ioremap_nocache for EFUSE failed!!\n");
91 return HI_ERR_CIPHER_FAILED_MEM;
92 }
93
94 return HI_SUCCESS;
95 }
96
hal_efuse_wait_write_key(hi_void)97 hi_s32 hal_efuse_wait_write_key(hi_void)
98 {
99 cipher_kd_sta efuse_sta;
100 hi_u32 ul_start_time, ul_last_time, ul_dura_time;
101
102 /* wait for hash_rdy */
103 ul_start_time = osal_get_tickcount();
104 for (;;) {
105 hal_cipher_read_reg(CIPHER_KD_STA, &efuse_sta.u32);
106 if (efuse_sta.bits.key_wt_finish == 1) {
107 break;
108 }
109
110 ul_last_time = osal_get_tickcount();
111 ul_dura_time = ul_last_time - ul_start_time;
112 if (ul_dura_time >= KD_TIME_OUT) {
113 hi_log_error("Error! efuse write key time out!\n");
114 return HI_ERR_CIPHER_TIMEOUT;
115 }
116
117 osal_msleep(1);
118 }
119 return HI_SUCCESS;
120 }
121
hal_efuse_wait_cipher_load_key(hi_void)122 hi_s32 hal_efuse_wait_cipher_load_key(hi_void)
123 {
124 cipher_kd_sta efuse_sta;
125 hi_u32 ul_start_time, ul_last_time, ul_dura_time;
126
127 ul_start_time = osal_get_tickcount();
128
129 while (1) {
130 hal_cipher_read_reg(CIPHER_KD_STA, &efuse_sta.u32);
131 if (efuse_sta.bits.cipher_kl_finish == 1) {
132 break;
133 }
134
135 ul_last_time = osal_get_tickcount();
136 ul_dura_time = ul_last_time - ul_start_time;
137 if (ul_dura_time >= KD_TIME_OUT) {
138 hi_log_error("Error! efuse load key time out!\n");
139 return HI_ERR_CIPHER_TIMEOUT;
140 }
141 osal_msleep(1);
142 }
143 return HI_SUCCESS;
144 }
145
hal_efuse_wait_hash_load_key(hi_void)146 hi_s32 hal_efuse_wait_hash_load_key(hi_void)
147 {
148 cipher_kd_sta efuse_sta;
149 hi_u32 ul_start_time, ul_last_time, ul_dura_time;
150
151 ul_start_time = osal_get_tickcount();
152
153 while (1) {
154 hal_cipher_read_reg(CIPHER_KD_STA, &efuse_sta.u32);
155 if (efuse_sta.bits.hash_key_read_busy == 0) {
156 break;
157 }
158
159 ul_last_time = osal_get_tickcount();
160 ul_dura_time = ul_last_time - ul_start_time;
161 if (ul_dura_time >= KD_TIME_OUT) {
162 hi_log_error("Error! efuse load key out!\n");
163 return HI_ERR_CIPHER_TIMEOUT;
164 }
165 osal_msleep(1);
166 }
167 return HI_SUCCESS;
168 }
169
hal_efuse_wait_ready(hi_void)170 hi_s32 hal_efuse_wait_ready(hi_void)
171 {
172 cipher_kd_sta efuse_sta;
173 hi_u32 ul_start_time, ul_last_time, ul_dura_time;
174
175 ul_start_time = osal_get_tickcount();
176
177 while (1) {
178 hal_cipher_read_reg(CIPHER_KD_STA, &efuse_sta.u32);
179 if (efuse_sta.bits.ctrl_rdy && (!efuse_sta.bits.ctrl_busy1) && (!efuse_sta.bits.ctrl_busy0)) {
180 break;
181 }
182
183 ul_last_time = osal_get_tickcount();
184 ul_dura_time = ul_last_time - ul_start_time;
185 if (ul_dura_time >= KD_TIME_OUT) {
186 hi_log_error("Error! efuse load key out!\n");
187 return HI_ERR_CIPHER_TIMEOUT;
188 }
189 osal_msleep(1);
190 }
191 return HI_SUCCESS;
192 }
193
hal_efuse_get_err_stat(hi_void)194 hi_s32 hal_efuse_get_err_stat(hi_void)
195 {
196 cipher_kd_sta efuse_sta;
197
198 hal_cipher_read_reg(CIPHER_KD_STA, &efuse_sta.u32);
199 return efuse_sta.bits.key_wt_error;
200 }
201
hal_efuse_write_key(hi_u32 * p_key,hi_u32 opt_id)202 hi_s32 hal_efuse_write_key(hi_u32 *p_key, hi_u32 opt_id)
203 {
204 hi_s32 ret;
205 hi_u32 kd_ctl_mode;
206
207 if (g_is_efuse_busy_flag != HI_FALSE) {
208 return HI_ERR_CIPHER_BUSY;
209 }
210
211 g_is_efuse_busy_flag = HI_TRUE;
212 kd_ctl_mode = kd_ctl_mode_opt_key_addr(opt_id) | KD_CTL_MODE_OPT_KD | KD_CTL_MODE_START;
213
214 hal_cipher_write_reg(CIPHER_KD_WKEY0, *p_key);
215 hal_cipher_write_reg(CIPHER_KD_WKEY1, *(p_key + WORD_IDX_1));
216 hal_cipher_write_reg(CIPHER_KD_WKEY2, *(p_key + WORD_IDX_2));
217 hal_cipher_write_reg(CIPHER_KD_WKEY3, *(p_key + WORD_IDX_3));
218
219 ret = hal_efuse_wait_ready();
220 if (ret != HI_SUCCESS) {
221 hi_log_print_func_err(hal_efuse_wait_ready, ret);
222 g_is_efuse_busy_flag = HI_FALSE;
223 return ret;
224 }
225
226 hal_cipher_write_reg(CIPHER_KD_CTRL, kd_ctl_mode);
227
228 ret = hal_efuse_wait_write_key();
229 if (ret != HI_SUCCESS) {
230 hi_log_print_func_err(hal_efuse_wait_write_key, ret);
231 g_is_efuse_busy_flag = HI_FALSE;
232 return ret;
233 }
234
235 ret = hal_efuse_get_err_stat()
236 if (ret != HI_SUCCESS) {
237 hi_log_error("efuse key is already write.\n");
238 hi_log_print_func_err(hal_efuse_get_err_stat, ret);
239 g_is_efuse_busy_flag = HI_FALSE;
240 return ret;
241 }
242
243 g_is_efuse_busy_flag = HI_FALSE;
244 return HI_SUCCESS;
245 }
246
hal_efuse_otp_load_cipher_key(hi_u32 chn_id,hi_u32 opt_id)247 hi_s32 hal_efuse_otp_load_cipher_key(hi_u32 chn_id, hi_u32 opt_id)
248 {
249 hi_s32 ret;
250 hi_u32 kd_ctl_mode;
251
252 if (g_is_efuse_busy_flag != HI_FALSE) {
253 return HI_ERR_CIPHER_BUSY;
254 }
255
256 g_is_efuse_busy_flag = HI_TRUE;
257
258 kd_ctl_mode = (kd_ctl_mode_cipher_key_addr(chn_id) | kd_ctl_mode_opt_key_addr(opt_id) | \
259 KD_CTL_MODE_CIPHER_KL | KD_CTL_MODE_START);
260
261 ret = hal_efuse_wait_ready();
262 if (ret != HI_SUCCESS) {
263 hi_log_print_func_err(hal_efuse_wait_ready, ret);
264 g_is_efuse_busy_flag = HI_FALSE;
265 return ret;
266 }
267
268 hal_cipher_write_reg(CIPHER_KD_CTRL, kd_ctl_mode);
269 ret = hal_efuse_wait_cipher_load_key();
270 if (ret != HI_SUCCESS) {
271 g_is_efuse_busy_flag = HI_FALSE;
272 hi_log_print_func_err(hal_efuse_wait_cipher_load_key, ret);
273 return ret;
274 }
275
276 g_is_efuse_busy_flag = HI_FALSE;
277 return HI_SUCCESS;
278 }
279
hal_efuse_load_hash_key(hi_u32 opt_id)280 hi_s32 hal_efuse_load_hash_key(hi_u32 opt_id)
281 {
282 hi_s32 ret;
283 hi_u32 kd_ctl_mode;
284
285 if (g_is_efuse_busy_flag == HI_TRUE) {
286 return HI_ERR_CIPHER_BUSY;
287 }
288
289 g_is_efuse_busy_flag = HI_TRUE;
290
291 kd_ctl_mode = (kd_ctl_mode_opt_key_addr(opt_id) | KD_CTL_MODE_HASH_KL | KD_CTL_MODE_START);
292 ret = hal_efuse_wait_ready();
293 if (ret != HI_SUCCESS) {
294 hi_log_print_func_err(hal_efuse_wait_ready, ret);
295 g_is_efuse_busy_flag = HI_FALSE;
296 return ret;
297 }
298
299 hal_cipher_write_reg(CIPHER_KD_CTRL, kd_ctl_mode);
300 ret = hal_efuse_wait_hash_load_key();
301 if (ret != HI_SUCCESS) {
302 g_is_efuse_busy_flag = HI_FALSE;
303 hi_log_print_func_err(hal_efuse_wait_hash_load_key, ret);
304 return ret;
305 }
306
307 g_is_efuse_busy_flag = HI_FALSE;
308 return HI_SUCCESS;
309 }
310
hal_efuse_otp_set_reg_base(hi_u8 * reg_base)311 hi_void hal_efuse_otp_set_reg_base(hi_u8 *reg_base)
312 {
313 g_efuse_otp_reg_base = reg_base;
314 }
315
hal_efuse_otp_get_reg_base(hi_void)316 hi_u8 *hal_efuse_otp_get_reg_base(hi_void)
317 {
318 return g_efuse_otp_reg_base;
319 }
320 #endif
321