2 * Copyright 2008-2016 Freescale Semiconductor, Inc.
4 * SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+
7 #ifndef __RTA_MOVE_CMD_H__
8 #define __RTA_MOVE_CMD_H__
10 #define MOVE_SET_AUX_SRC 0x01
11 #define MOVE_SET_AUX_DST 0x02
12 #define MOVE_SET_AUX_LS 0x03
13 #define MOVE_SET_LEN_16b 0x04
15 #define MOVE_SET_AUX_MATH 0x10
16 #define MOVE_SET_AUX_MATH_SRC (MOVE_SET_AUX_SRC | MOVE_SET_AUX_MATH)
17 #define MOVE_SET_AUX_MATH_DST (MOVE_SET_AUX_DST | MOVE_SET_AUX_MATH)
21 /* MOVE command type */
26 extern enum rta_sec_era rta_sec_era;
28 static const uint32_t move_src_table[][2] = {
29 /*1*/ { CONTEXT1, MOVE_SRC_CLASS1CTX },
30 { CONTEXT2, MOVE_SRC_CLASS2CTX },
31 { OFIFO, MOVE_SRC_OUTFIFO },
32 { DESCBUF, MOVE_SRC_DESCBUF },
33 { MATH0, MOVE_SRC_MATH0 },
34 { MATH1, MOVE_SRC_MATH1 },
35 { MATH2, MOVE_SRC_MATH2 },
36 { MATH3, MOVE_SRC_MATH3 },
37 /*9*/ { IFIFOABD, MOVE_SRC_INFIFO },
38 { IFIFOAB1, MOVE_SRC_INFIFO_CL | MOVE_AUX_LS },
39 { IFIFOAB2, MOVE_SRC_INFIFO_CL },
40 /*12*/ { ABD, MOVE_SRC_INFIFO_NO_NFIFO },
41 { AB1, MOVE_SRC_INFIFO_NO_NFIFO | MOVE_AUX_LS },
42 { AB2, MOVE_SRC_INFIFO_NO_NFIFO | MOVE_AUX_MS }
45 /* Allowed MOVE / MOVE_LEN sources for each SEC Era.
46 * Values represent the number of entries from move_src_table[] that are
49 static const unsigned int move_src_table_sz[] = {9, 11, 14, 14, 14, 14, 14, 14};
51 static const uint32_t move_dst_table[][2] = {
52 /*1*/ { CONTEXT1, MOVE_DEST_CLASS1CTX },
53 { CONTEXT2, MOVE_DEST_CLASS2CTX },
54 { OFIFO, MOVE_DEST_OUTFIFO },
55 { DESCBUF, MOVE_DEST_DESCBUF },
56 { MATH0, MOVE_DEST_MATH0 },
57 { MATH1, MOVE_DEST_MATH1 },
58 { MATH2, MOVE_DEST_MATH2 },
59 { MATH3, MOVE_DEST_MATH3 },
60 { IFIFOAB1, MOVE_DEST_CLASS1INFIFO },
61 { IFIFOAB2, MOVE_DEST_CLASS2INFIFO },
62 { PKA, MOVE_DEST_PK_A },
63 { KEY1, MOVE_DEST_CLASS1KEY },
64 { KEY2, MOVE_DEST_CLASS2KEY },
65 /*14*/ { IFIFO, MOVE_DEST_INFIFO },
66 /*15*/ { ALTSOURCE, MOVE_DEST_ALTSOURCE}
69 /* Allowed MOVE / MOVE_LEN destinations for each SEC Era.
70 * Values represent the number of entries from move_dst_table[] that are
74 unsigned int move_dst_table_sz[] = {13, 14, 14, 15, 15, 15, 15, 15};
77 set_move_offset(struct program *program __maybe_unused,
78 uint64_t src, uint16_t src_offset,
79 uint64_t dst, uint16_t dst_offset,
80 uint16_t *offset, uint16_t *opt);
83 math_offset(uint16_t offset);
86 rta_move(struct program *program, int cmd_type, uint64_t src,
87 uint16_t src_offset, uint64_t dst,
88 uint16_t dst_offset, uint32_t length, uint32_t flags)
91 uint16_t offset = 0, opt = 0;
94 bool is_move_len_cmd = false;
95 unsigned int start_pc = program->current_pc;
97 if ((rta_sec_era < RTA_SEC_ERA_7) && (cmd_type != __MOVE)) {
98 pr_err("MOVE: MOVEB / MOVEDW 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);
104 /* write command type */
105 if (cmd_type == __MOVEB) {
107 } else if (cmd_type == __MOVEDW) {
109 } else if (!(flags & IMMED)) {
110 if (rta_sec_era < RTA_SEC_ERA_3) {
111 pr_err("MOVE: MOVE_LEN not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
112 USER_SEC_ERA(rta_sec_era), program->current_pc,
113 program->current_instruction);
117 if ((length != MATH0) && (length != MATH1) &&
118 (length != MATH2) && (length != MATH3)) {
119 pr_err("MOVE: MOVE_LEN length must be MATH[0-3]. SEC PC: %d; Instr: %d\n",
121 program->current_instruction);
125 opcode = CMD_MOVE_LEN;
126 is_move_len_cmd = true;
131 /* write offset first, to check for invalid combinations or incorrect
132 * offset values sooner; decide which offset should be here
135 ret = set_move_offset(program, src, src_offset, dst, dst_offset,
140 opcode |= (offset << MOVE_OFFSET_SHIFT) & MOVE_OFFSET_MASK;
142 /* set AUX field if required */
143 if (opt == MOVE_SET_AUX_SRC) {
144 opcode |= ((src_offset / 16) << MOVE_AUX_SHIFT) & MOVE_AUX_MASK;
145 } else if (opt == MOVE_SET_AUX_DST) {
146 opcode |= ((dst_offset / 16) << MOVE_AUX_SHIFT) & MOVE_AUX_MASK;
147 } else if (opt == MOVE_SET_AUX_LS) {
148 opcode |= MOVE_AUX_LS;
149 } else if (opt & MOVE_SET_AUX_MATH) {
150 if (opt & MOVE_SET_AUX_SRC)
155 if (rta_sec_era < RTA_SEC_ERA_6) {
157 pr_debug("MOVE: Offset not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
158 USER_SEC_ERA(rta_sec_era),
160 program->current_instruction);
161 /* nothing to do for offset = 0 */
163 ret = math_offset(offset);
165 pr_err("MOVE: Invalid offset in MATH register. SEC PC: %d; Instr: %d\n",
167 program->current_instruction);
171 opcode |= (uint32_t)ret;
175 /* write source field */
176 ret = __rta_map_opcode((uint32_t)src, move_src_table,
177 move_src_table_sz[rta_sec_era], &val);
179 pr_err("MOVE: Invalid SRC. SEC PC: %d; Instr: %d\n",
180 program->current_pc, program->current_instruction);
185 /* write destination field */
186 ret = __rta_map_opcode((uint32_t)dst, move_dst_table,
187 move_dst_table_sz[rta_sec_era], &val);
189 pr_err("MOVE: Invalid DST. SEC PC: %d; Instr: %d\n",
190 program->current_pc, program->current_instruction);
196 if (flags & (FLUSH1 | FLUSH2))
197 opcode |= MOVE_AUX_MS;
198 if (flags & (LAST2 | LAST1))
199 opcode |= MOVE_AUX_LS;
200 if (flags & WAITCOMP)
201 opcode |= MOVE_WAITCOMP;
203 if (!is_move_len_cmd) {
205 if (opt == MOVE_SET_LEN_16b)
206 opcode |= (length & (MOVE_OFFSET_MASK | MOVE_LEN_MASK));
208 opcode |= (length & MOVE_LEN_MASK);
214 * opcode |= MOVELEN_MRSEL_MATH0;
215 * MOVELEN_MRSEL_MATH0 is 0
219 opcode |= MOVELEN_MRSEL_MATH1;
222 opcode |= MOVELEN_MRSEL_MATH2;
225 opcode |= MOVELEN_MRSEL_MATH3;
230 if (rta_sec_era >= RTA_SEC_ERA_7) {
231 if (flags & SIZE_WORD)
232 opcode |= MOVELEN_SIZE_WORD;
233 else if (flags & SIZE_BYTE)
234 opcode |= MOVELEN_SIZE_BYTE;
235 else if (flags & SIZE_DWORD)
236 opcode |= MOVELEN_SIZE_DWORD;
240 __rta_out32(program, opcode);
241 program->current_instruction++;
243 return (int)start_pc;
246 program->first_error_pc = start_pc;
247 program->current_instruction++;
252 set_move_offset(struct program *program __maybe_unused,
253 uint64_t src, uint16_t src_offset,
254 uint64_t dst, uint16_t dst_offset,
255 uint16_t *offset, uint16_t *opt)
260 if (dst == DESCBUF) {
261 *opt = MOVE_SET_AUX_SRC;
262 *offset = dst_offset;
263 } else if ((dst == KEY1) || (dst == KEY2)) {
264 if ((src_offset) && (dst_offset)) {
265 pr_err("MOVE: Bad offset. SEC PC: %d; Instr: %d\n",
267 program->current_instruction);
271 *opt = MOVE_SET_AUX_LS;
272 *offset = dst_offset;
274 *offset = src_offset;
277 if ((dst == MATH0) || (dst == MATH1) ||
278 (dst == MATH2) || (dst == MATH3)) {
279 *opt = MOVE_SET_AUX_MATH_DST;
280 } else if (((dst == OFIFO) || (dst == ALTSOURCE)) &&
282 pr_err("MOVE: Bad offset alignment. SEC PC: %d; Instr: %d\n",
284 program->current_instruction);
288 *offset = src_offset;
294 pr_err("MOVE: Invalid DST. SEC PC: %d; Instr: %d\n",
296 program->current_instruction);
299 if (((dst == IFIFOAB1) || (dst == IFIFOAB2) ||
300 (dst == IFIFO) || (dst == PKA)) &&
301 (src_offset || dst_offset)) {
302 pr_err("MOVE: Offset should be zero. SEC PC: %d; Instr: %d\n",
304 program->current_instruction);
307 *offset = dst_offset;
311 if ((dst == CONTEXT1) || (dst == CONTEXT2)) {
312 *opt = MOVE_SET_AUX_DST;
313 } else if ((dst == MATH0) || (dst == MATH1) ||
314 (dst == MATH2) || (dst == MATH3)) {
315 *opt = MOVE_SET_AUX_MATH_DST;
316 } else if (dst == DESCBUF) {
317 pr_err("MOVE: Invalid DST. SEC PC: %d; Instr: %d\n",
319 program->current_instruction);
321 } else if (((dst == OFIFO) || (dst == ALTSOURCE)) &&
323 pr_err("MOVE: Invalid offset alignment. SEC PC: %d; Instr %d\n",
325 program->current_instruction);
329 *offset = src_offset;
336 if ((dst == OFIFO) || (dst == ALTSOURCE)) {
337 if (src_offset % 4) {
338 pr_err("MOVE: Bad offset alignment. SEC PC: %d; Instr: %d\n",
340 program->current_instruction);
343 *offset = src_offset;
344 } else if ((dst == IFIFOAB1) || (dst == IFIFOAB2) ||
345 (dst == IFIFO) || (dst == PKA)) {
346 *offset = src_offset;
348 *offset = dst_offset;
351 * This condition is basically the negation of:
352 * dst in { CONTEXT[1-2], MATH[0-3] }
354 if ((dst != KEY1) && (dst != KEY2))
355 *opt = MOVE_SET_AUX_MATH_SRC;
365 if ((dst == IFIFOAB1) || (dst == IFIFOAB2) ||
366 (dst == IFIFO) || (dst == PKA) || (dst == ALTSOURCE)) {
367 pr_err("MOVE: Bad DST. SEC PC: %d; Instr: %d\n",
369 program->current_instruction);
373 *opt = MOVE_SET_LEN_16b;
375 if (dst_offset % 4) {
376 pr_err("MOVE: Bad offset alignment. SEC PC: %d; Instr: %d\n",
378 program->current_instruction);
381 *offset = dst_offset;
395 math_offset(uint16_t offset)
405 return MOVE_AUX_LS | MOVE_AUX_MS;
411 #endif /* __RTA_MOVE_CMD_H__ */