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 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 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