1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright 2022-2024 HiSilicon Limited.
4 * Kunpeng hardware accelerator SEC module init.
5 */
6
7 #include <initcall.h>
8 #include <io.h>
9 #include <malloc.h>
10 #include <sys/queue.h>
11 #include <trace.h>
12 #include <util.h>
13
14 #include "sec_main.h"
15
16 #define AM_CFG_SINGLE_PORT_MAX_TRANS 0x300014
17 #define SEC_CORE_INT_MASK 0x301000
18 #define SEC_CORE_INT_SOURCE 0x301010
19 #define SEC_RAS_CE_ENABLE 0x301050
20 #define SEC_RAS_FE_ENABLE 0x301054
21 #define SEC_RAS_NFE_ENABLE 0x301058
22 #define SEC_MEM_START_INIT 0x301100
23 #define SEC_MEM_INIT_DONE 0x301104
24 #define SEC_CONTROL_REG 0x301200
25 #define SEC_INTERFACE_USER_CTRL0 0x301220
26 #define SEC_INTERFACE_USER_CTRL1 0x301224
27 #define SEC_SAA_EN 0x301270
28 #define SEC_BD_ERR_CHK_EN0 0x301380
29 #define SEC_BD_ERR_CHK_EN1 0x301384
30 #define SEC_BD_ERR_CHK_EN2 0x301388
31 #define SEC_BD_ERR_CHK_EN3 0x30138c
32 #define SEC_DYNAMIC_GATE_V3 0x30121c
33 #define SEC_BD_ERR_CHK_EN2_V3 0x301508
34 #define SEC_CORE_AUTO_GATE_V3 0x30212c
35 #define SEC_INTERFACE_USER_CTRL0_V3 0x302220
36 #define SEC_INTERFACE_USER_CTRL1_V3 0x302224
37 #define SEC_SINGLE_PORT_MAX_TRANS 0x2060
38 #define SEC_ABNML_INT_DISABLE 0x0
39 #define SEC_RAS_CE_ENB_MASK 0x88
40 #define SEC_RAS_FE_ENB 0x0
41 #define SEC_RAS_NFE_ENB_MASK 0x177
42 #define SEC_CLK_GATE_ENABLE BIT(3)
43 #define SEC_DYNAMIC_GATE_EN 0x7bff
44 #define SEC_CORE_AUTO_GATE_EN GENMASK_32(3, 0)
45 #define SEC_TRNG_EN_MASK BIT(8)
46 #define SEC_SAA_ENABLE 0x17f
47 #define SEC_SAA_ENABLE_V3 0xf
48 #define SEC_BD_ERR_CHK0 0xefffffff
49 #define SEC_BD_ERR_CHK1 0x7ffff7fd
50 #define SEC_BD_ERR_CHK2 0xffff7fff
51 #define SEC_BD_ERR_CHK3 0xffffbfff
52 #define SEC_USER0_CFG 0x20200
53 #define SEC_USER0_SMMU_NORMAL (BIT(23) | BIT(15))
54 #define SEC_USER1_CFG 0x12141214
55 #define SEC_USER1_SMMU_NORMAL (BIT(31) | BIT(23) | BIT(15) | BIT(7))
56 #define SEC_USER0_CFG_V3 0x20200
57 #define SEC_USER1_CFG_V3 0x8c494
58
59 static SLIST_HEAD(, acc_device) sec_list = SLIST_HEAD_INITIALIZER(sec_list);
60
sec_create_qp(uint8_t sq_type)61 struct hisi_qp *sec_create_qp(uint8_t sq_type)
62 {
63 struct acc_device *sec_dev = NULL;
64 struct acc_device *cur_dev = NULL;
65 uint32_t free_qp_num = 0;
66 uint32_t max_qp_num = 0;
67
68 /* Find the SEC device with the most remaining qp numbers */
69 SLIST_FOREACH(cur_dev, &sec_list, link) {
70 if (cur_dev->qm.fun_type == HISI_QM_HW_PF)
71 free_qp_num = HISI_QM_PF_Q_NUM - cur_dev->qm.qp_in_used;
72 else
73 free_qp_num = HISI_QM_VF_Q_NUM - cur_dev->qm.qp_in_used;
74 if (free_qp_num > max_qp_num) {
75 max_qp_num = free_qp_num;
76 sec_dev = cur_dev;
77 }
78 }
79
80 if (!sec_dev) {
81 EMSG("No available sec device");
82 return NULL;
83 }
84
85 return hisi_qm_create_qp(&sec_dev->qm, sq_type);
86 }
87
sec_enable_clock_gate(struct hisi_qm * qm)88 static void sec_enable_clock_gate(struct hisi_qm *qm)
89 {
90 if (qm->version == HISI_QM_HW_V2)
91 return;
92
93 io_setbits32(qm->io_base + SEC_CONTROL_REG, SEC_CLK_GATE_ENABLE);
94 io_write32(qm->io_base + SEC_DYNAMIC_GATE_V3, SEC_DYNAMIC_GATE_EN);
95 io_write32(qm->io_base + SEC_CORE_AUTO_GATE_V3, SEC_CORE_AUTO_GATE_EN);
96 }
97
sec_engine_init(struct acc_device * sec_dev)98 static enum hisi_drv_status sec_engine_init(struct acc_device *sec_dev)
99 {
100 struct hisi_qm *qm = &sec_dev->qm;
101 uint32_t val = 0;
102
103 if (qm->fun_type == HISI_QM_HW_VF)
104 return HISI_QM_DRVCRYPT_NO_ERR;
105
106 /* QM_HW_V2 version need to close clock gating */
107 io_clrbits32(qm->io_base + SEC_CONTROL_REG, SEC_CLK_GATE_ENABLE);
108
109 hisi_qm_dev_init(qm);
110
111 io_write32(qm->io_base + SEC_MEM_START_INIT, 0x1);
112 if (IO_READ32_POLL_TIMEOUT(qm->io_base + SEC_MEM_INIT_DONE, val,
113 val & 0x1, POLL_PERIOD, POLL_TIMEOUT)) {
114 EMSG("Fail to init sec mem");
115 return HISI_QM_DRVCRYPT_ETMOUT;
116 }
117
118 io_setbits32(qm->io_base + SEC_CONTROL_REG, sec_dev->endian);
119
120 if (qm->version == HISI_QM_HW_V2) {
121 /* SMMU bypass */
122 io_write32(qm->io_base + SEC_INTERFACE_USER_CTRL0,
123 SEC_USER0_CFG);
124 io_write32(qm->io_base + SEC_INTERFACE_USER_CTRL1,
125 SEC_USER1_CFG);
126 io_write32(qm->io_base + AM_CFG_SINGLE_PORT_MAX_TRANS,
127 SEC_SINGLE_PORT_MAX_TRANS);
128 io_write32(qm->io_base + SEC_SAA_EN, SEC_SAA_ENABLE);
129 /* HW V2 enable SM4 extra mode, as CTR/ECB */
130 io_write32(qm->io_base + SEC_BD_ERR_CHK_EN0, SEC_BD_ERR_CHK0);
131 /* Enable SM4 xts mode multiple iv */
132 io_write32(qm->io_base + SEC_BD_ERR_CHK_EN1, SEC_BD_ERR_CHK1);
133 /* disable PBKDF2 len check */
134 io_write32(qm->io_base + SEC_BD_ERR_CHK_EN2, SEC_BD_ERR_CHK2);
135 io_write32(qm->io_base + SEC_BD_ERR_CHK_EN3, SEC_BD_ERR_CHK3);
136 } else {
137 /* cmd_type is controlled by HAC subctrl, default normal */
138 io_write32(qm->io_base + SEC_INTERFACE_USER_CTRL0_V3,
139 SEC_USER0_CFG_V3);
140 io_write32(qm->io_base + SEC_INTERFACE_USER_CTRL1_V3,
141 SEC_USER1_CFG_V3);
142 io_write32(qm->io_base + SEC_SAA_EN, SEC_SAA_ENABLE_V3);
143 /* disable PBKDF2 salt len check */
144 io_write32(qm->io_base + SEC_BD_ERR_CHK_EN2_V3,
145 SEC_BD_ERR_CHK2);
146 }
147 io_write32(qm->io_base + SEC_RAS_CE_ENABLE, SEC_RAS_CE_ENB_MASK);
148 io_write32(qm->io_base + SEC_RAS_FE_ENABLE, SEC_RAS_FE_ENB);
149 io_write32(qm->io_base + SEC_RAS_NFE_ENABLE, SEC_RAS_NFE_ENB_MASK);
150 io_write32(qm->io_base + SEC_CORE_INT_MASK, SEC_ABNML_INT_DISABLE);
151
152 sec_enable_clock_gate(qm);
153
154 return HISI_QM_DRVCRYPT_NO_ERR;
155 }
156
sec_dev_status_check(struct hisi_qm * qm)157 static enum hisi_drv_status sec_dev_status_check(struct hisi_qm *qm)
158 {
159 uint32_t val = 0;
160
161 val = io_read32(qm->io_base + SEC_CORE_INT_SOURCE);
162 if (val & SEC_RAS_NFE_ENB_MASK) {
163 EMSG("SEC NFE RAS happened, need to reset");
164 return HISI_QM_DRVCRYPT_HW_EACCESS;
165 }
166
167 val = io_read32(qm->io_base + HISI_QM_ABNML_INT_SRC);
168 if (val) {
169 if (val & HISI_QM_SEC_NFE_INT_MASK)
170 EMSG("QM NFE RAS happened, need to reset");
171
172 if (val & HISI_QM_INVALID_DB) {
173 EMSG("QM invalid db happened, please check");
174 io_write32(qm->io_base + HISI_QM_ABNML_INT_SRC,
175 HISI_QM_INVALID_DB);
176 }
177
178 return HISI_QM_DRVCRYPT_HW_EACCESS;
179 }
180
181 return HISI_QM_DRVCRYPT_NO_ERR;
182 }
183
sec_qm_init(struct acc_device * sec_dev)184 static enum hisi_drv_status sec_qm_init(struct acc_device *sec_dev)
185 {
186 struct hisi_qm *qm = &sec_dev->qm;
187
188 qm->io_base = (vaddr_t)phys_to_virt_io(sec_dev->io_base,
189 sec_dev->io_size);
190 if (!qm->io_base) {
191 EMSG("Fail to get qm io_base");
192 return HISI_QM_DRVCRYPT_EFAULT;
193 }
194
195 qm->fun_type = sec_dev->fun_type;
196 qm->vfs_num = sec_dev->vfs_num;
197 qm->sqe_size = SEC_SQE_SIZE;
198 qm->sqe_log2_size = SEC_SQE_LOG2_SIZE;
199 if (qm->fun_type == HISI_QM_HW_PF) {
200 hisi_qm_get_version(qm);
201 DMSG("SEC hardware version is %#"PRIx32, qm->version);
202 qm->qp_base = HISI_QM_PF_Q_BASE;
203 qm->qp_num = HISI_QM_PF_Q_NUM;
204 qm->dev_status_check = sec_dev_status_check;
205 }
206
207 return hisi_qm_init(qm);
208 }
209
sec_alloc(void)210 static struct acc_device *sec_alloc(void)
211 {
212 struct acc_device *sec_dev = NULL;
213
214 sec_dev = calloc(1, sizeof(*sec_dev));
215 if (!sec_dev) {
216 EMSG("Fail to alloc sec_dev");
217 return NULL;
218 }
219
220 sec_dev->io_base = SEC_BAR;
221 sec_dev->io_size = SEC_SIZE;
222 sec_dev->fun_type = HISI_QM_HW_PF;
223 SLIST_INSERT_HEAD(&sec_list, sec_dev, link);
224
225 return sec_dev;
226 }
227
sec_free(struct acc_device * sec_dev)228 static void sec_free(struct acc_device *sec_dev)
229 {
230 SLIST_REMOVE_HEAD(&sec_list, link);
231 free(sec_dev);
232 }
233
sec_probe(void)234 static TEE_Result sec_probe(void)
235 {
236 enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
237 struct acc_device *sec_dev = NULL;
238 struct hisi_qm *qm = NULL;
239
240 DMSG("SEC driver init start");
241 sec_dev = sec_alloc();
242 if (!sec_dev)
243 return TEE_ERROR_OUT_OF_MEMORY;
244
245 qm = &sec_dev->qm;
246 ret = sec_qm_init(sec_dev);
247 if (ret) {
248 EMSG("Fail to init sec qm, ret=%d", ret);
249 goto err_with_pre_init;
250 }
251
252 ret = sec_engine_init(sec_dev);
253 if (ret) {
254 EMSG("fail to init engine, ret=%d", ret);
255 goto err_with_qm_init;
256 }
257
258 ret = hisi_qm_start(qm);
259 if (ret) {
260 EMSG("Fail to start qm, ret=%d", ret);
261 goto err_with_qm_init;
262 }
263
264 DMSG("SEC driver init done");
265 return TEE_SUCCESS;
266
267 err_with_qm_init:
268 hisi_qm_uninit(qm);
269 err_with_pre_init:
270 sec_free(sec_dev);
271
272 return TEE_ERROR_BAD_STATE;
273 }
274
275 driver_init(sec_probe);
276