xref: /dpdk/drivers/common/dpaax/caamflib/rta/load_cmd.h (revision c0ded849131598760a25e96ff368d035838af0b3)
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_LOAD_CMD_H__
8 #define __RTA_LOAD_CMD_H__
9 
10 extern enum rta_sec_era rta_sec_era;
11 
12 /* Allowed length and offset masks for each SEC Era in case DST = DCTRL */
13 static const uint32_t load_len_mask_allowed[] = {
14 	0x000000ee,
15 	0x000000fe,
16 	0x000000fe,
17 	0x000000fe,
18 	0x000000fe,
19 	0x000000fe,
20 	0x000000fe,
21 	0x000000fe,
22 	0x000000fe,
23 	0x000000fe
24 };
25 
26 static const uint32_t load_off_mask_allowed[] = {
27 	0x0000000f,
28 	0x000000ff,
29 	0x000000ff,
30 	0x000000ff,
31 	0x000000ff,
32 	0x000000ff,
33 	0x000000ff,
34 	0x000000ff,
35 	0x000000ff,
36 	0x000000ff
37 };
38 
39 #define IMM_MUST 0
40 #define IMM_CAN  1
41 #define IMM_NO   2
42 #define IMM_DSNM 3 /* it doesn't matter the src type */
43 
44 enum e_lenoff {
45 	LENOF_03,
46 	LENOF_4,
47 	LENOF_48,
48 	LENOF_448,
49 	LENOF_18,
50 	LENOF_32,
51 	LENOF_24,
52 	LENOF_16,
53 	LENOF_8,
54 	LENOF_128,
55 	LENOF_256,
56 	DSNM /* it doesn't matter the length/offset values */
57 };
58 
59 struct load_map {
60 	uint32_t dst;
61 	uint32_t dst_opcode;
62 	enum e_lenoff len_off;
63 	uint8_t imm_src;
64 
65 };
66 
67 static const struct load_map load_dst[] = {
68 /*1*/	{ KEY1SZ,  LDST_CLASS_1_CCB | LDST_SRCDST_WORD_KEYSZ_REG,
69 		   LENOF_4,   IMM_MUST },
70 	{ KEY2SZ,  LDST_CLASS_2_CCB | LDST_SRCDST_WORD_KEYSZ_REG,
71 		   LENOF_4,   IMM_MUST },
72 	{ DATA1SZ, LDST_CLASS_1_CCB | LDST_SRCDST_WORD_DATASZ_REG,
73 		   LENOF_448, IMM_MUST },
74 	{ DATA2SZ, LDST_CLASS_2_CCB | LDST_SRCDST_WORD_DATASZ_REG,
75 		   LENOF_448, IMM_MUST },
76 	{ ICV1SZ,  LDST_CLASS_1_CCB | LDST_SRCDST_WORD_ICVSZ_REG,
77 		   LENOF_4,   IMM_MUST },
78 	{ ICV2SZ,  LDST_CLASS_2_CCB | LDST_SRCDST_WORD_ICVSZ_REG,
79 		   LENOF_4,   IMM_MUST },
80 	{ CCTRL,   LDST_CLASS_IND_CCB | LDST_SRCDST_WORD_CHACTRL,
81 		   LENOF_4,   IMM_MUST },
82 	{ DCTRL,   LDST_CLASS_DECO | LDST_IMM | LDST_SRCDST_WORD_DECOCTRL,
83 		   DSNM,      IMM_DSNM },
84 	{ ICTRL,   LDST_CLASS_IND_CCB | LDST_SRCDST_WORD_IRQCTRL,
85 		   LENOF_4,   IMM_MUST },
86 	{ DPOVRD,  LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_PCLOVRD,
87 		   LENOF_4,   IMM_MUST },
88 	{ CLRW,    LDST_CLASS_IND_CCB | LDST_SRCDST_WORD_CLRW,
89 		   LENOF_4,   IMM_MUST },
90 	{ AAD1SZ,  LDST_CLASS_1_CCB | LDST_SRCDST_WORD_DECO_AAD_SZ,
91 		   LENOF_4,   IMM_MUST },
92 	{ IV1SZ,   LDST_CLASS_1_CCB | LDST_SRCDST_WORD_CLASS1_IV_SZ,
93 		   LENOF_4,   IMM_MUST },
94 	{ ALTDS1,  LDST_CLASS_1_CCB | LDST_SRCDST_WORD_ALTDS_CLASS1,
95 		   LENOF_448, IMM_MUST },
96 	{ PKASZ,   LDST_CLASS_1_CCB | LDST_SRCDST_WORD_PKHA_A_SZ,
97 		   LENOF_4,   IMM_MUST, },
98 	{ PKBSZ,   LDST_CLASS_1_CCB | LDST_SRCDST_WORD_PKHA_B_SZ,
99 		   LENOF_4,   IMM_MUST },
100 	{ PKNSZ,   LDST_CLASS_1_CCB | LDST_SRCDST_WORD_PKHA_N_SZ,
101 		   LENOF_4,   IMM_MUST },
102 	{ PKESZ,   LDST_CLASS_1_CCB | LDST_SRCDST_WORD_PKHA_E_SZ,
103 		   LENOF_4,   IMM_MUST },
104 	{ NFIFO,   LDST_CLASS_IND_CCB | LDST_SRCDST_WORD_INFO_FIFO,
105 		   LENOF_48,  IMM_MUST },
106 	{ IFIFO,   LDST_SRCDST_BYTE_INFIFO,  LENOF_18, IMM_MUST },
107 	{ OFIFO,   LDST_SRCDST_BYTE_OUTFIFO, LENOF_18, IMM_MUST },
108 	{ MATH0,   LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_MATH0,
109 		   LENOF_32,  IMM_CAN },
110 	{ MATH1,   LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_MATH1,
111 		   LENOF_24,  IMM_CAN },
112 	{ MATH2,   LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_MATH2,
113 		   LENOF_16,  IMM_CAN },
114 	{ MATH3,   LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_MATH3,
115 		   LENOF_8,   IMM_CAN },
116 	{ CONTEXT1, LDST_CLASS_1_CCB | LDST_SRCDST_BYTE_CONTEXT,
117 		   LENOF_128, IMM_CAN },
118 	{ CONTEXT2, LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_CONTEXT,
119 		   LENOF_128, IMM_CAN },
120 	{ KEY1,    LDST_CLASS_1_CCB | LDST_SRCDST_BYTE_KEY,
121 		   LENOF_32,  IMM_CAN },
122 	{ KEY2,    LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY,
123 		   LENOF_32,  IMM_CAN },
124 	{ DESCBUF, LDST_CLASS_DECO | LDST_SRCDST_WORD_DESCBUF,
125 		   LENOF_256,  IMM_NO },
126 	{ DPID,    LDST_CLASS_DECO | LDST_SRCDST_WORD_PID,
127 		   LENOF_448, IMM_MUST },
128 /*32*/	{ IDFNS,   LDST_SRCDST_WORD_IFNSR, LENOF_18,  IMM_MUST },
129 	{ ODFNS,   LDST_SRCDST_WORD_OFNSR, LENOF_18,  IMM_MUST },
130 	{ ALTSOURCE, LDST_SRCDST_BYTE_ALTSOURCE, LENOF_18,  IMM_MUST },
131 /*35*/	{ NFIFO_SZL, LDST_SRCDST_WORD_INFO_FIFO_SZL, LENOF_48, IMM_MUST },
132 	{ NFIFO_SZM, LDST_SRCDST_WORD_INFO_FIFO_SZM, LENOF_03, IMM_MUST },
133 	{ NFIFO_L, LDST_SRCDST_WORD_INFO_FIFO_L, LENOF_48, IMM_MUST },
134 	{ NFIFO_M, LDST_SRCDST_WORD_INFO_FIFO_M, LENOF_03, IMM_MUST },
135 	{ SZL,     LDST_SRCDST_WORD_SZL, LENOF_48, IMM_MUST },
136 /*40*/	{ SZM,     LDST_SRCDST_WORD_SZM, LENOF_03, IMM_MUST }
137 };
138 
139 /*
140  * Allowed LOAD destinations for each SEC Era.
141  * Values represent the number of entries from load_dst[] that are supported.
142  */
143 static const unsigned int load_dst_sz[] = { 31, 34, 34, 40, 40,
144 					    40, 40, 40, 40, 40};
145 
146 static inline int
load_check_len_offset(int pos,uint32_t length,uint32_t offset)147 load_check_len_offset(int pos, uint32_t length, uint32_t offset)
148 {
149 	if ((load_dst[pos].dst == DCTRL) &&
150 	    ((length & ~load_len_mask_allowed[rta_sec_era]) ||
151 	     (offset & ~load_off_mask_allowed[rta_sec_era])))
152 		goto err;
153 
154 	switch (load_dst[pos].len_off) {
155 	case (LENOF_03):
156 		if ((length > 3) || (offset))
157 			goto err;
158 		break;
159 	case (LENOF_4):
160 		if ((length != 4) || (offset != 0))
161 			goto err;
162 		break;
163 	case (LENOF_48):
164 		if (!(((length == 4) && (offset == 0)) ||
165 		      ((length == 8) && (offset == 0))))
166 			goto err;
167 		break;
168 	case (LENOF_448):
169 		if (!(((length == 4) && (offset == 0)) ||
170 		      ((length == 4) && (offset == 4)) ||
171 		      ((length == 8) && (offset == 0))))
172 			goto err;
173 		break;
174 	case (LENOF_18):
175 		if ((length < 1) || (length > 8) || (offset != 0))
176 			goto err;
177 		break;
178 	case (LENOF_32):
179 		if ((length > 32) || (offset > 32) || ((offset + length) > 32))
180 			goto err;
181 		break;
182 	case (LENOF_24):
183 		if ((length > 24) || (offset > 24) || ((offset + length) > 24))
184 			goto err;
185 		break;
186 	case (LENOF_16):
187 		if ((length > 16) || (offset > 16) || ((offset + length) > 16))
188 			goto err;
189 		break;
190 	case (LENOF_8):
191 		if ((length > 8) || (offset > 8) || ((offset + length) > 8))
192 			goto err;
193 		break;
194 	case (LENOF_128):
195 		if ((length > 128) || (offset > 128) ||
196 		    ((offset + length) > 128))
197 			goto err;
198 		break;
199 	case (LENOF_256):
200 		if ((length < 1) || (length > 256) || ((length + offset) > 256))
201 			goto err;
202 		break;
203 	case (DSNM):
204 		break;
205 	default:
206 		goto err;
207 	}
208 
209 	return 0;
210 err:
211 	return -EINVAL;
212 }
213 
214 static inline int
rta_load(struct program * program,uint64_t src,uint64_t dst,uint32_t offset,uint32_t length,uint32_t flags)215 rta_load(struct program *program, uint64_t src, uint64_t dst,
216 	 uint32_t offset, uint32_t length, uint32_t flags)
217 {
218 	uint32_t opcode = 0;
219 	int pos = -1, ret = -EINVAL;
220 	unsigned int start_pc = program->current_pc, i;
221 
222 	if (flags & SEQ)
223 		opcode = CMD_SEQ_LOAD;
224 	else
225 		opcode = CMD_LOAD;
226 
227 	if ((length & 0xffffff00) || (offset & 0xffffff00)) {
228 		pr_err("LOAD: Bad length/offset passed. Should be 8 bits\n");
229 		goto err;
230 	}
231 
232 	if (flags & SGF)
233 		opcode |= LDST_SGF;
234 	if (flags & VLF)
235 		opcode |= LDST_VLF;
236 
237 	/* check load destination, length and offset and source type */
238 	for (i = 0; i < load_dst_sz[rta_sec_era]; i++)
239 		if (dst == load_dst[i].dst) {
240 			pos = (int)i;
241 			break;
242 		}
243 	if (-1 == pos) {
244 		pr_err("LOAD: Invalid dst. SEC Program Line: %d\n",
245 		       program->current_pc);
246 		goto err;
247 	}
248 
249 	if (flags & IMMED) {
250 		if (load_dst[pos].imm_src == IMM_NO) {
251 			pr_err("LOAD: Invalid source type. SEC Program Line: %d\n",
252 			       program->current_pc);
253 			goto err;
254 		}
255 		opcode |= LDST_IMM;
256 	} else if (load_dst[pos].imm_src == IMM_MUST) {
257 		pr_err("LOAD IMM: Invalid source type. SEC Program Line: %d\n",
258 		       program->current_pc);
259 		goto err;
260 	}
261 
262 	ret = load_check_len_offset(pos, length, offset);
263 	if (ret < 0) {
264 		pr_err("LOAD: Invalid length/offset. SEC Program Line: %d\n",
265 		       program->current_pc);
266 		goto err;
267 	}
268 
269 	opcode |= load_dst[pos].dst_opcode;
270 
271 	/* DESC BUFFER: length / offset values are specified in 4-byte words */
272 	if (dst == DESCBUF) {
273 		opcode |= (length >> 2);
274 		opcode |= ((offset >> 2) << LDST_OFFSET_SHIFT);
275 	} else {
276 		opcode |= length;
277 		opcode |= (offset << LDST_OFFSET_SHIFT);
278 	}
279 
280 	__rta_out32(program, opcode);
281 	program->current_instruction++;
282 
283 	/* DECO CONTROL: skip writing pointer of imm data */
284 	if (dst == DCTRL)
285 		return (int)start_pc;
286 
287 	/*
288 	 * For data copy, 3 possible ways to specify how to copy data:
289 	 *  - IMMED & !COPY: copy data directly from src( max 8 bytes)
290 	 *  - IMMED & COPY: copy data imm from the location specified by user
291 	 *  - !IMMED and is not SEQ cmd: copy the address
292 	 */
293 	if (flags & IMMED)
294 		__rta_inline_data(program, src, flags & __COPY_MASK, length);
295 	else if (!(flags & SEQ))
296 		__rta_out64(program, program->ps, src);
297 
298 	return (int)start_pc;
299 
300  err:
301 	program->first_error_pc = start_pc;
302 	program->current_instruction++;
303 	return ret;
304 }
305 
306 #endif /* __RTA_LOAD_CMD_H__*/
307