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