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