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