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.
7 * Copyright 2008-2016 Freescale Semiconductor Inc.
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.
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
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.
41 #ifndef __RTA_MOVE_CMD_H__
42 #define __RTA_MOVE_CMD_H__
44 #define MOVE_SET_AUX_SRC 0x01
45 #define MOVE_SET_AUX_DST 0x02
46 #define MOVE_SET_AUX_LS 0x03
47 #define MOVE_SET_LEN_16b 0x04
49 #define MOVE_SET_AUX_MATH 0x10
50 #define MOVE_SET_AUX_MATH_SRC (MOVE_SET_AUX_SRC | MOVE_SET_AUX_MATH)
51 #define MOVE_SET_AUX_MATH_DST (MOVE_SET_AUX_DST | MOVE_SET_AUX_MATH)
55 /* MOVE command type */
60 extern enum rta_sec_era rta_sec_era;
62 static const uint32_t move_src_table[][2] = {
63 /*1*/ { CONTEXT1, MOVE_SRC_CLASS1CTX },
64 { CONTEXT2, MOVE_SRC_CLASS2CTX },
65 { OFIFO, MOVE_SRC_OUTFIFO },
66 { DESCBUF, MOVE_SRC_DESCBUF },
67 { MATH0, MOVE_SRC_MATH0 },
68 { MATH1, MOVE_SRC_MATH1 },
69 { MATH2, MOVE_SRC_MATH2 },
70 { MATH3, MOVE_SRC_MATH3 },
71 /*9*/ { IFIFOABD, MOVE_SRC_INFIFO },
72 { IFIFOAB1, MOVE_SRC_INFIFO_CL | MOVE_AUX_LS },
73 { IFIFOAB2, MOVE_SRC_INFIFO_CL },
74 /*12*/ { ABD, MOVE_SRC_INFIFO_NO_NFIFO },
75 { AB1, MOVE_SRC_INFIFO_NO_NFIFO | MOVE_AUX_LS },
76 { AB2, MOVE_SRC_INFIFO_NO_NFIFO | MOVE_AUX_MS }
79 /* Allowed MOVE / MOVE_LEN sources for each SEC Era.
80 * Values represent the number of entries from move_src_table[] that are
83 static const unsigned int move_src_table_sz[] = {9, 11, 14, 14, 14, 14, 14, 14};
85 static const uint32_t move_dst_table[][2] = {
86 /*1*/ { CONTEXT1, MOVE_DEST_CLASS1CTX },
87 { CONTEXT2, MOVE_DEST_CLASS2CTX },
88 { OFIFO, MOVE_DEST_OUTFIFO },
89 { DESCBUF, MOVE_DEST_DESCBUF },
90 { MATH0, MOVE_DEST_MATH0 },
91 { MATH1, MOVE_DEST_MATH1 },
92 { MATH2, MOVE_DEST_MATH2 },
93 { MATH3, MOVE_DEST_MATH3 },
94 { IFIFOAB1, MOVE_DEST_CLASS1INFIFO },
95 { IFIFOAB2, MOVE_DEST_CLASS2INFIFO },
96 { PKA, MOVE_DEST_PK_A },
97 { KEY1, MOVE_DEST_CLASS1KEY },
98 { KEY2, MOVE_DEST_CLASS2KEY },
99 /*14*/ { IFIFO, MOVE_DEST_INFIFO },
100 /*15*/ { ALTSOURCE, MOVE_DEST_ALTSOURCE}
103 /* Allowed MOVE / MOVE_LEN destinations for each SEC Era.
104 * Values represent the number of entries from move_dst_table[] that are
108 unsigned int move_dst_table_sz[] = {13, 14, 14, 15, 15, 15, 15, 15};
111 set_move_offset(struct program *program __maybe_unused,
112 uint64_t src, uint16_t src_offset,
113 uint64_t dst, uint16_t dst_offset,
114 uint16_t *offset, uint16_t *opt);
117 math_offset(uint16_t offset);
120 rta_move(struct program *program, int cmd_type, uint64_t src,
121 uint16_t src_offset, uint64_t dst,
122 uint16_t dst_offset, uint32_t length, uint32_t flags)
125 uint16_t offset = 0, opt = 0;
128 bool is_move_len_cmd = false;
129 unsigned int start_pc = program->current_pc;
131 if ((rta_sec_era < RTA_SEC_ERA_7) && (cmd_type != __MOVE)) {
132 pr_err("MOVE: MOVEB / MOVEDW not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
133 USER_SEC_ERA(rta_sec_era), program->current_pc,
134 program->current_instruction);
138 /* write command type */
139 if (cmd_type == __MOVEB) {
141 } else if (cmd_type == __MOVEDW) {
143 } else if (!(flags & IMMED)) {
144 if (rta_sec_era < RTA_SEC_ERA_3) {
145 pr_err("MOVE: MOVE_LEN not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
146 USER_SEC_ERA(rta_sec_era), program->current_pc,
147 program->current_instruction);
151 if ((length != MATH0) && (length != MATH1) &&
152 (length != MATH2) && (length != MATH3)) {
153 pr_err("MOVE: MOVE_LEN length must be MATH[0-3]. SEC PC: %d; Instr: %d\n",
155 program->current_instruction);
159 opcode = CMD_MOVE_LEN;
160 is_move_len_cmd = true;
165 /* write offset first, to check for invalid combinations or incorrect
166 * offset values sooner; decide which offset should be here
169 ret = set_move_offset(program, src, src_offset, dst, dst_offset,
174 opcode |= (offset << MOVE_OFFSET_SHIFT) & MOVE_OFFSET_MASK;
176 /* set AUX field if required */
177 if (opt == MOVE_SET_AUX_SRC) {
178 opcode |= ((src_offset / 16) << MOVE_AUX_SHIFT) & MOVE_AUX_MASK;
179 } else if (opt == MOVE_SET_AUX_DST) {
180 opcode |= ((dst_offset / 16) << MOVE_AUX_SHIFT) & MOVE_AUX_MASK;
181 } else if (opt == MOVE_SET_AUX_LS) {
182 opcode |= MOVE_AUX_LS;
183 } else if (opt & MOVE_SET_AUX_MATH) {
184 if (opt & MOVE_SET_AUX_SRC)
189 if (rta_sec_era < RTA_SEC_ERA_6) {
191 pr_debug("MOVE: Offset not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
192 USER_SEC_ERA(rta_sec_era),
194 program->current_instruction);
195 /* nothing to do for offset = 0 */
197 ret = math_offset(offset);
199 pr_err("MOVE: Invalid offset in MATH register. SEC PC: %d; Instr: %d\n",
201 program->current_instruction);
205 opcode |= (uint32_t)ret;
209 /* write source field */
210 ret = __rta_map_opcode((uint32_t)src, move_src_table,
211 move_src_table_sz[rta_sec_era], &val);
213 pr_err("MOVE: Invalid SRC. SEC PC: %d; Instr: %d\n",
214 program->current_pc, program->current_instruction);
219 /* write destination field */
220 ret = __rta_map_opcode((uint32_t)dst, move_dst_table,
221 move_dst_table_sz[rta_sec_era], &val);
223 pr_err("MOVE: Invalid DST. SEC PC: %d; Instr: %d\n",
224 program->current_pc, program->current_instruction);
230 if (flags & (FLUSH1 | FLUSH2))
231 opcode |= MOVE_AUX_MS;
232 if (flags & (LAST2 | LAST1))
233 opcode |= MOVE_AUX_LS;
234 if (flags & WAITCOMP)
235 opcode |= MOVE_WAITCOMP;
237 if (!is_move_len_cmd) {
239 if (opt == MOVE_SET_LEN_16b)
240 opcode |= (length & (MOVE_OFFSET_MASK | MOVE_LEN_MASK));
242 opcode |= (length & MOVE_LEN_MASK);
248 * opcode |= MOVELEN_MRSEL_MATH0;
249 * MOVELEN_MRSEL_MATH0 is 0
253 opcode |= MOVELEN_MRSEL_MATH1;
256 opcode |= MOVELEN_MRSEL_MATH2;
259 opcode |= MOVELEN_MRSEL_MATH3;
264 if (rta_sec_era >= RTA_SEC_ERA_7) {
265 if (flags & SIZE_WORD)
266 opcode |= MOVELEN_SIZE_WORD;
267 else if (flags & SIZE_BYTE)
268 opcode |= MOVELEN_SIZE_BYTE;
269 else if (flags & SIZE_DWORD)
270 opcode |= MOVELEN_SIZE_DWORD;
274 __rta_out32(program, opcode);
275 program->current_instruction++;
277 return (int)start_pc;
280 program->first_error_pc = start_pc;
281 program->current_instruction++;
286 set_move_offset(struct program *program __maybe_unused,
287 uint64_t src, uint16_t src_offset,
288 uint64_t dst, uint16_t dst_offset,
289 uint16_t *offset, uint16_t *opt)
294 if (dst == DESCBUF) {
295 *opt = MOVE_SET_AUX_SRC;
296 *offset = dst_offset;
297 } else if ((dst == KEY1) || (dst == KEY2)) {
298 if ((src_offset) && (dst_offset)) {
299 pr_err("MOVE: Bad offset. SEC PC: %d; Instr: %d\n",
301 program->current_instruction);
305 *opt = MOVE_SET_AUX_LS;
306 *offset = dst_offset;
308 *offset = src_offset;
311 if ((dst == MATH0) || (dst == MATH1) ||
312 (dst == MATH2) || (dst == MATH3)) {
313 *opt = MOVE_SET_AUX_MATH_DST;
314 } else if (((dst == OFIFO) || (dst == ALTSOURCE)) &&
316 pr_err("MOVE: Bad offset alignment. SEC PC: %d; Instr: %d\n",
318 program->current_instruction);
322 *offset = src_offset;
328 pr_err("MOVE: Invalid DST. SEC PC: %d; Instr: %d\n",
330 program->current_instruction);
333 if (((dst == IFIFOAB1) || (dst == IFIFOAB2) ||
334 (dst == IFIFO) || (dst == PKA)) &&
335 (src_offset || dst_offset)) {
336 pr_err("MOVE: Offset should be zero. SEC PC: %d; Instr: %d\n",
338 program->current_instruction);
341 *offset = dst_offset;
345 if ((dst == CONTEXT1) || (dst == CONTEXT2)) {
346 *opt = MOVE_SET_AUX_DST;
347 } else if ((dst == MATH0) || (dst == MATH1) ||
348 (dst == MATH2) || (dst == MATH3)) {
349 *opt = MOVE_SET_AUX_MATH_DST;
350 } else if (dst == DESCBUF) {
351 pr_err("MOVE: Invalid DST. SEC PC: %d; Instr: %d\n",
353 program->current_instruction);
355 } else if (((dst == OFIFO) || (dst == ALTSOURCE)) &&
357 pr_err("MOVE: Invalid offset alignment. SEC PC: %d; Instr %d\n",
359 program->current_instruction);
363 *offset = src_offset;
370 if ((dst == OFIFO) || (dst == ALTSOURCE)) {
371 if (src_offset % 4) {
372 pr_err("MOVE: Bad offset alignment. SEC PC: %d; Instr: %d\n",
374 program->current_instruction);
377 *offset = src_offset;
378 } else if ((dst == IFIFOAB1) || (dst == IFIFOAB2) ||
379 (dst == IFIFO) || (dst == PKA)) {
380 *offset = src_offset;
382 *offset = dst_offset;
385 * This condition is basically the negation of:
386 * dst in { CONTEXT[1-2], MATH[0-3] }
388 if ((dst != KEY1) && (dst != KEY2))
389 *opt = MOVE_SET_AUX_MATH_SRC;
399 if ((dst == IFIFOAB1) || (dst == IFIFOAB2) ||
400 (dst == IFIFO) || (dst == PKA) || (dst == ALTSOURCE)) {
401 pr_err("MOVE: Bad DST. SEC PC: %d; Instr: %d\n",
403 program->current_instruction);
407 *opt = MOVE_SET_LEN_16b;
409 if (dst_offset % 4) {
410 pr_err("MOVE: Bad offset alignment. SEC PC: %d; Instr: %d\n",
412 program->current_instruction);
415 *offset = dst_offset;
429 math_offset(uint16_t offset)
439 return MOVE_AUX_LS | MOVE_AUX_MS;
445 #endif /* __RTA_MOVE_CMD_H__ */