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