1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019-2021 Broadcom
13 #include "hcapi_cfa_defs.h"
15 #define HCAPI_CFA_LKUP_SEED_MEM_SIZE 512
16 uint32_t hcapi_cfa_lkup_lkup3_init_cfg;
17 uint32_t hcapi_cfa_lkup_em_seed_mem[HCAPI_CFA_LKUP_SEED_MEM_SIZE];
18 bool hcapi_cfa_lkup_init;
20 static inline uint32_t SWAP_WORDS32(uint32_t val32)
22 return (((val32 & 0x0000ffff) << 16) |
23 ((val32 & 0xffff0000) >> 16));
26 static void hcapi_cfa_seeds_init(void)
31 if (hcapi_cfa_lkup_init)
34 hcapi_cfa_lkup_init = true;
36 /* Initialize the lfsr */
39 /* RX and TX use the same seed values */
40 hcapi_cfa_lkup_lkup3_init_cfg = SWAP_WORDS32(rand32());
42 for (i = 0; i < HCAPI_CFA_LKUP_SEED_MEM_SIZE / 2; i++) {
43 r = SWAP_WORDS32(rand32());
44 hcapi_cfa_lkup_em_seed_mem[i * 2] = r;
45 r = SWAP_WORDS32(rand32());
46 hcapi_cfa_lkup_em_seed_mem[i * 2 + 1] = (r & 0x1);
50 /* CRC32i support for Key0 hash */
51 #define ucrc32(ch, crc) (crc32tbl[((crc) ^ (ch)) & 0xff] ^ ((crc) >> 8))
52 #define crc32(x, y) crc32i(~0, x, y)
54 static const uint32_t crc32tbl[] = { /* CRC polynomial 0xedb88320 */
55 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
56 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
57 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
58 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
59 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
60 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
61 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
62 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
63 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
64 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
65 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
66 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
67 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
68 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
69 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
70 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
71 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
72 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
73 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
74 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
75 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
76 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
77 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
78 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
79 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
80 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
81 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
82 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
83 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
84 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
85 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
86 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
87 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
88 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
89 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
90 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
91 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
92 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
93 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
94 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
95 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
96 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
97 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
98 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
99 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
100 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
101 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
102 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
103 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
104 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
105 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
106 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
107 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
108 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
109 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
110 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
111 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
112 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
113 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
114 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
115 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
116 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
117 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
118 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
121 static uint32_t hcapi_cfa_crc32i(uint32_t crc, const uint8_t *buf, size_t len)
126 TFP_DRV_LOG(DEBUG, "CRC2:");
128 for (l = (len - 1); l >= 0; l--) {
129 crc = ucrc32(buf[l], crc);
140 TFP_DRV_LOG(DEBUG, "\n");
146 static uint32_t hcapi_cfa_crc32_hash(uint8_t *key)
154 /* Do byte-wise XOR of the 52-byte HASH key first. */
158 for (i = CFA_P4_EEM_KEY_MAX_SIZE - 2; i >= 0; i--) {
159 index = index ^ *kptr;
164 val1 = hcapi_cfa_lkup_em_seed_mem[index * 2];
165 val2 = hcapi_cfa_lkup_em_seed_mem[index * 2 + 1];
167 temp[3] = (uint8_t)(val1 >> 24);
168 temp[2] = (uint8_t)(val1 >> 16);
169 temp[1] = (uint8_t)(val1 >> 8);
170 temp[0] = (uint8_t)(val1 & 0xff);
173 /* Start with seed */
175 val1 = hcapi_cfa_crc32i(~val1, temp, 4);
177 val1 = hcapi_cfa_crc32i(~val1,
178 (key - (CFA_P4_EEM_KEY_MAX_SIZE - 1)),
179 CFA_P4_EEM_KEY_MAX_SIZE);
183 val1 = hcapi_cfa_crc32i(~val1, temp, 4);
188 static uint32_t hcapi_cfa_lookup3_hash(uint8_t *in_key)
192 val1 = hashword(((const uint32_t *)(uintptr_t *)in_key) + 1,
193 CFA_P4_EEM_KEY_MAX_SIZE / (sizeof(uint32_t)),
194 hcapi_cfa_lkup_lkup3_init_cfg);
200 uint64_t hcapi_get_table_page(struct hcapi_cfa_em_table *mem,
210 * Use the level according to the num_level of page table
212 level = mem->num_lvl - 1;
214 addr = (uintptr_t)mem->pg_tbl[level].pg_va_tbl[page];
219 /** Approximation of HCAPI hcapi_cfa_key_hash()
224 uint64_t hcapi_cfa_key_hash(uint64_t *key_data,
231 * Init the seeds if needed
233 if (!hcapi_cfa_lkup_init)
234 hcapi_cfa_seeds_init();
236 key0_hash = hcapi_cfa_crc32_hash(((uint8_t *)key_data) +
239 key1_hash = hcapi_cfa_lookup3_hash((uint8_t *)key_data);
241 return ((uint64_t)key0_hash) << 32 | (uint64_t)key1_hash;
244 static int hcapi_cfa_key_hw_op_put(struct hcapi_cfa_hwop *op,
245 struct hcapi_cfa_key_data *key_obj)
249 memcpy((uint8_t *)(uintptr_t)op->hw.base_addr +
257 static int hcapi_cfa_key_hw_op_get(struct hcapi_cfa_hwop *op,
258 struct hcapi_cfa_key_data *key_obj)
262 memcpy(key_obj->data,
263 (uint8_t *)(uintptr_t)op->hw.base_addr +
270 static int hcapi_cfa_key_hw_op_add(struct hcapi_cfa_hwop *op,
271 struct hcapi_cfa_key_data *key_obj)
274 struct cfa_p4_eem_64b_entry table_entry;
280 (uint8_t *)(uintptr_t)op->hw.base_addr +
285 * If this is entry is valid then report failure
287 if (table_entry.hdr.word1 & (1 << CFA_P4_EEM_ENTRY_VALID_SHIFT))
290 memcpy((uint8_t *)(uintptr_t)op->hw.base_addr +
298 static int hcapi_cfa_key_hw_op_del(struct hcapi_cfa_hwop *op,
299 struct hcapi_cfa_key_data *key_obj)
302 struct cfa_p4_eem_64b_entry table_entry;
308 (uint8_t *)(uintptr_t)op->hw.base_addr +
313 * If this is not a valid entry then report failure.
315 if (table_entry.hdr.word1 & (1 << CFA_P4_EEM_ENTRY_VALID_SHIFT)) {
317 * If a key has been provided then verify the key matches
318 * before deleting the entry.
320 if (key_obj->data != NULL) {
321 if (memcmp(&table_entry,
334 memset((uint8_t *)(uintptr_t)op->hw.base_addr +
343 /** Apporiximation of hcapi_cfa_key_hw_op()
347 int hcapi_cfa_key_hw_op(struct hcapi_cfa_hwop *op,
348 struct hcapi_cfa_key_tbl *key_tbl,
349 struct hcapi_cfa_key_data *key_obj,
350 struct hcapi_cfa_key_loc *key_loc)
361 hcapi_get_table_page((struct hcapi_cfa_em_table *)
363 key_obj->offset / key_tbl->page_size);
364 /* Offset is adjusted to be the offset into the page */
365 key_obj->offset = key_obj->offset % key_tbl->page_size;
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);