1 /* 2 * Copyright 2008-2012 Freescale Semiconductor Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution. 11 * * Neither the name of Freescale Semiconductor nor the 12 * names of its contributors may be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * 16 * ALTERNATIVELY, this software may be distributed under the terms of the 17 * GNU General Public License ("GPL") as published by the Free Software 18 * Foundation, either version 2 of that License or (at your option) any 19 * later version. 20 * 21 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY 22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include "fsl_fman_kg.h" 34 35 /****************************************/ 36 /* static functions */ 37 /****************************************/ 38 39 40 static uint32_t build_ar_bind_scheme(uint8_t hwport_id, bool write) 41 { 42 uint32_t rw; 43 44 rw = write ? (uint32_t)FM_KG_KGAR_WRITE : (uint32_t)FM_KG_KGAR_READ; 45 46 return (uint32_t)(FM_KG_KGAR_GO | 47 rw | 48 FM_PCD_KG_KGAR_SEL_PORT_ENTRY | 49 hwport_id | 50 FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP); 51 } 52 53 static void clear_pe_all_scheme(struct fman_kg_regs *regs, uint8_t hwport_id) 54 { 55 uint32_t ar; 56 57 fman_kg_write_sp(regs, 0xffffffff, 0); 58 59 ar = build_ar_bind_scheme(hwport_id, TRUE); 60 fman_kg_write_ar_wait(regs, ar); 61 } 62 63 static uint32_t build_ar_bind_cls_plan(uint8_t hwport_id, bool write) 64 { 65 uint32_t rw; 66 67 rw = write ? (uint32_t)FM_KG_KGAR_WRITE : (uint32_t)FM_KG_KGAR_READ; 68 69 return (uint32_t)(FM_KG_KGAR_GO | 70 rw | 71 FM_PCD_KG_KGAR_SEL_PORT_ENTRY | 72 hwport_id | 73 FM_PCD_KG_KGAR_SEL_PORT_WSEL_CPP); 74 } 75 76 static void clear_pe_all_cls_plan(struct fman_kg_regs *regs, uint8_t hwport_id) 77 { 78 uint32_t ar; 79 80 fman_kg_write_cpp(regs, 0); 81 82 ar = build_ar_bind_cls_plan(hwport_id, TRUE); 83 fman_kg_write_ar_wait(regs, ar); 84 } 85 86 static uint8_t get_gen_ht_code(enum fman_kg_gen_extract_src src, 87 bool no_validation, 88 uint8_t *offset) 89 { 90 int code; 91 92 switch (src) { 93 case E_FMAN_KG_GEN_EXTRACT_ETH: 94 code = no_validation ? 0x73 : 0x3; 95 break; 96 97 case E_FMAN_KG_GEN_EXTRACT_ETYPE: 98 code = no_validation ? 0x77 : 0x7; 99 break; 100 101 case E_FMAN_KG_GEN_EXTRACT_SNAP: 102 code = no_validation ? 0x74 : 0x4; 103 break; 104 105 case E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_1: 106 code = no_validation ? 0x75 : 0x5; 107 break; 108 109 case E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_N: 110 code = no_validation ? 0x76 : 0x6; 111 break; 112 113 case E_FMAN_KG_GEN_EXTRACT_PPPoE: 114 code = no_validation ? 0x78 : 0x8; 115 break; 116 117 case E_FMAN_KG_GEN_EXTRACT_MPLS_1: 118 code = no_validation ? 0x79 : 0x9; 119 break; 120 121 case E_FMAN_KG_GEN_EXTRACT_MPLS_2: 122 code = no_validation ? FM_KG_SCH_GEN_HT_INVALID : 0x19; 123 break; 124 125 case E_FMAN_KG_GEN_EXTRACT_MPLS_3: 126 code = no_validation ? FM_KG_SCH_GEN_HT_INVALID : 0x29; 127 break; 128 129 case E_FMAN_KG_GEN_EXTRACT_MPLS_N: 130 code = no_validation ? 0x7a : 0xa; 131 break; 132 133 case E_FMAN_KG_GEN_EXTRACT_IPv4_1: 134 code = no_validation ? 0x7b : 0xb; 135 break; 136 137 case E_FMAN_KG_GEN_EXTRACT_IPv6_1: 138 code = no_validation ? 0x7b : 0x1b; 139 break; 140 141 case E_FMAN_KG_GEN_EXTRACT_IPv4_2: 142 code = no_validation ? 0x7c : 0xc; 143 break; 144 145 case E_FMAN_KG_GEN_EXTRACT_IPv6_2: 146 code = no_validation ? 0x7c : 0x1c; 147 break; 148 149 case E_FMAN_KG_GEN_EXTRACT_MINENCAP: 150 code = no_validation ? 0x7c : 0x2c; 151 break; 152 153 case E_FMAN_KG_GEN_EXTRACT_IP_PID: 154 code = no_validation ? 0x72 : 0x2; 155 break; 156 157 case E_FMAN_KG_GEN_EXTRACT_GRE: 158 code = no_validation ? 0x7d : 0xd; 159 break; 160 161 case E_FMAN_KG_GEN_EXTRACT_TCP: 162 code = no_validation ? 0x7e : 0xe; 163 break; 164 165 case E_FMAN_KG_GEN_EXTRACT_UDP: 166 code = no_validation ? 0x7e : 0x1e; 167 break; 168 169 case E_FMAN_KG_GEN_EXTRACT_SCTP: 170 code = no_validation ? 0x7e : 0x3e; 171 break; 172 173 case E_FMAN_KG_GEN_EXTRACT_DCCP: 174 code = no_validation ? 0x7e : 0x4e; 175 break; 176 177 case E_FMAN_KG_GEN_EXTRACT_IPSEC_AH: 178 code = no_validation ? 0x7e : 0x2e; 179 break; 180 181 case E_FMAN_KG_GEN_EXTRACT_IPSEC_ESP: 182 code = no_validation ? 0x7e : 0x6e; 183 break; 184 185 case E_FMAN_KG_GEN_EXTRACT_SHIM_1: 186 code = 0x70; 187 break; 188 189 case E_FMAN_KG_GEN_EXTRACT_SHIM_2: 190 code = 0x71; 191 break; 192 193 case E_FMAN_KG_GEN_EXTRACT_FROM_DFLT: 194 code = 0x10; 195 break; 196 197 case E_FMAN_KG_GEN_EXTRACT_FROM_FRAME_START: 198 code = 0x40; 199 break; 200 201 case E_FMAN_KG_GEN_EXTRACT_FROM_PARSE_RESULT: 202 code = 0x20; 203 break; 204 205 case E_FMAN_KG_GEN_EXTRACT_FROM_END_OF_PARSE: 206 code = 0x7f; 207 break; 208 209 case E_FMAN_KG_GEN_EXTRACT_FROM_FQID: 210 code = 0x20; 211 *offset += 0x20; 212 break; 213 214 default: 215 code = FM_KG_SCH_GEN_HT_INVALID; 216 } 217 218 return (uint8_t)code; 219 } 220 221 static uint32_t build_ar_scheme(uint8_t scheme, 222 uint8_t hwport_id, 223 bool update_counter, 224 bool write) 225 { 226 uint32_t rw; 227 228 rw = (uint32_t)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ); 229 230 return (uint32_t)(FM_KG_KGAR_GO | 231 rw | 232 FM_KG_KGAR_SEL_SCHEME_ENTRY | 233 hwport_id | 234 ((uint32_t)scheme << FM_KG_KGAR_NUM_SHIFT) | 235 (update_counter ? FM_KG_KGAR_SCM_WSEL_UPDATE_CNT : 0)); 236 } 237 238 static uint32_t build_ar_cls_plan(uint8_t grp, 239 uint8_t entries_mask, 240 uint8_t hwport_id, 241 bool write) 242 { 243 uint32_t rw; 244 245 rw = (uint32_t)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ); 246 247 return (uint32_t)(FM_KG_KGAR_GO | 248 rw | 249 FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY | 250 hwport_id | 251 ((uint32_t)grp << FM_KG_KGAR_NUM_SHIFT) | 252 ((uint32_t)entries_mask << FM_KG_KGAR_WSEL_SHIFT)); 253 } 254 255 int fman_kg_write_ar_wait(struct fman_kg_regs *regs, uint32_t fmkg_ar) 256 { 257 iowrite32be(fmkg_ar, ®s->fmkg_ar); 258 /* Wait for GO to be idle and read error */ 259 while ((fmkg_ar = ioread32be(®s->fmkg_ar)) & FM_KG_KGAR_GO) ; 260 if (fmkg_ar & FM_PCD_KG_KGAR_ERR) 261 return -EINVAL; 262 return 0; 263 } 264 265 void fman_kg_write_sp(struct fman_kg_regs *regs, uint32_t sp, bool add) 266 { 267 268 struct fman_kg_pe_regs *kgpe_regs; 269 uint32_t tmp; 270 271 kgpe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]); 272 tmp = ioread32be(&kgpe_regs->fmkg_pe_sp); 273 274 if (add) 275 tmp |= sp; 276 else /* clear */ 277 tmp &= ~sp; 278 279 iowrite32be(tmp, &kgpe_regs->fmkg_pe_sp); 280 281 } 282 283 void fman_kg_write_cpp(struct fman_kg_regs *regs, uint32_t cpp) 284 { 285 struct fman_kg_pe_regs *kgpe_regs; 286 287 kgpe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]); 288 289 iowrite32be(cpp, &kgpe_regs->fmkg_pe_cpp); 290 } 291 292 void fman_kg_get_event(struct fman_kg_regs *regs, 293 uint32_t *event, 294 uint32_t *scheme_idx) 295 { 296 uint32_t mask, force; 297 298 *event = ioread32be(®s->fmkg_eer); 299 mask = ioread32be(®s->fmkg_eeer); 300 *scheme_idx = ioread32be(®s->fmkg_seer); 301 *scheme_idx &= ioread32be(®s->fmkg_seeer); 302 303 *event &= mask; 304 305 /* clear the forced events */ 306 force = ioread32be(®s->fmkg_feer); 307 if (force & *event) 308 iowrite32be(force & ~*event ,®s->fmkg_feer); 309 310 iowrite32be(*event, ®s->fmkg_eer); 311 iowrite32be(*scheme_idx, ®s->fmkg_seer); 312 } 313 314 315 void fman_kg_init(struct fman_kg_regs *regs, 316 uint32_t exceptions, 317 uint32_t dflt_nia) 318 { 319 uint32_t tmp; 320 int i; 321 322 iowrite32be(FM_EX_KG_DOUBLE_ECC | FM_EX_KG_KEYSIZE_OVERFLOW, 323 ®s->fmkg_eer); 324 325 tmp = 0; 326 if (exceptions & FM_EX_KG_DOUBLE_ECC) 327 tmp |= FM_EX_KG_DOUBLE_ECC; 328 329 if (exceptions & FM_EX_KG_KEYSIZE_OVERFLOW) 330 tmp |= FM_EX_KG_KEYSIZE_OVERFLOW; 331 332 iowrite32be(tmp, ®s->fmkg_eeer); 333 iowrite32be(0, ®s->fmkg_fdor); 334 iowrite32be(0, ®s->fmkg_gdv0r); 335 iowrite32be(0, ®s->fmkg_gdv1r); 336 iowrite32be(dflt_nia, ®s->fmkg_gcr); 337 338 /* Clear binding between ports to schemes and classification plans 339 * so that all ports are not bound to any scheme/classification plan */ 340 for (i = 0; i < FMAN_MAX_NUM_OF_HW_PORTS; i++) { 341 clear_pe_all_scheme(regs, (uint8_t)i); 342 clear_pe_all_cls_plan(regs, (uint8_t)i); 343 } 344 } 345 346 void fman_kg_enable_scheme_interrupts(struct fman_kg_regs *regs) 347 { 348 /* enable and enable all scheme interrupts */ 349 iowrite32be(0xFFFFFFFF, ®s->fmkg_seer); 350 iowrite32be(0xFFFFFFFF, ®s->fmkg_seeer); 351 } 352 353 void fman_kg_enable(struct fman_kg_regs *regs) 354 { 355 iowrite32be(ioread32be(®s->fmkg_gcr) | FM_KG_KGGCR_EN, 356 ®s->fmkg_gcr); 357 } 358 359 void fman_kg_disable(struct fman_kg_regs *regs) 360 { 361 iowrite32be(ioread32be(®s->fmkg_gcr) & ~FM_KG_KGGCR_EN, 362 ®s->fmkg_gcr); 363 } 364 365 void fman_kg_set_data_after_prs(struct fman_kg_regs *regs, uint8_t offset) 366 { 367 iowrite32be(offset, ®s->fmkg_fdor); 368 } 369 370 void fman_kg_set_dflt_val(struct fman_kg_regs *regs, 371 uint8_t def_id, 372 uint32_t val) 373 { 374 if(def_id == 0) 375 iowrite32be(val, ®s->fmkg_gdv0r); 376 else 377 iowrite32be(val, ®s->fmkg_gdv1r); 378 } 379 380 381 void fman_kg_set_exception(struct fman_kg_regs *regs, 382 uint32_t exception, 383 bool enable) 384 { 385 uint32_t tmp; 386 387 tmp = ioread32be(®s->fmkg_eeer); 388 389 if (enable) { 390 tmp |= exception; 391 } else { 392 tmp &= ~exception; 393 } 394 395 iowrite32be(tmp, ®s->fmkg_eeer); 396 } 397 398 void fman_kg_get_exception(struct fman_kg_regs *regs, 399 uint32_t *events, 400 uint32_t *scheme_ids, 401 bool clear) 402 { 403 uint32_t mask; 404 405 *events = ioread32be(®s->fmkg_eer); 406 mask = ioread32be(®s->fmkg_eeer); 407 *events &= mask; 408 409 *scheme_ids = 0; 410 411 if (*events & FM_EX_KG_KEYSIZE_OVERFLOW) { 412 *scheme_ids = ioread32be(®s->fmkg_seer); 413 mask = ioread32be(®s->fmkg_seeer); 414 *scheme_ids &= mask; 415 } 416 417 if (clear) { 418 iowrite32be(*scheme_ids, ®s->fmkg_seer); 419 iowrite32be(*events, ®s->fmkg_eer); 420 } 421 } 422 423 void fman_kg_get_capture(struct fman_kg_regs *regs, 424 struct fman_kg_ex_ecc_attr *ecc_attr, 425 bool clear) 426 { 427 uint32_t tmp; 428 429 tmp = ioread32be(®s->fmkg_serc); 430 431 if (tmp & KG_FMKG_SERC_CAP) { 432 /* Captured data is valid */ 433 ecc_attr->valid = TRUE; 434 ecc_attr->double_ecc = 435 (bool)((tmp & KG_FMKG_SERC_CET) ? TRUE : FALSE); 436 ecc_attr->single_ecc_count = 437 (uint8_t)((tmp & KG_FMKG_SERC_CNT_MSK) >> 438 KG_FMKG_SERC_CNT_SHIFT); 439 ecc_attr->addr = (uint16_t)(tmp & KG_FMKG_SERC_ADDR_MSK); 440 441 if (clear) 442 iowrite32be(KG_FMKG_SERC_CAP, ®s->fmkg_serc); 443 } else { 444 /* No ECC error is captured */ 445 ecc_attr->valid = FALSE; 446 } 447 } 448 449 int fman_kg_build_scheme(struct fman_kg_scheme_params *params, 450 struct fman_kg_scheme_regs *scheme_regs) 451 { 452 struct fman_kg_extract_params *extract_params; 453 struct fman_kg_gen_extract_params *gen_params; 454 uint32_t tmp_reg, i, select, mask, fqb; 455 uint8_t offset, shift, ht; 456 457 /* Zero out all registers so no need to care about unused ones */ 458 memset(scheme_regs, 0, sizeof(struct fman_kg_scheme_regs)); 459 460 /* Mode register */ 461 tmp_reg = fm_kg_build_nia(params->next_engine, 462 params->next_engine_action); 463 if (tmp_reg == KG_NIA_INVALID) { 464 return -EINVAL; 465 } 466 467 if (params->next_engine == E_FMAN_PCD_PLCR) { 468 tmp_reg |= FMAN_KG_SCH_MODE_NIA_PLCR; 469 } 470 else if (params->next_engine == E_FMAN_PCD_CC) { 471 tmp_reg |= (uint32_t)params->cc_params.base_offset << 472 FMAN_KG_SCH_MODE_CCOBASE_SHIFT; 473 } 474 475 tmp_reg |= FMAN_KG_SCH_MODE_EN; 476 scheme_regs->kgse_mode = tmp_reg; 477 478 /* Match vector */ 479 scheme_regs->kgse_mv = params->match_vector; 480 481 extract_params = ¶ms->extract_params; 482 483 /* Scheme default values registers */ 484 scheme_regs->kgse_dv0 = extract_params->def_scheme_0; 485 scheme_regs->kgse_dv1 = extract_params->def_scheme_1; 486 487 /* Extract Known Fields Command register */ 488 scheme_regs->kgse_ekfc = extract_params->known_fields; 489 490 /* Entry Extract Known Default Value register */ 491 tmp_reg = 0; 492 tmp_reg |= extract_params->known_fields_def.mac_addr << 493 FMAN_KG_SCH_DEF_MAC_ADDR_SHIFT; 494 tmp_reg |= extract_params->known_fields_def.vlan_tci << 495 FMAN_KG_SCH_DEF_VLAN_TCI_SHIFT; 496 tmp_reg |= extract_params->known_fields_def.etype << 497 FMAN_KG_SCH_DEF_ETYPE_SHIFT; 498 tmp_reg |= extract_params->known_fields_def.ppp_sid << 499 FMAN_KG_SCH_DEF_PPP_SID_SHIFT; 500 tmp_reg |= extract_params->known_fields_def.ppp_pid << 501 FMAN_KG_SCH_DEF_PPP_PID_SHIFT; 502 tmp_reg |= extract_params->known_fields_def.mpls << 503 FMAN_KG_SCH_DEF_MPLS_SHIFT; 504 tmp_reg |= extract_params->known_fields_def.ip_addr << 505 FMAN_KG_SCH_DEF_IP_ADDR_SHIFT; 506 tmp_reg |= extract_params->known_fields_def.ptype << 507 FMAN_KG_SCH_DEF_PTYPE_SHIFT; 508 tmp_reg |= extract_params->known_fields_def.ip_tos_tc << 509 FMAN_KG_SCH_DEF_IP_TOS_TC_SHIFT; 510 tmp_reg |= extract_params->known_fields_def.ipv6_fl << 511 FMAN_KG_SCH_DEF_IPv6_FL_SHIFT; 512 tmp_reg |= extract_params->known_fields_def.ipsec_spi << 513 FMAN_KG_SCH_DEF_IPSEC_SPI_SHIFT; 514 tmp_reg |= extract_params->known_fields_def.l4_port << 515 FMAN_KG_SCH_DEF_L4_PORT_SHIFT; 516 tmp_reg |= extract_params->known_fields_def.tcp_flg << 517 FMAN_KG_SCH_DEF_TCP_FLG_SHIFT; 518 519 scheme_regs->kgse_ekdv = tmp_reg; 520 521 /* Generic extract registers */ 522 if (extract_params->gen_extract_num > FM_KG_NUM_OF_GENERIC_REGS) { 523 return -EINVAL; 524 } 525 526 for (i = 0; i < extract_params->gen_extract_num; i++) { 527 gen_params = extract_params->gen_extract + i; 528 529 tmp_reg = FMAN_KG_SCH_GEN_VALID; 530 tmp_reg |= (uint32_t)gen_params->def_val << 531 FMAN_KG_SCH_GEN_DEF_SHIFT; 532 533 if (gen_params->type == E_FMAN_KG_HASH_EXTRACT) { 534 if ((gen_params->extract > FMAN_KG_SCH_GEN_SIZE_MAX) || 535 (gen_params->extract == 0)) { 536 return -EINVAL; 537 } 538 } else { 539 tmp_reg |= FMAN_KG_SCH_GEN_OR; 540 } 541 542 tmp_reg |= (uint32_t)gen_params->extract << 543 FMAN_KG_SCH_GEN_SIZE_SHIFT; 544 tmp_reg |= (uint32_t)gen_params->mask << 545 FMAN_KG_SCH_GEN_MASK_SHIFT; 546 547 offset = gen_params->offset; 548 ht = get_gen_ht_code(gen_params->src, 549 gen_params->no_validation, 550 &offset); 551 tmp_reg |= (uint32_t)ht << FMAN_KG_SCH_GEN_HT_SHIFT; 552 tmp_reg |= offset; 553 554 scheme_regs->kgse_gec[i] = tmp_reg; 555 } 556 557 /* Masks registers */ 558 if (extract_params->masks_num > FM_KG_EXTRACT_MASKS_NUM) { 559 return -EINVAL; 560 } 561 562 select = 0; 563 mask = 0; 564 fqb = 0; 565 for (i = 0; i < extract_params->masks_num; i++) { 566 /* MCSx fields */ 567 KG_GET_MASK_SEL_SHIFT(shift, i); 568 if (extract_params->masks[i].is_known) { 569 /* Mask known field */ 570 select |= extract_params->masks[i].field_or_gen_idx << 571 shift; 572 } else { 573 /* Mask generic extract */ 574 select |= (extract_params->masks[i].field_or_gen_idx + 575 FM_KG_MASK_SEL_GEN_BASE) << shift; 576 } 577 578 /* MOx fields - spread between se_bmch and se_fqb registers */ 579 KG_GET_MASK_OFFSET_SHIFT(shift, i); 580 if (i < 2) { 581 select |= (uint32_t)extract_params->masks[i].offset << 582 shift; 583 } else { 584 fqb |= (uint32_t)extract_params->masks[i].offset << 585 shift; 586 } 587 588 /* BMx fields */ 589 KG_GET_MASK_SHIFT(shift, i); 590 mask |= (uint32_t)extract_params->masks[i].mask << shift; 591 } 592 593 /* Finish with rest of BMx fileds - 594 * don't mask bits for unused masks by setting 595 * corresponding BMx field = 0xFF */ 596 for (i = extract_params->masks_num; i < FM_KG_EXTRACT_MASKS_NUM; i++) { 597 KG_GET_MASK_SHIFT(shift, i); 598 mask |= 0xFF << shift; 599 } 600 601 scheme_regs->kgse_bmch = select; 602 scheme_regs->kgse_bmcl = mask; 603 604 /* Finish with FQB register initialization. 605 * Check fqid is 24-bit value. */ 606 if (params->base_fqid & ~0x00FFFFFF) { 607 return -EINVAL; 608 } 609 610 fqb |= params->base_fqid; 611 scheme_regs->kgse_fqb = fqb; 612 613 /* Hash Configuration register */ 614 tmp_reg = 0; 615 if (params->hash_params.use_hash) { 616 /* Check hash mask is 24-bit value */ 617 if (params->hash_params.mask & ~0x00FFFFFF) { 618 return -EINVAL; 619 } 620 621 /* Hash function produces 64-bit value, 24 bits of that 622 * are used to generate fq_id and policer profile. 623 * Thus, maximal shift is 40 bits to allow 24 bits out of 64. 624 */ 625 if (params->hash_params.shift_r > FMAN_KG_SCH_HASH_HSHIFT_MAX) { 626 return -EINVAL; 627 } 628 629 tmp_reg |= params->hash_params.mask; 630 tmp_reg |= (uint32_t)params->hash_params.shift_r << 631 FMAN_KG_SCH_HASH_HSHIFT_SHIFT; 632 633 if (params->hash_params.sym) { 634 tmp_reg |= FMAN_KG_SCH_HASH_SYM; 635 } 636 637 } 638 639 if (params->bypass_fqid_gen) { 640 tmp_reg |= FMAN_KG_SCH_HASH_NO_FQID_GEN; 641 } 642 643 scheme_regs->kgse_hc = tmp_reg; 644 645 /* Policer Profile register */ 646 if (params->policer_params.bypass_pp_gen) { 647 tmp_reg = 0; 648 } else { 649 /* Lower 8 bits of 24-bits extracted from hash result 650 * are used for policer profile generation. 651 * That leaves maximum shift value = 23. */ 652 if (params->policer_params.shift > FMAN_KG_SCH_PP_SHIFT_MAX) { 653 return -EINVAL; 654 } 655 656 tmp_reg = params->policer_params.base; 657 tmp_reg |= ((uint32_t)params->policer_params.shift << 658 FMAN_KG_SCH_PP_SH_SHIFT) & 659 FMAN_KG_SCH_PP_SH_MASK; 660 tmp_reg |= ((uint32_t)params->policer_params.shift << 661 FMAN_KG_SCH_PP_SL_SHIFT) & 662 FMAN_KG_SCH_PP_SL_MASK; 663 tmp_reg |= (uint32_t)params->policer_params.mask << 664 FMAN_KG_SCH_PP_MASK_SHIFT; 665 } 666 667 scheme_regs->kgse_ppc = tmp_reg; 668 669 /* Coarse Classification Bit Select register */ 670 if (params->next_engine == E_FMAN_PCD_CC) { 671 scheme_regs->kgse_ccbs = params->cc_params.qlcv_bits_sel; 672 } 673 674 /* Packets Counter register */ 675 if (params->update_counter) { 676 scheme_regs->kgse_spc = params->counter_value; 677 } 678 679 return 0; 680 } 681 682 int fman_kg_write_scheme(struct fman_kg_regs *regs, 683 uint8_t scheme_id, 684 uint8_t hwport_id, 685 struct fman_kg_scheme_regs *scheme_regs, 686 bool update_counter) 687 { 688 struct fman_kg_scheme_regs *kgse_regs; 689 uint32_t tmp_reg; 690 int err, i; 691 692 /* Write indirect scheme registers */ 693 kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]); 694 695 iowrite32be(scheme_regs->kgse_mode, &kgse_regs->kgse_mode); 696 iowrite32be(scheme_regs->kgse_ekfc, &kgse_regs->kgse_ekfc); 697 iowrite32be(scheme_regs->kgse_ekdv, &kgse_regs->kgse_ekdv); 698 iowrite32be(scheme_regs->kgse_bmch, &kgse_regs->kgse_bmch); 699 iowrite32be(scheme_regs->kgse_bmcl, &kgse_regs->kgse_bmcl); 700 iowrite32be(scheme_regs->kgse_fqb, &kgse_regs->kgse_fqb); 701 iowrite32be(scheme_regs->kgse_hc, &kgse_regs->kgse_hc); 702 iowrite32be(scheme_regs->kgse_ppc, &kgse_regs->kgse_ppc); 703 iowrite32be(scheme_regs->kgse_spc, &kgse_regs->kgse_spc); 704 iowrite32be(scheme_regs->kgse_dv0, &kgse_regs->kgse_dv0); 705 iowrite32be(scheme_regs->kgse_dv1, &kgse_regs->kgse_dv1); 706 iowrite32be(scheme_regs->kgse_ccbs, &kgse_regs->kgse_ccbs); 707 iowrite32be(scheme_regs->kgse_mv, &kgse_regs->kgse_mv); 708 709 for (i = 0 ; i < FM_KG_NUM_OF_GENERIC_REGS ; i++) 710 iowrite32be(scheme_regs->kgse_gec[i], &kgse_regs->kgse_gec[i]); 711 712 /* Write AR (Action register) */ 713 tmp_reg = build_ar_scheme(scheme_id, hwport_id, update_counter, TRUE); 714 err = fman_kg_write_ar_wait(regs, tmp_reg); 715 return err; 716 } 717 718 int fman_kg_delete_scheme(struct fman_kg_regs *regs, 719 uint8_t scheme_id, 720 uint8_t hwport_id) 721 { 722 struct fman_kg_scheme_regs *kgse_regs; 723 uint32_t tmp_reg; 724 int err, i; 725 726 kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]); 727 728 /* Clear all registers including enable bit in mode register */ 729 for (i = 0; i < (sizeof(struct fman_kg_scheme_regs)) / 4; ++i) { 730 iowrite32be(0, ((uint32_t *)kgse_regs + i)); 731 } 732 733 /* Write AR (Action register) */ 734 tmp_reg = build_ar_scheme(scheme_id, hwport_id, FALSE, TRUE); 735 err = fman_kg_write_ar_wait(regs, tmp_reg); 736 return err; 737 } 738 739 int fman_kg_get_scheme_counter(struct fman_kg_regs *regs, 740 uint8_t scheme_id, 741 uint8_t hwport_id, 742 uint32_t *counter) 743 { 744 struct fman_kg_scheme_regs *kgse_regs; 745 uint32_t tmp_reg; 746 int err; 747 748 kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]); 749 750 tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, FALSE); 751 err = fman_kg_write_ar_wait(regs, tmp_reg); 752 753 if (err != 0) 754 return err; 755 756 *counter = ioread32be(&kgse_regs->kgse_spc); 757 758 return 0; 759 } 760 761 int fman_kg_set_scheme_counter(struct fman_kg_regs *regs, 762 uint8_t scheme_id, 763 uint8_t hwport_id, 764 uint32_t counter) 765 { 766 struct fman_kg_scheme_regs *kgse_regs; 767 uint32_t tmp_reg; 768 int err; 769 770 kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]); 771 772 tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, FALSE); 773 774 err = fman_kg_write_ar_wait(regs, tmp_reg); 775 if (err != 0) 776 return err; 777 778 /* Keygen indirect access memory contains all scheme_id registers 779 * by now. Change only counter value. */ 780 iowrite32be(counter, &kgse_regs->kgse_spc); 781 782 /* Write back scheme registers */ 783 tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, TRUE); 784 err = fman_kg_write_ar_wait(regs, tmp_reg); 785 786 return err; 787 } 788 789 uint32_t fman_kg_get_schemes_total_counter(struct fman_kg_regs *regs) 790 { 791 return ioread32be(®s->fmkg_tpc); 792 } 793 794 int fman_kg_build_cls_plan(struct fman_kg_cls_plan_params *params, 795 struct fman_kg_cp_regs *cls_plan_regs) 796 { 797 uint8_t entries_set, entry_bit; 798 int i; 799 800 /* Zero out all group's register */ 801 memset(cls_plan_regs, 0, sizeof(struct fman_kg_cp_regs)); 802 803 /* Go over all classification entries in params->entries_mask and 804 * configure the corresponding cpe register */ 805 entries_set = params->entries_mask; 806 for (i = 0; entries_set; i++) { 807 entry_bit = (uint8_t)(0x80 >> i); 808 if ((entry_bit & entries_set) == 0) 809 continue; 810 entries_set ^= entry_bit; 811 cls_plan_regs->kgcpe[i] = params->mask_vector[i]; 812 } 813 814 return 0; 815 } 816 817 int fman_kg_write_cls_plan(struct fman_kg_regs *regs, 818 uint8_t grp_id, 819 uint8_t entries_mask, 820 uint8_t hwport_id, 821 struct fman_kg_cp_regs *cls_plan_regs) 822 { 823 struct fman_kg_cp_regs *kgcpe_regs; 824 uint32_t tmp_reg; 825 int i, err; 826 827 /* Check group index is valid and the group isn't empty */ 828 if (grp_id >= FM_KG_CLS_PLAN_GRPS_NUM) 829 return -EINVAL; 830 831 /* Write indirect classification plan registers */ 832 kgcpe_regs = (struct fman_kg_cp_regs *)&(regs->fmkg_indirect[0]); 833 834 for (i = 0; i < FM_KG_NUM_CLS_PLAN_ENTR; i++) { 835 iowrite32be(cls_plan_regs->kgcpe[i], &kgcpe_regs->kgcpe[i]); 836 } 837 838 tmp_reg = build_ar_cls_plan(grp_id, entries_mask, hwport_id, TRUE); 839 err = fman_kg_write_ar_wait(regs, tmp_reg); 840 return err; 841 } 842 843 int fman_kg_write_bind_schemes(struct fman_kg_regs *regs, 844 uint8_t hwport_id, 845 uint32_t schemes) 846 { 847 struct fman_kg_pe_regs *kg_pe_regs; 848 uint32_t tmp_reg; 849 int err; 850 851 kg_pe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]); 852 853 iowrite32be(schemes, &kg_pe_regs->fmkg_pe_sp); 854 855 tmp_reg = build_ar_bind_scheme(hwport_id, TRUE); 856 err = fman_kg_write_ar_wait(regs, tmp_reg); 857 return err; 858 } 859 860 int fman_kg_build_bind_cls_plans(uint8_t grp_base, 861 uint8_t grp_mask, 862 uint32_t *bind_cls_plans) 863 { 864 /* Check grp_base and grp_mask are 5-bits values */ 865 if ((grp_base & ~0x0000001F) || (grp_mask & ~0x0000001F)) 866 return -EINVAL; 867 868 *bind_cls_plans = (uint32_t) ((grp_mask << FMAN_KG_PE_CPP_MASK_SHIFT) | grp_base); 869 return 0; 870 } 871 872 873 int fman_kg_write_bind_cls_plans(struct fman_kg_regs *regs, 874 uint8_t hwport_id, 875 uint32_t bind_cls_plans) 876 { 877 struct fman_kg_pe_regs *kg_pe_regs; 878 uint32_t tmp_reg; 879 int err; 880 881 kg_pe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]); 882 883 iowrite32be(bind_cls_plans, &kg_pe_regs->fmkg_pe_cpp); 884 885 tmp_reg = build_ar_bind_cls_plan(hwport_id, TRUE); 886 err = fman_kg_write_ar_wait(regs, tmp_reg); 887 return err; 888 } 889