New upstream version 17.08
[deb_dpdk.git] / drivers / crypto / dpaa2_sec / hw / rta / math_cmd.h
1 /*-
2  * This file is provided under a dual BSD/GPLv2 license. When using or
3  * redistributing this file, you may do so under either license.
4  *
5  *   BSD LICENSE
6  *
7  * Copyright 2008-2016 Freescale Semiconductor Inc.
8  * Copyright 2016 NXP.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  * * Neither the name of the above-listed copyright holders nor the
18  * names of any contributors may be used to endorse or promote products
19  * derived from this software without specific prior written permission.
20  *
21  *   GPL LICENSE SUMMARY
22  *
23  * ALTERNATIVELY, this software may be distributed under the terms of the
24  * GNU General Public License ("GPL") as published by the Free Software
25  * Foundation, either version 2 of that License or (at your option) any
26  * later version.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
32  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  */
40
41 #ifndef __RTA_MATH_CMD_H__
42 #define __RTA_MATH_CMD_H__
43
44 extern enum rta_sec_era rta_sec_era;
45
46 static const uint32_t math_op1[][2] = {
47 /*1*/   { MATH0,     MATH_SRC0_REG0 },
48         { MATH1,     MATH_SRC0_REG1 },
49         { MATH2,     MATH_SRC0_REG2 },
50         { MATH3,     MATH_SRC0_REG3 },
51         { SEQINSZ,   MATH_SRC0_SEQINLEN },
52         { SEQOUTSZ,  MATH_SRC0_SEQOUTLEN },
53         { VSEQINSZ,  MATH_SRC0_VARSEQINLEN },
54         { VSEQOUTSZ, MATH_SRC0_VARSEQOUTLEN },
55         { ZERO,      MATH_SRC0_ZERO },
56 /*10*/  { NONE,      0 }, /* dummy value */
57         { DPOVRD,    MATH_SRC0_DPOVRD },
58         { ONE,       MATH_SRC0_ONE }
59 };
60
61 /*
62  * Allowed MATH op1 sources for each SEC Era.
63  * Values represent the number of entries from math_op1[] that are supported.
64  */
65 static const unsigned int math_op1_sz[] = {10, 10, 12, 12, 12, 12, 12, 12};
66
67 static const uint32_t math_op2[][2] = {
68 /*1*/   { MATH0,     MATH_SRC1_REG0 },
69         { MATH1,     MATH_SRC1_REG1 },
70         { MATH2,     MATH_SRC1_REG2 },
71         { MATH3,     MATH_SRC1_REG3 },
72         { ABD,       MATH_SRC1_INFIFO },
73         { OFIFO,     MATH_SRC1_OUTFIFO },
74         { ONE,       MATH_SRC1_ONE },
75 /*8*/   { NONE,      0 }, /* dummy value */
76         { JOBSRC,    MATH_SRC1_JOBSOURCE },
77         { DPOVRD,    MATH_SRC1_DPOVRD },
78         { VSEQINSZ,  MATH_SRC1_VARSEQINLEN },
79         { VSEQOUTSZ, MATH_SRC1_VARSEQOUTLEN },
80 /*13*/  { ZERO,      MATH_SRC1_ZERO }
81 };
82
83 /*
84  * Allowed MATH op2 sources for each SEC Era.
85  * Values represent the number of entries from math_op2[] that are supported.
86  */
87 static const unsigned int math_op2_sz[] = {8, 9, 13, 13, 13, 13, 13, 13};
88
89 static const uint32_t math_result[][2] = {
90 /*1*/   { MATH0,     MATH_DEST_REG0 },
91         { MATH1,     MATH_DEST_REG1 },
92         { MATH2,     MATH_DEST_REG2 },
93         { MATH3,     MATH_DEST_REG3 },
94         { SEQINSZ,   MATH_DEST_SEQINLEN },
95         { SEQOUTSZ,  MATH_DEST_SEQOUTLEN },
96         { VSEQINSZ,  MATH_DEST_VARSEQINLEN },
97         { VSEQOUTSZ, MATH_DEST_VARSEQOUTLEN },
98 /*9*/   { NONE,      MATH_DEST_NONE },
99         { DPOVRD,    MATH_DEST_DPOVRD }
100 };
101
102 /*
103  * Allowed MATH result destinations for each SEC Era.
104  * Values represent the number of entries from math_result[] that are
105  * supported.
106  */
107 static const unsigned int math_result_sz[] = {9, 9, 10, 10, 10, 10, 10, 10};
108
109 static inline int
110 rta_math(struct program *program, uint64_t operand1,
111          uint32_t op, uint64_t operand2, uint32_t result,
112          int length, uint32_t options)
113 {
114         uint32_t opcode = CMD_MATH;
115         uint32_t val = 0;
116         int ret = -EINVAL;
117         unsigned int start_pc = program->current_pc;
118
119         if (((op == MATH_FUN_BSWAP) && (rta_sec_era < RTA_SEC_ERA_4)) ||
120             ((op == MATH_FUN_ZBYT) && (rta_sec_era < RTA_SEC_ERA_2))) {
121                 pr_err("MATH: operation not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
122                        USER_SEC_ERA(rta_sec_era), program->current_pc,
123                        program->current_instruction);
124                 goto err;
125         }
126
127         if (options & SWP) {
128                 if (rta_sec_era < RTA_SEC_ERA_7) {
129                         pr_err("MATH: operation not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
130                                USER_SEC_ERA(rta_sec_era), program->current_pc,
131                                program->current_instruction);
132                         goto err;
133                 }
134
135                 if ((options & IFB) ||
136                     (!(options & IMMED) && !(options & IMMED2)) ||
137                     ((options & IMMED) && (options & IMMED2))) {
138                         pr_err("MATH: SWP - invalid configuration. SEC PC: %d; Instr: %d\n",
139                                program->current_pc,
140                                program->current_instruction);
141                         goto err;
142                 }
143         }
144
145         /*
146          * SHLD operation is different from others and we
147          * assume that we can have _NONE as first operand
148          * or _SEQINSZ as second operand
149          */
150         if ((op != MATH_FUN_SHLD) && ((operand1 == NONE) ||
151                                       (operand2 == SEQINSZ))) {
152                 pr_err("MATH: Invalid operand. SEC PC: %d; Instr: %d\n",
153                        program->current_pc, program->current_instruction);
154                 goto err;
155         }
156
157         /*
158          * We first check if it is unary operation. In that
159          * case second operand must be _NONE
160          */
161         if (((op == MATH_FUN_ZBYT) || (op == MATH_FUN_BSWAP)) &&
162             (operand2 != NONE)) {
163                 pr_err("MATH: Invalid operand2. SEC PC: %d; Instr: %d\n",
164                        program->current_pc, program->current_instruction);
165                 goto err;
166         }
167
168         /* Write first operand field */
169         if (options & IMMED) {
170                 opcode |= MATH_SRC0_IMM;
171         } else {
172                 ret = __rta_map_opcode((uint32_t)operand1, math_op1,
173                                        math_op1_sz[rta_sec_era], &val);
174                 if (ret < 0) {
175                         pr_err("MATH: operand1 not supported. SEC PC: %d; Instr: %d\n",
176                                program->current_pc,
177                                program->current_instruction);
178                         goto err;
179                 }
180                 opcode |= val;
181         }
182
183         /* Write second operand field */
184         if (options & IMMED2) {
185                 opcode |= MATH_SRC1_IMM;
186         } else {
187                 ret = __rta_map_opcode((uint32_t)operand2, math_op2,
188                                        math_op2_sz[rta_sec_era], &val);
189                 if (ret < 0) {
190                         pr_err("MATH: operand2 not supported. SEC PC: %d; Instr: %d\n",
191                                program->current_pc,
192                                program->current_instruction);
193                         goto err;
194                 }
195                 opcode |= val;
196         }
197
198         /* Write result field */
199         ret = __rta_map_opcode(result, math_result, math_result_sz[rta_sec_era],
200                                &val);
201         if (ret < 0) {
202                 pr_err("MATH: result not supported. SEC PC: %d; Instr: %d\n",
203                        program->current_pc, program->current_instruction);
204                 goto err;
205         }
206         opcode |= val;
207
208         /*
209          * as we encode operations with their "real" values, we do not
210          * to translate but we do need to validate the value
211          */
212         switch (op) {
213         /*Binary operators */
214         case (MATH_FUN_ADD):
215         case (MATH_FUN_ADDC):
216         case (MATH_FUN_SUB):
217         case (MATH_FUN_SUBB):
218         case (MATH_FUN_OR):
219         case (MATH_FUN_AND):
220         case (MATH_FUN_XOR):
221         case (MATH_FUN_LSHIFT):
222         case (MATH_FUN_RSHIFT):
223         case (MATH_FUN_SHLD):
224         /* Unary operators */
225         case (MATH_FUN_ZBYT):
226         case (MATH_FUN_BSWAP):
227                 opcode |= op;
228                 break;
229         default:
230                 pr_err("MATH: operator is not supported. SEC PC: %d; Instr: %d\n",
231                        program->current_pc, program->current_instruction);
232                 ret = -EINVAL;
233                 goto err;
234         }
235
236         opcode |= (options & ~(IMMED | IMMED2));
237
238         /* Verify length */
239         switch (length) {
240         case (1):
241                 opcode |= MATH_LEN_1BYTE;
242                 break;
243         case (2):
244                 opcode |= MATH_LEN_2BYTE;
245                 break;
246         case (4):
247                 opcode |= MATH_LEN_4BYTE;
248                 break;
249         case (8):
250                 opcode |= MATH_LEN_8BYTE;
251                 break;
252         default:
253                 pr_err("MATH: length is not supported. SEC PC: %d; Instr: %d\n",
254                        program->current_pc, program->current_instruction);
255                 ret = -EINVAL;
256                 goto err;
257         }
258
259         __rta_out32(program, opcode);
260         program->current_instruction++;
261
262         /* Write immediate value */
263         if ((options & IMMED) && !(options & IMMED2)) {
264                 __rta_out64(program, (length > 4) && !(options & IFB),
265                             operand1);
266         } else if ((options & IMMED2) && !(options & IMMED)) {
267                 __rta_out64(program, (length > 4) && !(options & IFB),
268                             operand2);
269         } else if ((options & IMMED) && (options & IMMED2)) {
270                 __rta_out32(program, lower_32_bits(operand1));
271                 __rta_out32(program, lower_32_bits(operand2));
272         }
273
274         return (int)start_pc;
275
276  err:
277         program->first_error_pc = start_pc;
278         program->current_instruction++;
279         return ret;
280 }
281
282 static inline int
283 rta_mathi(struct program *program, uint64_t operand,
284           uint32_t op, uint8_t imm, uint32_t result,
285           int length, uint32_t options)
286 {
287         uint32_t opcode = CMD_MATHI;
288         uint32_t val = 0;
289         int ret = -EINVAL;
290         unsigned int start_pc = program->current_pc;
291
292         if (rta_sec_era < RTA_SEC_ERA_6) {
293                 pr_err("MATHI: Command not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
294                        USER_SEC_ERA(rta_sec_era), program->current_pc,
295                        program->current_instruction);
296                 goto err;
297         }
298
299         if (((op == MATH_FUN_FBYT) && (options & SSEL))) {
300                 pr_err("MATHI: Illegal combination - FBYT and SSEL. SEC PC: %d; Instr: %d\n",
301                        program->current_pc, program->current_instruction);
302                 goto err;
303         }
304
305         if ((options & SWP) && (rta_sec_era < RTA_SEC_ERA_7)) {
306                 pr_err("MATHI: SWP not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
307                        USER_SEC_ERA(rta_sec_era), program->current_pc,
308                        program->current_instruction);
309                 goto err;
310         }
311
312         /* Write first operand field */
313         if (!(options & SSEL))
314                 ret = __rta_map_opcode((uint32_t)operand, math_op1,
315                                        math_op1_sz[rta_sec_era], &val);
316         else
317                 ret = __rta_map_opcode((uint32_t)operand, math_op2,
318                                        math_op2_sz[rta_sec_era], &val);
319         if (ret < 0) {
320                 pr_err("MATHI: operand not supported. SEC PC: %d; Instr: %d\n",
321                        program->current_pc, program->current_instruction);
322                 goto err;
323         }
324
325         if (!(options & SSEL))
326                 opcode |= val;
327         else
328                 opcode |= (val << (MATHI_SRC1_SHIFT - MATH_SRC1_SHIFT));
329
330         /* Write second operand field */
331         opcode |= (imm << MATHI_IMM_SHIFT);
332
333         /* Write result field */
334         ret = __rta_map_opcode(result, math_result, math_result_sz[rta_sec_era],
335                                &val);
336         if (ret < 0) {
337                 pr_err("MATHI: result not supported. SEC PC: %d; Instr: %d\n",
338                        program->current_pc, program->current_instruction);
339                 goto err;
340         }
341         opcode |= (val << (MATHI_DEST_SHIFT - MATH_DEST_SHIFT));
342
343         /*
344          * as we encode operations with their "real" values, we do not have to
345          * translate but we do need to validate the value
346          */
347         switch (op) {
348         case (MATH_FUN_ADD):
349         case (MATH_FUN_ADDC):
350         case (MATH_FUN_SUB):
351         case (MATH_FUN_SUBB):
352         case (MATH_FUN_OR):
353         case (MATH_FUN_AND):
354         case (MATH_FUN_XOR):
355         case (MATH_FUN_LSHIFT):
356         case (MATH_FUN_RSHIFT):
357         case (MATH_FUN_FBYT):
358                 opcode |= op;
359                 break;
360         default:
361                 pr_err("MATHI: operator not supported. SEC PC: %d; Instr: %d\n",
362                        program->current_pc, program->current_instruction);
363                 ret = -EINVAL;
364                 goto err;
365         }
366
367         opcode |= options;
368
369         /* Verify length */
370         switch (length) {
371         case (1):
372                 opcode |= MATH_LEN_1BYTE;
373                 break;
374         case (2):
375                 opcode |= MATH_LEN_2BYTE;
376                 break;
377         case (4):
378                 opcode |= MATH_LEN_4BYTE;
379                 break;
380         case (8):
381                 opcode |= MATH_LEN_8BYTE;
382                 break;
383         default:
384                 pr_err("MATHI: length %d not supported. SEC PC: %d; Instr: %d\n",
385                        length, program->current_pc,
386                        program->current_instruction);
387                 ret = -EINVAL;
388                 goto err;
389         }
390
391         __rta_out32(program, opcode);
392         program->current_instruction++;
393
394         return (int)start_pc;
395
396  err:
397         program->first_error_pc = start_pc;
398         program->current_instruction++;
399         return ret;
400 }
401
402 #endif /* __RTA_MATH_CMD_H__ */