xref: /dpdk/drivers/common/dpaax/caamflib/rta/math_cmd.h (revision 882f25383499f422dc36cfd96ea688a92fb47d94)
1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2  *
3  * Copyright 2008-2016 Freescale Semiconductor Inc.
4  * Copyright 2016,2019 NXP
5  */
6 
7 #ifndef __RTA_MATH_CMD_H__
8 #define __RTA_MATH_CMD_H__
9 
10 extern enum rta_sec_era rta_sec_era;
11 
12 static const uint32_t math_op1[][2] = {
13 /*1*/	{ MATH0,     MATH_SRC0_REG0 },
14 	{ MATH1,     MATH_SRC0_REG1 },
15 	{ MATH2,     MATH_SRC0_REG2 },
16 	{ MATH3,     MATH_SRC0_REG3 },
17 	{ SEQINSZ,   MATH_SRC0_SEQINLEN },
18 	{ SEQOUTSZ,  MATH_SRC0_SEQOUTLEN },
19 	{ VSEQINSZ,  MATH_SRC0_VARSEQINLEN },
20 	{ VSEQOUTSZ, MATH_SRC0_VARSEQOUTLEN },
21 	{ ZERO,      MATH_SRC0_ZERO },
22 /*10*/	{ NONE,      0 }, /* dummy value */
23 	{ DPOVRD,    MATH_SRC0_DPOVRD },
24 	{ ONE,       MATH_SRC0_ONE }
25 };
26 
27 /*
28  * Allowed MATH op1 sources for each SEC Era.
29  * Values represent the number of entries from math_op1[] that are supported.
30  */
31 static const unsigned int math_op1_sz[] = {10, 10, 12, 12, 12, 12,
32 					   12, 12, 12, 12};
33 
34 static const uint32_t math_op2[][2] = {
35 /*1*/	{ MATH0,     MATH_SRC1_REG0 },
36 	{ MATH1,     MATH_SRC1_REG1 },
37 	{ MATH2,     MATH_SRC1_REG2 },
38 	{ MATH3,     MATH_SRC1_REG3 },
39 	{ ABD,       MATH_SRC1_INFIFO },
40 	{ OFIFO,     MATH_SRC1_OUTFIFO },
41 	{ ONE,       MATH_SRC1_ONE },
42 /*8*/	{ NONE,      0 }, /* dummy value */
43 	{ JOBSRC,    MATH_SRC1_JOBSOURCE },
44 	{ DPOVRD,    MATH_SRC1_DPOVRD },
45 	{ VSEQINSZ,  MATH_SRC1_VARSEQINLEN },
46 	{ VSEQOUTSZ, MATH_SRC1_VARSEQOUTLEN },
47 /*13*/	{ ZERO,      MATH_SRC1_ZERO }
48 };
49 
50 /*
51  * Allowed MATH op2 sources for each SEC Era.
52  * Values represent the number of entries from math_op2[] that are supported.
53  */
54 static const unsigned int math_op2_sz[] = {8, 9, 13, 13, 13, 13, 13, 13,
55 					   13, 13};
56 
57 static const uint32_t math_result[][2] = {
58 /*1*/	{ MATH0,     MATH_DEST_REG0 },
59 	{ MATH1,     MATH_DEST_REG1 },
60 	{ MATH2,     MATH_DEST_REG2 },
61 	{ MATH3,     MATH_DEST_REG3 },
62 	{ SEQINSZ,   MATH_DEST_SEQINLEN },
63 	{ SEQOUTSZ,  MATH_DEST_SEQOUTLEN },
64 	{ VSEQINSZ,  MATH_DEST_VARSEQINLEN },
65 	{ VSEQOUTSZ, MATH_DEST_VARSEQOUTLEN },
66 /*9*/	{ NONE,      MATH_DEST_NONE },
67 	{ DPOVRD,    MATH_DEST_DPOVRD }
68 };
69 
70 /*
71  * Allowed MATH result destinations for each SEC Era.
72  * Values represent the number of entries from math_result[] that are
73  * supported.
74  */
75 static const unsigned int math_result_sz[] = {9, 9, 10, 10, 10, 10, 10, 10,
76 					      10, 10};
77 
78 static inline int
rta_math(struct program * program,uint64_t operand1,uint32_t op,uint64_t operand2,uint32_t result,int length,uint32_t options)79 rta_math(struct program *program, uint64_t operand1,
80 	 uint32_t op, uint64_t operand2, uint32_t result,
81 	 int length, uint32_t options)
82 {
83 	uint32_t opcode = CMD_MATH;
84 	uint32_t val = 0;
85 	int ret = -EINVAL;
86 	unsigned int start_pc = program->current_pc;
87 
88 	if (options & SWP) {
89 		if ((options & IFB) ||
90 		    (!(options & IMMED) && !(options & IMMED2)) ||
91 		    ((options & IMMED) && (options & IMMED2))) {
92 			pr_err("MATH: SWP - invalid configuration. SEC PC: %d; Instr: %d\n",
93 			       program->current_pc,
94 			       program->current_instruction);
95 			goto err;
96 		}
97 	}
98 
99 	/*
100 	 * SHLD operation is different from others and we
101 	 * assume that we can have _NONE as first operand
102 	 * or _SEQINSZ as second operand
103 	 */
104 	if ((op != MATH_FUN_SHLD) && ((operand1 == NONE) ||
105 				      (operand2 == SEQINSZ))) {
106 		pr_err("MATH: Invalid operand. SEC PC: %d; Instr: %d\n",
107 		       program->current_pc, program->current_instruction);
108 		goto err;
109 	}
110 
111 	/*
112 	 * We first check if it is unary operation. In that
113 	 * case second operand must be _NONE
114 	 */
115 	if (((op == MATH_FUN_ZBYT) || (op == MATH_FUN_BSWAP)) &&
116 	    (operand2 != NONE)) {
117 		pr_err("MATH: Invalid operand2. SEC PC: %d; Instr: %d\n",
118 		       program->current_pc, program->current_instruction);
119 		goto err;
120 	}
121 
122 	/* Write first operand field */
123 	if (options & IMMED) {
124 		opcode |= MATH_SRC0_IMM;
125 	} else {
126 		ret = __rta_map_opcode((uint32_t)operand1, math_op1,
127 				       math_op1_sz[rta_sec_era], &val);
128 		if (ret < 0) {
129 			pr_err("MATH: operand1 not supported. SEC PC: %d; Instr: %d\n",
130 			       program->current_pc,
131 			       program->current_instruction);
132 			goto err;
133 		}
134 		opcode |= val;
135 	}
136 
137 	/* Write second operand field */
138 	if (options & IMMED2) {
139 		opcode |= MATH_SRC1_IMM;
140 	} else {
141 		ret = __rta_map_opcode((uint32_t)operand2, math_op2,
142 				       math_op2_sz[rta_sec_era], &val);
143 		if (ret < 0) {
144 			pr_err("MATH: operand2 not supported. SEC PC: %d; Instr: %d\n",
145 			       program->current_pc,
146 			       program->current_instruction);
147 			goto err;
148 		}
149 		opcode |= val;
150 	}
151 
152 	/* Write result field */
153 	ret = __rta_map_opcode(result, math_result, math_result_sz[rta_sec_era],
154 			       &val);
155 	if (ret < 0) {
156 		pr_err("MATH: result not supported. SEC PC: %d; Instr: %d\n",
157 		       program->current_pc, program->current_instruction);
158 		goto err;
159 	}
160 	opcode |= val;
161 
162 	/*
163 	 * as we encode operations with their "real" values, we do not
164 	 * to translate but we do need to validate the value
165 	 */
166 	switch (op) {
167 	/*Binary operators */
168 	case (MATH_FUN_ADD):
169 	case (MATH_FUN_ADDC):
170 	case (MATH_FUN_SUB):
171 	case (MATH_FUN_SUBB):
172 	case (MATH_FUN_OR):
173 	case (MATH_FUN_AND):
174 	case (MATH_FUN_XOR):
175 	case (MATH_FUN_LSHIFT):
176 	case (MATH_FUN_RSHIFT):
177 	case (MATH_FUN_SHLD):
178 	/* Unary operators */
179 	case (MATH_FUN_ZBYT):
180 	case (MATH_FUN_BSWAP):
181 		opcode |= op;
182 		break;
183 	default:
184 		pr_err("MATH: operator is not supported. SEC PC: %d; Instr: %d\n",
185 		       program->current_pc, program->current_instruction);
186 		ret = -EINVAL;
187 		goto err;
188 	}
189 
190 	opcode |= (options & ~(IMMED | IMMED2));
191 
192 	/* Verify length */
193 	switch (length) {
194 	case (1):
195 		opcode |= MATH_LEN_1BYTE;
196 		break;
197 	case (2):
198 		opcode |= MATH_LEN_2BYTE;
199 		break;
200 	case (4):
201 		opcode |= MATH_LEN_4BYTE;
202 		break;
203 	case (8):
204 		opcode |= MATH_LEN_8BYTE;
205 		break;
206 	default:
207 		pr_err("MATH: length is not supported. SEC PC: %d; Instr: %d\n",
208 		       program->current_pc, program->current_instruction);
209 		ret = -EINVAL;
210 		goto err;
211 	}
212 
213 	__rta_out32(program, opcode);
214 	program->current_instruction++;
215 
216 	/* Write immediate value */
217 	if ((options & IMMED) && !(options & IMMED2)) {
218 		__rta_out64(program, (length > 4) && !(options & IFB),
219 			    operand1);
220 	} else if ((options & IMMED2) && !(options & IMMED)) {
221 		__rta_out64(program, (length > 4) && !(options & IFB),
222 			    operand2);
223 	} else if ((options & IMMED) && (options & IMMED2)) {
224 		__rta_out32(program, lower_32_bits(operand1));
225 		__rta_out32(program, lower_32_bits(operand2));
226 	}
227 
228 	return (int)start_pc;
229 
230  err:
231 	program->first_error_pc = start_pc;
232 	program->current_instruction++;
233 	return ret;
234 }
235 
236 static inline int
rta_mathi(struct program * program,uint64_t operand,uint32_t op,uint8_t imm,uint32_t result,int length,uint32_t options)237 rta_mathi(struct program *program, uint64_t operand,
238 	  uint32_t op, uint8_t imm, uint32_t result,
239 	  int length, uint32_t options)
240 {
241 	uint32_t opcode = CMD_MATHI;
242 	uint32_t val = 0;
243 	int ret = -EINVAL;
244 	unsigned int start_pc = program->current_pc;
245 
246 	if (((op == MATH_FUN_FBYT) && (options & SSEL))) {
247 		pr_err("MATHI: Illegal combination - FBYT and SSEL. SEC PC: %d; Instr: %d\n",
248 		       program->current_pc, program->current_instruction);
249 		goto err;
250 	}
251 
252 	/* Write first operand field */
253 	if (!(options & SSEL))
254 		ret = __rta_map_opcode((uint32_t)operand, math_op1,
255 				       math_op1_sz[rta_sec_era], &val);
256 	else
257 		ret = __rta_map_opcode((uint32_t)operand, math_op2,
258 				       math_op2_sz[rta_sec_era], &val);
259 	if (ret < 0) {
260 		pr_err("MATHI: operand not supported. SEC PC: %d; Instr: %d\n",
261 		       program->current_pc, program->current_instruction);
262 		goto err;
263 	}
264 
265 	if (!(options & SSEL))
266 		opcode |= val;
267 	else
268 		opcode |= (val << (MATHI_SRC1_SHIFT - MATH_SRC1_SHIFT));
269 
270 	/* Write second operand field */
271 	opcode |= (imm << MATHI_IMM_SHIFT);
272 
273 	/* Write result field */
274 	ret = __rta_map_opcode(result, math_result, math_result_sz[rta_sec_era],
275 			       &val);
276 	if (ret < 0) {
277 		pr_err("MATHI: result not supported. SEC PC: %d; Instr: %d\n",
278 		       program->current_pc, program->current_instruction);
279 		goto err;
280 	}
281 	opcode |= (val << (MATHI_DEST_SHIFT - MATH_DEST_SHIFT));
282 
283 	/*
284 	 * as we encode operations with their "real" values, we do not have to
285 	 * translate but we do need to validate the value
286 	 */
287 	switch (op) {
288 	case (MATH_FUN_ADD):
289 	case (MATH_FUN_ADDC):
290 	case (MATH_FUN_SUB):
291 	case (MATH_FUN_SUBB):
292 	case (MATH_FUN_OR):
293 	case (MATH_FUN_AND):
294 	case (MATH_FUN_XOR):
295 	case (MATH_FUN_LSHIFT):
296 	case (MATH_FUN_RSHIFT):
297 	case (MATH_FUN_FBYT):
298 		opcode |= op;
299 		break;
300 	default:
301 		pr_err("MATHI: operator not supported. SEC PC: %d; Instr: %d\n",
302 		       program->current_pc, program->current_instruction);
303 		ret = -EINVAL;
304 		goto err;
305 	}
306 
307 	opcode |= options;
308 
309 	/* Verify length */
310 	switch (length) {
311 	case (1):
312 		opcode |= MATH_LEN_1BYTE;
313 		break;
314 	case (2):
315 		opcode |= MATH_LEN_2BYTE;
316 		break;
317 	case (4):
318 		opcode |= MATH_LEN_4BYTE;
319 		break;
320 	case (8):
321 		opcode |= MATH_LEN_8BYTE;
322 		break;
323 	default:
324 		pr_err("MATHI: length %d not supported. SEC PC: %d; Instr: %d\n",
325 		       length, program->current_pc,
326 		       program->current_instruction);
327 		ret = -EINVAL;
328 		goto err;
329 	}
330 
331 	__rta_out32(program, opcode);
332 	program->current_instruction++;
333 
334 	return (int)start_pc;
335 
336  err:
337 	program->first_error_pc = start_pc;
338 	program->current_instruction++;
339 	return ret;
340 }
341 
342 #endif /* __RTA_MATH_CMD_H__ */
343