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 (((op == MATH_FUN_BSWAP) && (rta_sec_era < RTA_SEC_ERA_4)) ||
89 ((op == MATH_FUN_ZBYT) && (rta_sec_era < RTA_SEC_ERA_2))) {
90 pr_err("MATH: operation not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
91 USER_SEC_ERA(rta_sec_era), program->current_pc,
92 program->current_instruction);
93 goto err;
94 }
95
96 if (options & SWP) {
97 if (rta_sec_era < RTA_SEC_ERA_7) {
98 pr_err("MATH: operation not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
99 USER_SEC_ERA(rta_sec_era), program->current_pc,
100 program->current_instruction);
101 goto err;
102 }
103
104 if ((options & IFB) ||
105 (!(options & IMMED) && !(options & IMMED2)) ||
106 ((options & IMMED) && (options & IMMED2))) {
107 pr_err("MATH: SWP - invalid configuration. SEC PC: %d; Instr: %d\n",
108 program->current_pc,
109 program->current_instruction);
110 goto err;
111 }
112 }
113
114 /*
115 * SHLD operation is different from others and we
116 * assume that we can have _NONE as first operand
117 * or _SEQINSZ as second operand
118 */
119 if ((op != MATH_FUN_SHLD) && ((operand1 == NONE) ||
120 (operand2 == SEQINSZ))) {
121 pr_err("MATH: Invalid operand. SEC PC: %d; Instr: %d\n",
122 program->current_pc, program->current_instruction);
123 goto err;
124 }
125
126 /*
127 * We first check if it is unary operation. In that
128 * case second operand must be _NONE
129 */
130 if (((op == MATH_FUN_ZBYT) || (op == MATH_FUN_BSWAP)) &&
131 (operand2 != NONE)) {
132 pr_err("MATH: Invalid operand2. SEC PC: %d; Instr: %d\n",
133 program->current_pc, program->current_instruction);
134 goto err;
135 }
136
137 /* Write first operand field */
138 if (options & IMMED) {
139 opcode |= MATH_SRC0_IMM;
140 } else {
141 ret = __rta_map_opcode((uint32_t)operand1, math_op1,
142 math_op1_sz[rta_sec_era], &val);
143 if (ret < 0) {
144 pr_err("MATH: operand1 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 second operand field */
153 if (options & IMMED2) {
154 opcode |= MATH_SRC1_IMM;
155 } else {
156 ret = __rta_map_opcode((uint32_t)operand2, math_op2,
157 math_op2_sz[rta_sec_era], &val);
158 if (ret < 0) {
159 pr_err("MATH: operand2 not supported. SEC PC: %d; Instr: %d\n",
160 program->current_pc,
161 program->current_instruction);
162 goto err;
163 }
164 opcode |= val;
165 }
166
167 /* Write result field */
168 ret = __rta_map_opcode(result, math_result, math_result_sz[rta_sec_era],
169 &val);
170 if (ret < 0) {
171 pr_err("MATH: result not supported. SEC PC: %d; Instr: %d\n",
172 program->current_pc, program->current_instruction);
173 goto err;
174 }
175 opcode |= val;
176
177 /*
178 * as we encode operations with their "real" values, we do not
179 * to translate but we do need to validate the value
180 */
181 switch (op) {
182 /*Binary operators */
183 case (MATH_FUN_ADD):
184 case (MATH_FUN_ADDC):
185 case (MATH_FUN_SUB):
186 case (MATH_FUN_SUBB):
187 case (MATH_FUN_OR):
188 case (MATH_FUN_AND):
189 case (MATH_FUN_XOR):
190 case (MATH_FUN_LSHIFT):
191 case (MATH_FUN_RSHIFT):
192 case (MATH_FUN_SHLD):
193 /* Unary operators */
194 case (MATH_FUN_ZBYT):
195 case (MATH_FUN_BSWAP):
196 opcode |= op;
197 break;
198 default:
199 pr_err("MATH: operator is not supported. SEC PC: %d; Instr: %d\n",
200 program->current_pc, program->current_instruction);
201 ret = -EINVAL;
202 goto err;
203 }
204
205 opcode |= (options & ~(IMMED | IMMED2));
206
207 /* Verify length */
208 switch (length) {
209 case (1):
210 opcode |= MATH_LEN_1BYTE;
211 break;
212 case (2):
213 opcode |= MATH_LEN_2BYTE;
214 break;
215 case (4):
216 opcode |= MATH_LEN_4BYTE;
217 break;
218 case (8):
219 opcode |= MATH_LEN_8BYTE;
220 break;
221 default:
222 pr_err("MATH: length is not supported. SEC PC: %d; Instr: %d\n",
223 program->current_pc, program->current_instruction);
224 ret = -EINVAL;
225 goto err;
226 }
227
228 __rta_out32(program, opcode);
229 program->current_instruction++;
230
231 /* Write immediate value */
232 if ((options & IMMED) && !(options & IMMED2)) {
233 __rta_out64(program, (length > 4) && !(options & IFB),
234 operand1);
235 } else if ((options & IMMED2) && !(options & IMMED)) {
236 __rta_out64(program, (length > 4) && !(options & IFB),
237 operand2);
238 } else if ((options & IMMED) && (options & IMMED2)) {
239 __rta_out32(program, lower_32_bits(operand1));
240 __rta_out32(program, lower_32_bits(operand2));
241 }
242
243 return (int)start_pc;
244
245 err:
246 program->first_error_pc = start_pc;
247 program->current_instruction++;
248 return ret;
249 }
250
251 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)252 rta_mathi(struct program *program, uint64_t operand,
253 uint32_t op, uint8_t imm, uint32_t result,
254 int length, uint32_t options)
255 {
256 uint32_t opcode = CMD_MATHI;
257 uint32_t val = 0;
258 int ret = -EINVAL;
259 unsigned int start_pc = program->current_pc;
260
261 if (rta_sec_era < RTA_SEC_ERA_6) {
262 pr_err("MATHI: Command not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
263 USER_SEC_ERA(rta_sec_era), program->current_pc,
264 program->current_instruction);
265 goto err;
266 }
267
268 if (((op == MATH_FUN_FBYT) && (options & SSEL))) {
269 pr_err("MATHI: Illegal combination - FBYT and SSEL. SEC PC: %d; Instr: %d\n",
270 program->current_pc, program->current_instruction);
271 goto err;
272 }
273
274 if ((options & SWP) && (rta_sec_era < RTA_SEC_ERA_7)) {
275 pr_err("MATHI: SWP not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
276 USER_SEC_ERA(rta_sec_era), program->current_pc,
277 program->current_instruction);
278 goto err;
279 }
280
281 /* Write first operand field */
282 if (!(options & SSEL))
283 ret = __rta_map_opcode((uint32_t)operand, math_op1,
284 math_op1_sz[rta_sec_era], &val);
285 else
286 ret = __rta_map_opcode((uint32_t)operand, math_op2,
287 math_op2_sz[rta_sec_era], &val);
288 if (ret < 0) {
289 pr_err("MATHI: operand not supported. SEC PC: %d; Instr: %d\n",
290 program->current_pc, program->current_instruction);
291 goto err;
292 }
293
294 if (!(options & SSEL))
295 opcode |= val;
296 else
297 opcode |= (val << (MATHI_SRC1_SHIFT - MATH_SRC1_SHIFT));
298
299 /* Write second operand field */
300 opcode |= (imm << MATHI_IMM_SHIFT);
301
302 /* Write result field */
303 ret = __rta_map_opcode(result, math_result, math_result_sz[rta_sec_era],
304 &val);
305 if (ret < 0) {
306 pr_err("MATHI: result not supported. SEC PC: %d; Instr: %d\n",
307 program->current_pc, program->current_instruction);
308 goto err;
309 }
310 opcode |= (val << (MATHI_DEST_SHIFT - MATH_DEST_SHIFT));
311
312 /*
313 * as we encode operations with their "real" values, we do not have to
314 * translate but we do need to validate the value
315 */
316 switch (op) {
317 case (MATH_FUN_ADD):
318 case (MATH_FUN_ADDC):
319 case (MATH_FUN_SUB):
320 case (MATH_FUN_SUBB):
321 case (MATH_FUN_OR):
322 case (MATH_FUN_AND):
323 case (MATH_FUN_XOR):
324 case (MATH_FUN_LSHIFT):
325 case (MATH_FUN_RSHIFT):
326 case (MATH_FUN_FBYT):
327 opcode |= op;
328 break;
329 default:
330 pr_err("MATHI: operator not supported. SEC PC: %d; Instr: %d\n",
331 program->current_pc, program->current_instruction);
332 ret = -EINVAL;
333 goto err;
334 }
335
336 opcode |= options;
337
338 /* Verify length */
339 switch (length) {
340 case (1):
341 opcode |= MATH_LEN_1BYTE;
342 break;
343 case (2):
344 opcode |= MATH_LEN_2BYTE;
345 break;
346 case (4):
347 opcode |= MATH_LEN_4BYTE;
348 break;
349 case (8):
350 opcode |= MATH_LEN_8BYTE;
351 break;
352 default:
353 pr_err("MATHI: length %d not supported. SEC PC: %d; Instr: %d\n",
354 length, program->current_pc,
355 program->current_instruction);
356 ret = -EINVAL;
357 goto err;
358 }
359
360 __rta_out32(program, opcode);
361 program->current_instruction++;
362
363 return (int)start_pc;
364
365 err:
366 program->first_error_pc = start_pc;
367 program->current_instruction++;
368 return ret;
369 }
370
371 #endif /* __RTA_MATH_CMD_H__ */
372