• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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