1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019-2020 Broadcom
13 #include "hcapi_cfa_defs.h"
15 #define HCAPI_CFA_LKUP_SEED_MEM_SIZE 512
16 #define TF_EM_PAGE_SIZE (1 << 21)
17 uint32_t hcapi_cfa_lkup_lkup3_init_cfg;
18 uint32_t hcapi_cfa_lkup_em_seed_mem[HCAPI_CFA_LKUP_SEED_MEM_SIZE];
19 bool hcapi_cfa_lkup_init;
21 static inline uint32_t SWAP_WORDS32(uint32_t val32)
23 return (((val32 & 0x0000ffff) << 16) |
24 ((val32 & 0xffff0000) >> 16));
27 static void hcapi_cfa_seeds_init(void)
32 if (hcapi_cfa_lkup_init)
35 hcapi_cfa_lkup_init = true;
37 /* Initialize the lfsr */
40 /* RX and TX use the same seed values */
41 hcapi_cfa_lkup_lkup3_init_cfg = SWAP_WORDS32(rand32());
43 for (i = 0; i < HCAPI_CFA_LKUP_SEED_MEM_SIZE / 2; i++) {
44 r = SWAP_WORDS32(rand32());
45 hcapi_cfa_lkup_em_seed_mem[i * 2] = r;
46 r = SWAP_WORDS32(rand32());
47 hcapi_cfa_lkup_em_seed_mem[i * 2 + 1] = (r & 0x1);
51 /* CRC32i support for Key0 hash */
52 #define ucrc32(ch, crc) (crc32tbl[((crc) ^ (ch)) & 0xff] ^ ((crc) >> 8))
53 #define crc32(x, y) crc32i(~0, x, y)
55 static const uint32_t crc32tbl[] = { /* CRC polynomial 0xedb88320 */
56 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
57 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
58 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
59 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
60 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
61 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
62 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
63 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
64 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
65 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
66 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
67 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
68 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
69 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
70 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
71 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
72 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
73 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
74 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
75 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
76 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
77 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
78 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
79 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
80 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
81 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
82 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
83 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
84 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
85 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
86 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
87 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
88 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
89 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
90 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
91 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
92 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
93 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
94 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
95 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
96 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
97 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
98 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
99 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
100 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
101 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
102 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
103 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
104 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
105 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
106 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
107 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
108 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
109 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
110 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
111 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
112 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
113 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
114 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
115 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
116 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
117 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
118 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
119 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
122 static uint32_t hcapi_cfa_crc32i(uint32_t crc, const uint8_t *buf, size_t len)
127 TFP_DRV_LOG(DEBUG, "CRC2:");
129 for (l = (len - 1); l >= 0; l--) {
130 crc = ucrc32(buf[l], crc);
141 TFP_DRV_LOG(DEBUG, "\n");
147 static uint32_t hcapi_cfa_crc32_hash(uint8_t *key)
155 /* Do byte-wise XOR of the 52-byte HASH key first. */
159 for (i = CFA_P4_EEM_KEY_MAX_SIZE - 2; i >= 0; i--) {
160 index = index ^ *kptr;
165 val1 = hcapi_cfa_lkup_em_seed_mem[index * 2];
166 val2 = hcapi_cfa_lkup_em_seed_mem[index * 2 + 1];
168 temp[3] = (uint8_t)(val1 >> 24);
169 temp[2] = (uint8_t)(val1 >> 16);
170 temp[1] = (uint8_t)(val1 >> 8);
171 temp[0] = (uint8_t)(val1 & 0xff);
174 /* Start with seed */
176 val1 = hcapi_cfa_crc32i(~val1, temp, 4);
178 val1 = hcapi_cfa_crc32i(~val1,
179 (key - (CFA_P4_EEM_KEY_MAX_SIZE - 1)),
180 CFA_P4_EEM_KEY_MAX_SIZE);
184 val1 = hcapi_cfa_crc32i(~val1, temp, 4);
189 static uint32_t hcapi_cfa_lookup3_hash(uint8_t *in_key)
193 val1 = hashword(((const uint32_t *)(uintptr_t *)in_key) + 1,
194 CFA_P4_EEM_KEY_MAX_SIZE / (sizeof(uint32_t)),
195 hcapi_cfa_lkup_lkup3_init_cfg);
201 uint64_t hcapi_get_table_page(struct hcapi_cfa_em_table *mem,
205 int page = offset / TF_EM_PAGE_SIZE;
212 * Use the level according to the num_level of page table
214 level = mem->num_lvl - 1;
216 addr = (uintptr_t)mem->pg_tbl[level].pg_va_tbl[page];
221 /** Approximation of HCAPI hcapi_cfa_key_hash()
226 uint64_t hcapi_cfa_key_hash(uint64_t *key_data,
233 * Init the seeds if needed
235 if (!hcapi_cfa_lkup_init)
236 hcapi_cfa_seeds_init();
238 key0_hash = hcapi_cfa_crc32_hash(((uint8_t *)key_data) +
241 key1_hash = hcapi_cfa_lookup3_hash((uint8_t *)key_data);
243 return ((uint64_t)key0_hash) << 32 | (uint64_t)key1_hash;
246 static int hcapi_cfa_key_hw_op_put(struct hcapi_cfa_hwop *op,
247 struct hcapi_cfa_key_data *key_obj)
251 memcpy((uint8_t *)(uintptr_t)op->hw.base_addr +
259 static int hcapi_cfa_key_hw_op_get(struct hcapi_cfa_hwop *op,
260 struct hcapi_cfa_key_data *key_obj)
264 memcpy(key_obj->data,
265 (uint8_t *)(uintptr_t)op->hw.base_addr +
272 static int hcapi_cfa_key_hw_op_add(struct hcapi_cfa_hwop *op,
273 struct hcapi_cfa_key_data *key_obj)
276 struct cfa_p4_eem_64b_entry table_entry;
282 (uint8_t *)(uintptr_t)op->hw.base_addr +
287 * If this is entry is valid then report failure
289 if (table_entry.hdr.word1 & (1 << CFA_P4_EEM_ENTRY_VALID_SHIFT))
292 memcpy((uint8_t *)(uintptr_t)op->hw.base_addr +
300 static int hcapi_cfa_key_hw_op_del(struct hcapi_cfa_hwop *op,
301 struct hcapi_cfa_key_data *key_obj)
304 struct cfa_p4_eem_64b_entry table_entry;
310 (uint8_t *)(uintptr_t)op->hw.base_addr +
315 * If this is not a valid entry then report failure.
317 if (table_entry.hdr.word1 & (1 << CFA_P4_EEM_ENTRY_VALID_SHIFT)) {
319 * If a key has been provided then verify the key matches
320 * before deleting the entry.
322 if (key_obj->data != NULL) {
323 if (memcmp(&table_entry,
336 memset((uint8_t *)(uintptr_t)op->hw.base_addr +
345 /** Apporiximation of hcapi_cfa_key_hw_op()
349 int hcapi_cfa_key_hw_op(struct hcapi_cfa_hwop *op,
350 struct hcapi_cfa_key_tbl *key_tbl,
351 struct hcapi_cfa_key_data *key_obj,
352 struct hcapi_cfa_key_loc *key_loc)
363 hcapi_get_table_page((struct hcapi_cfa_em_table *)
367 if (op->hw.base_addr == 0)
370 switch (op->opcode) {
371 case HCAPI_CFA_HWOPS_PUT: /**< Write to HW operation */
372 rc = hcapi_cfa_key_hw_op_put(op, key_obj);
374 case HCAPI_CFA_HWOPS_GET: /**< Read from HW operation */
375 rc = hcapi_cfa_key_hw_op_get(op, key_obj);
377 case HCAPI_CFA_HWOPS_ADD:
378 /**< For operations which require more than
379 * simple writes to HW, this operation is used. The
380 * distinction with this operation when compared
381 * to the PUT ops is that this operation is used
382 * in conjunction with the HCAPI_CFA_HWOPS_DEL
383 * op to remove the operations issued by the
387 rc = hcapi_cfa_key_hw_op_add(op, key_obj);
390 case HCAPI_CFA_HWOPS_DEL:
391 rc = hcapi_cfa_key_hw_op_del(op, key_obj);