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