Path: blob/main/sys/contrib/ncsw/Peripherals/FM/Pcd/fman_kg.c
48524 views
/*1* Copyright 2008-2012 Freescale Semiconductor Inc.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions are met:5* * Redistributions of source code must retain the above copyright6* notice, this list of conditions and the following disclaimer.7* * Redistributions in binary form must reproduce the above copyright8* notice, this list of conditions and the following disclaimer in the9* documentation and/or other materials provided with the distribution.10* * Neither the name of Freescale Semiconductor nor the11* names of its contributors may be used to endorse or promote products12* derived from this software without specific prior written permission.13*14*15* ALTERNATIVELY, this software may be distributed under the terms of the16* GNU General Public License ("GPL") as published by the Free Software17* Foundation, either version 2 of that License or (at your option) any18* later version.19*20* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY21* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED22* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE23* DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY24* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES25* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;26* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND27* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT28* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS29* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.30*/3132#include "fsl_fman_kg.h"3334/****************************************/35/* static functions */36/****************************************/373839static uint32_t build_ar_bind_scheme(uint8_t hwport_id, bool write)40{41uint32_t rw;4243rw = write ? (uint32_t)FM_KG_KGAR_WRITE : (uint32_t)FM_KG_KGAR_READ;4445return (uint32_t)(FM_KG_KGAR_GO |46rw |47FM_PCD_KG_KGAR_SEL_PORT_ENTRY |48hwport_id |49FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP);50}5152static void clear_pe_all_scheme(struct fman_kg_regs *regs, uint8_t hwport_id)53{54uint32_t ar;5556fman_kg_write_sp(regs, 0xffffffff, 0);5758ar = build_ar_bind_scheme(hwport_id, TRUE);59fman_kg_write_ar_wait(regs, ar);60}6162static uint32_t build_ar_bind_cls_plan(uint8_t hwport_id, bool write)63{64uint32_t rw;6566rw = write ? (uint32_t)FM_KG_KGAR_WRITE : (uint32_t)FM_KG_KGAR_READ;6768return (uint32_t)(FM_KG_KGAR_GO |69rw |70FM_PCD_KG_KGAR_SEL_PORT_ENTRY |71hwport_id |72FM_PCD_KG_KGAR_SEL_PORT_WSEL_CPP);73}7475static void clear_pe_all_cls_plan(struct fman_kg_regs *regs, uint8_t hwport_id)76{77uint32_t ar;7879fman_kg_write_cpp(regs, 0);8081ar = build_ar_bind_cls_plan(hwport_id, TRUE);82fman_kg_write_ar_wait(regs, ar);83}8485static uint8_t get_gen_ht_code(enum fman_kg_gen_extract_src src,86bool no_validation,87uint8_t *offset)88{89int code;9091switch (src) {92case E_FMAN_KG_GEN_EXTRACT_ETH:93code = no_validation ? 0x73 : 0x3;94break;9596case E_FMAN_KG_GEN_EXTRACT_ETYPE:97code = no_validation ? 0x77 : 0x7;98break;99100case E_FMAN_KG_GEN_EXTRACT_SNAP:101code = no_validation ? 0x74 : 0x4;102break;103104case E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_1:105code = no_validation ? 0x75 : 0x5;106break;107108case E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_N:109code = no_validation ? 0x76 : 0x6;110break;111112case E_FMAN_KG_GEN_EXTRACT_PPPoE:113code = no_validation ? 0x78 : 0x8;114break;115116case E_FMAN_KG_GEN_EXTRACT_MPLS_1:117code = no_validation ? 0x79 : 0x9;118break;119120case E_FMAN_KG_GEN_EXTRACT_MPLS_2:121code = no_validation ? FM_KG_SCH_GEN_HT_INVALID : 0x19;122break;123124case E_FMAN_KG_GEN_EXTRACT_MPLS_3:125code = no_validation ? FM_KG_SCH_GEN_HT_INVALID : 0x29;126break;127128case E_FMAN_KG_GEN_EXTRACT_MPLS_N:129code = no_validation ? 0x7a : 0xa;130break;131132case E_FMAN_KG_GEN_EXTRACT_IPv4_1:133code = no_validation ? 0x7b : 0xb;134break;135136case E_FMAN_KG_GEN_EXTRACT_IPv6_1:137code = no_validation ? 0x7b : 0x1b;138break;139140case E_FMAN_KG_GEN_EXTRACT_IPv4_2:141code = no_validation ? 0x7c : 0xc;142break;143144case E_FMAN_KG_GEN_EXTRACT_IPv6_2:145code = no_validation ? 0x7c : 0x1c;146break;147148case E_FMAN_KG_GEN_EXTRACT_MINENCAP:149code = no_validation ? 0x7c : 0x2c;150break;151152case E_FMAN_KG_GEN_EXTRACT_IP_PID:153code = no_validation ? 0x72 : 0x2;154break;155156case E_FMAN_KG_GEN_EXTRACT_GRE:157code = no_validation ? 0x7d : 0xd;158break;159160case E_FMAN_KG_GEN_EXTRACT_TCP:161code = no_validation ? 0x7e : 0xe;162break;163164case E_FMAN_KG_GEN_EXTRACT_UDP:165code = no_validation ? 0x7e : 0x1e;166break;167168case E_FMAN_KG_GEN_EXTRACT_SCTP:169code = no_validation ? 0x7e : 0x3e;170break;171172case E_FMAN_KG_GEN_EXTRACT_DCCP:173code = no_validation ? 0x7e : 0x4e;174break;175176case E_FMAN_KG_GEN_EXTRACT_IPSEC_AH:177code = no_validation ? 0x7e : 0x2e;178break;179180case E_FMAN_KG_GEN_EXTRACT_IPSEC_ESP:181code = no_validation ? 0x7e : 0x6e;182break;183184case E_FMAN_KG_GEN_EXTRACT_SHIM_1:185code = 0x70;186break;187188case E_FMAN_KG_GEN_EXTRACT_SHIM_2:189code = 0x71;190break;191192case E_FMAN_KG_GEN_EXTRACT_FROM_DFLT:193code = 0x10;194break;195196case E_FMAN_KG_GEN_EXTRACT_FROM_FRAME_START:197code = 0x40;198break;199200case E_FMAN_KG_GEN_EXTRACT_FROM_PARSE_RESULT:201code = 0x20;202break;203204case E_FMAN_KG_GEN_EXTRACT_FROM_END_OF_PARSE:205code = 0x7f;206break;207208case E_FMAN_KG_GEN_EXTRACT_FROM_FQID:209code = 0x20;210*offset += 0x20;211break;212213default:214code = FM_KG_SCH_GEN_HT_INVALID;215}216217return (uint8_t)code;218}219220static uint32_t build_ar_scheme(uint8_t scheme,221uint8_t hwport_id,222bool update_counter,223bool write)224{225uint32_t rw;226227rw = (uint32_t)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ);228229return (uint32_t)(FM_KG_KGAR_GO |230rw |231FM_KG_KGAR_SEL_SCHEME_ENTRY |232hwport_id |233((uint32_t)scheme << FM_KG_KGAR_NUM_SHIFT) |234(update_counter ? FM_KG_KGAR_SCM_WSEL_UPDATE_CNT : 0));235}236237static uint32_t build_ar_cls_plan(uint8_t grp,238uint8_t entries_mask,239uint8_t hwport_id,240bool write)241{242uint32_t rw;243244rw = (uint32_t)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ);245246return (uint32_t)(FM_KG_KGAR_GO |247rw |248FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY |249hwport_id |250((uint32_t)grp << FM_KG_KGAR_NUM_SHIFT) |251((uint32_t)entries_mask << FM_KG_KGAR_WSEL_SHIFT));252}253254int fman_kg_write_ar_wait(struct fman_kg_regs *regs, uint32_t fmkg_ar)255{256iowrite32be(fmkg_ar, ®s->fmkg_ar);257/* Wait for GO to be idle and read error */258while ((fmkg_ar = ioread32be(®s->fmkg_ar)) & FM_KG_KGAR_GO) ;259if (fmkg_ar & FM_PCD_KG_KGAR_ERR)260return -EINVAL;261return 0;262}263264void fman_kg_write_sp(struct fman_kg_regs *regs, uint32_t sp, bool add)265{266267struct fman_kg_pe_regs *kgpe_regs;268uint32_t tmp;269270kgpe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]);271tmp = ioread32be(&kgpe_regs->fmkg_pe_sp);272273if (add)274tmp |= sp;275else /* clear */276tmp &= ~sp;277278iowrite32be(tmp, &kgpe_regs->fmkg_pe_sp);279280}281282void fman_kg_write_cpp(struct fman_kg_regs *regs, uint32_t cpp)283{284struct fman_kg_pe_regs *kgpe_regs;285286kgpe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]);287288iowrite32be(cpp, &kgpe_regs->fmkg_pe_cpp);289}290291void fman_kg_get_event(struct fman_kg_regs *regs,292uint32_t *event,293uint32_t *scheme_idx)294{295uint32_t mask, force;296297*event = ioread32be(®s->fmkg_eer);298mask = ioread32be(®s->fmkg_eeer);299*scheme_idx = ioread32be(®s->fmkg_seer);300*scheme_idx &= ioread32be(®s->fmkg_seeer);301302*event &= mask;303304/* clear the forced events */305force = ioread32be(®s->fmkg_feer);306if (force & *event)307iowrite32be(force & ~*event ,®s->fmkg_feer);308309iowrite32be(*event, ®s->fmkg_eer);310iowrite32be(*scheme_idx, ®s->fmkg_seer);311}312313314void fman_kg_init(struct fman_kg_regs *regs,315uint32_t exceptions,316uint32_t dflt_nia)317{318uint32_t tmp;319int i;320321iowrite32be(FM_EX_KG_DOUBLE_ECC | FM_EX_KG_KEYSIZE_OVERFLOW,322®s->fmkg_eer);323324tmp = 0;325if (exceptions & FM_EX_KG_DOUBLE_ECC)326tmp |= FM_EX_KG_DOUBLE_ECC;327328if (exceptions & FM_EX_KG_KEYSIZE_OVERFLOW)329tmp |= FM_EX_KG_KEYSIZE_OVERFLOW;330331iowrite32be(tmp, ®s->fmkg_eeer);332iowrite32be(0, ®s->fmkg_fdor);333iowrite32be(0, ®s->fmkg_gdv0r);334iowrite32be(0, ®s->fmkg_gdv1r);335iowrite32be(dflt_nia, ®s->fmkg_gcr);336337/* Clear binding between ports to schemes and classification plans338* so that all ports are not bound to any scheme/classification plan */339for (i = 0; i < FMAN_MAX_NUM_OF_HW_PORTS; i++) {340clear_pe_all_scheme(regs, (uint8_t)i);341clear_pe_all_cls_plan(regs, (uint8_t)i);342}343}344345void fman_kg_enable_scheme_interrupts(struct fman_kg_regs *regs)346{347/* enable and enable all scheme interrupts */348iowrite32be(0xFFFFFFFF, ®s->fmkg_seer);349iowrite32be(0xFFFFFFFF, ®s->fmkg_seeer);350}351352void fman_kg_enable(struct fman_kg_regs *regs)353{354iowrite32be(ioread32be(®s->fmkg_gcr) | FM_KG_KGGCR_EN,355®s->fmkg_gcr);356}357358void fman_kg_disable(struct fman_kg_regs *regs)359{360iowrite32be(ioread32be(®s->fmkg_gcr) & ~FM_KG_KGGCR_EN,361®s->fmkg_gcr);362}363364void fman_kg_set_data_after_prs(struct fman_kg_regs *regs, uint8_t offset)365{366iowrite32be(offset, ®s->fmkg_fdor);367}368369void fman_kg_set_dflt_val(struct fman_kg_regs *regs,370uint8_t def_id,371uint32_t val)372{373if(def_id == 0)374iowrite32be(val, ®s->fmkg_gdv0r);375else376iowrite32be(val, ®s->fmkg_gdv1r);377}378379380void fman_kg_set_exception(struct fman_kg_regs *regs,381uint32_t exception,382bool enable)383{384uint32_t tmp;385386tmp = ioread32be(®s->fmkg_eeer);387388if (enable) {389tmp |= exception;390} else {391tmp &= ~exception;392}393394iowrite32be(tmp, ®s->fmkg_eeer);395}396397void fman_kg_get_exception(struct fman_kg_regs *regs,398uint32_t *events,399uint32_t *scheme_ids,400bool clear)401{402uint32_t mask;403404*events = ioread32be(®s->fmkg_eer);405mask = ioread32be(®s->fmkg_eeer);406*events &= mask;407408*scheme_ids = 0;409410if (*events & FM_EX_KG_KEYSIZE_OVERFLOW) {411*scheme_ids = ioread32be(®s->fmkg_seer);412mask = ioread32be(®s->fmkg_seeer);413*scheme_ids &= mask;414}415416if (clear) {417iowrite32be(*scheme_ids, ®s->fmkg_seer);418iowrite32be(*events, ®s->fmkg_eer);419}420}421422void fman_kg_get_capture(struct fman_kg_regs *regs,423struct fman_kg_ex_ecc_attr *ecc_attr,424bool clear)425{426uint32_t tmp;427428tmp = ioread32be(®s->fmkg_serc);429430if (tmp & KG_FMKG_SERC_CAP) {431/* Captured data is valid */432ecc_attr->valid = TRUE;433ecc_attr->double_ecc =434(bool)((tmp & KG_FMKG_SERC_CET) ? TRUE : FALSE);435ecc_attr->single_ecc_count =436(uint8_t)((tmp & KG_FMKG_SERC_CNT_MSK) >>437KG_FMKG_SERC_CNT_SHIFT);438ecc_attr->addr = (uint16_t)(tmp & KG_FMKG_SERC_ADDR_MSK);439440if (clear)441iowrite32be(KG_FMKG_SERC_CAP, ®s->fmkg_serc);442} else {443/* No ECC error is captured */444ecc_attr->valid = FALSE;445}446}447448int fman_kg_build_scheme(struct fman_kg_scheme_params *params,449struct fman_kg_scheme_regs *scheme_regs)450{451struct fman_kg_extract_params *extract_params;452struct fman_kg_gen_extract_params *gen_params;453uint32_t tmp_reg, i, select, mask, fqb;454uint8_t offset, shift, ht;455456/* Zero out all registers so no need to care about unused ones */457memset(scheme_regs, 0, sizeof(struct fman_kg_scheme_regs));458459/* Mode register */460tmp_reg = fm_kg_build_nia(params->next_engine,461params->next_engine_action);462if (tmp_reg == KG_NIA_INVALID) {463return -EINVAL;464}465466if (params->next_engine == E_FMAN_PCD_PLCR) {467tmp_reg |= FMAN_KG_SCH_MODE_NIA_PLCR;468}469else if (params->next_engine == E_FMAN_PCD_CC) {470tmp_reg |= (uint32_t)params->cc_params.base_offset <<471FMAN_KG_SCH_MODE_CCOBASE_SHIFT;472}473474tmp_reg |= FMAN_KG_SCH_MODE_EN;475scheme_regs->kgse_mode = tmp_reg;476477/* Match vector */478scheme_regs->kgse_mv = params->match_vector;479480extract_params = ¶ms->extract_params;481482/* Scheme default values registers */483scheme_regs->kgse_dv0 = extract_params->def_scheme_0;484scheme_regs->kgse_dv1 = extract_params->def_scheme_1;485486/* Extract Known Fields Command register */487scheme_regs->kgse_ekfc = extract_params->known_fields;488489/* Entry Extract Known Default Value register */490tmp_reg = 0;491tmp_reg |= extract_params->known_fields_def.mac_addr <<492FMAN_KG_SCH_DEF_MAC_ADDR_SHIFT;493tmp_reg |= extract_params->known_fields_def.vlan_tci <<494FMAN_KG_SCH_DEF_VLAN_TCI_SHIFT;495tmp_reg |= extract_params->known_fields_def.etype <<496FMAN_KG_SCH_DEF_ETYPE_SHIFT;497tmp_reg |= extract_params->known_fields_def.ppp_sid <<498FMAN_KG_SCH_DEF_PPP_SID_SHIFT;499tmp_reg |= extract_params->known_fields_def.ppp_pid <<500FMAN_KG_SCH_DEF_PPP_PID_SHIFT;501tmp_reg |= extract_params->known_fields_def.mpls <<502FMAN_KG_SCH_DEF_MPLS_SHIFT;503tmp_reg |= extract_params->known_fields_def.ip_addr <<504FMAN_KG_SCH_DEF_IP_ADDR_SHIFT;505tmp_reg |= extract_params->known_fields_def.ptype <<506FMAN_KG_SCH_DEF_PTYPE_SHIFT;507tmp_reg |= extract_params->known_fields_def.ip_tos_tc <<508FMAN_KG_SCH_DEF_IP_TOS_TC_SHIFT;509tmp_reg |= extract_params->known_fields_def.ipv6_fl <<510FMAN_KG_SCH_DEF_IPv6_FL_SHIFT;511tmp_reg |= extract_params->known_fields_def.ipsec_spi <<512FMAN_KG_SCH_DEF_IPSEC_SPI_SHIFT;513tmp_reg |= extract_params->known_fields_def.l4_port <<514FMAN_KG_SCH_DEF_L4_PORT_SHIFT;515tmp_reg |= extract_params->known_fields_def.tcp_flg <<516FMAN_KG_SCH_DEF_TCP_FLG_SHIFT;517518scheme_regs->kgse_ekdv = tmp_reg;519520/* Generic extract registers */521if (extract_params->gen_extract_num > FM_KG_NUM_OF_GENERIC_REGS) {522return -EINVAL;523}524525for (i = 0; i < extract_params->gen_extract_num; i++) {526gen_params = extract_params->gen_extract + i;527528tmp_reg = FMAN_KG_SCH_GEN_VALID;529tmp_reg |= (uint32_t)gen_params->def_val <<530FMAN_KG_SCH_GEN_DEF_SHIFT;531532if (gen_params->type == E_FMAN_KG_HASH_EXTRACT) {533if ((gen_params->extract > FMAN_KG_SCH_GEN_SIZE_MAX) ||534(gen_params->extract == 0)) {535return -EINVAL;536}537} else {538tmp_reg |= FMAN_KG_SCH_GEN_OR;539}540541tmp_reg |= (uint32_t)gen_params->extract <<542FMAN_KG_SCH_GEN_SIZE_SHIFT;543tmp_reg |= (uint32_t)gen_params->mask <<544FMAN_KG_SCH_GEN_MASK_SHIFT;545546offset = gen_params->offset;547ht = get_gen_ht_code(gen_params->src,548gen_params->no_validation,549&offset);550tmp_reg |= (uint32_t)ht << FMAN_KG_SCH_GEN_HT_SHIFT;551tmp_reg |= offset;552553scheme_regs->kgse_gec[i] = tmp_reg;554}555556/* Masks registers */557if (extract_params->masks_num > FM_KG_EXTRACT_MASKS_NUM) {558return -EINVAL;559}560561select = 0;562mask = 0;563fqb = 0;564for (i = 0; i < extract_params->masks_num; i++) {565/* MCSx fields */566KG_GET_MASK_SEL_SHIFT(shift, i);567if (extract_params->masks[i].is_known) {568/* Mask known field */569select |= extract_params->masks[i].field_or_gen_idx <<570shift;571} else {572/* Mask generic extract */573select |= (extract_params->masks[i].field_or_gen_idx +574FM_KG_MASK_SEL_GEN_BASE) << shift;575}576577/* MOx fields - spread between se_bmch and se_fqb registers */578KG_GET_MASK_OFFSET_SHIFT(shift, i);579if (i < 2) {580select |= (uint32_t)extract_params->masks[i].offset <<581shift;582} else {583fqb |= (uint32_t)extract_params->masks[i].offset <<584shift;585}586587/* BMx fields */588KG_GET_MASK_SHIFT(shift, i);589mask |= (uint32_t)extract_params->masks[i].mask << shift;590}591592/* Finish with rest of BMx fileds -593* don't mask bits for unused masks by setting594* corresponding BMx field = 0xFF */595for (i = extract_params->masks_num; i < FM_KG_EXTRACT_MASKS_NUM; i++) {596KG_GET_MASK_SHIFT(shift, i);597mask |= 0xFF << shift;598}599600scheme_regs->kgse_bmch = select;601scheme_regs->kgse_bmcl = mask;602603/* Finish with FQB register initialization.604* Check fqid is 24-bit value. */605if (params->base_fqid & ~0x00FFFFFF) {606return -EINVAL;607}608609fqb |= params->base_fqid;610scheme_regs->kgse_fqb = fqb;611612/* Hash Configuration register */613tmp_reg = 0;614if (params->hash_params.use_hash) {615/* Check hash mask is 24-bit value */616if (params->hash_params.mask & ~0x00FFFFFF) {617return -EINVAL;618}619620/* Hash function produces 64-bit value, 24 bits of that621* are used to generate fq_id and policer profile.622* Thus, maximal shift is 40 bits to allow 24 bits out of 64.623*/624if (params->hash_params.shift_r > FMAN_KG_SCH_HASH_HSHIFT_MAX) {625return -EINVAL;626}627628tmp_reg |= params->hash_params.mask;629tmp_reg |= (uint32_t)params->hash_params.shift_r <<630FMAN_KG_SCH_HASH_HSHIFT_SHIFT;631632if (params->hash_params.sym) {633tmp_reg |= FMAN_KG_SCH_HASH_SYM;634}635636}637638if (params->bypass_fqid_gen) {639tmp_reg |= FMAN_KG_SCH_HASH_NO_FQID_GEN;640}641642scheme_regs->kgse_hc = tmp_reg;643644/* Policer Profile register */645if (params->policer_params.bypass_pp_gen) {646tmp_reg = 0;647} else {648/* Lower 8 bits of 24-bits extracted from hash result649* are used for policer profile generation.650* That leaves maximum shift value = 23. */651if (params->policer_params.shift > FMAN_KG_SCH_PP_SHIFT_MAX) {652return -EINVAL;653}654655tmp_reg = params->policer_params.base;656tmp_reg |= ((uint32_t)params->policer_params.shift <<657FMAN_KG_SCH_PP_SH_SHIFT) &658FMAN_KG_SCH_PP_SH_MASK;659tmp_reg |= ((uint32_t)params->policer_params.shift <<660FMAN_KG_SCH_PP_SL_SHIFT) &661FMAN_KG_SCH_PP_SL_MASK;662tmp_reg |= (uint32_t)params->policer_params.mask <<663FMAN_KG_SCH_PP_MASK_SHIFT;664}665666scheme_regs->kgse_ppc = tmp_reg;667668/* Coarse Classification Bit Select register */669if (params->next_engine == E_FMAN_PCD_CC) {670scheme_regs->kgse_ccbs = params->cc_params.qlcv_bits_sel;671}672673/* Packets Counter register */674if (params->update_counter) {675scheme_regs->kgse_spc = params->counter_value;676}677678return 0;679}680681int fman_kg_write_scheme(struct fman_kg_regs *regs,682uint8_t scheme_id,683uint8_t hwport_id,684struct fman_kg_scheme_regs *scheme_regs,685bool update_counter)686{687struct fman_kg_scheme_regs *kgse_regs;688uint32_t tmp_reg;689int err, i;690691/* Write indirect scheme registers */692kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]);693694iowrite32be(scheme_regs->kgse_mode, &kgse_regs->kgse_mode);695iowrite32be(scheme_regs->kgse_ekfc, &kgse_regs->kgse_ekfc);696iowrite32be(scheme_regs->kgse_ekdv, &kgse_regs->kgse_ekdv);697iowrite32be(scheme_regs->kgse_bmch, &kgse_regs->kgse_bmch);698iowrite32be(scheme_regs->kgse_bmcl, &kgse_regs->kgse_bmcl);699iowrite32be(scheme_regs->kgse_fqb, &kgse_regs->kgse_fqb);700iowrite32be(scheme_regs->kgse_hc, &kgse_regs->kgse_hc);701iowrite32be(scheme_regs->kgse_ppc, &kgse_regs->kgse_ppc);702iowrite32be(scheme_regs->kgse_spc, &kgse_regs->kgse_spc);703iowrite32be(scheme_regs->kgse_dv0, &kgse_regs->kgse_dv0);704iowrite32be(scheme_regs->kgse_dv1, &kgse_regs->kgse_dv1);705iowrite32be(scheme_regs->kgse_ccbs, &kgse_regs->kgse_ccbs);706iowrite32be(scheme_regs->kgse_mv, &kgse_regs->kgse_mv);707708for (i = 0 ; i < FM_KG_NUM_OF_GENERIC_REGS ; i++)709iowrite32be(scheme_regs->kgse_gec[i], &kgse_regs->kgse_gec[i]);710711/* Write AR (Action register) */712tmp_reg = build_ar_scheme(scheme_id, hwport_id, update_counter, TRUE);713err = fman_kg_write_ar_wait(regs, tmp_reg);714return err;715}716717int fman_kg_delete_scheme(struct fman_kg_regs *regs,718uint8_t scheme_id,719uint8_t hwport_id)720{721struct fman_kg_scheme_regs *kgse_regs;722uint32_t tmp_reg;723int err, i;724725kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]);726727/* Clear all registers including enable bit in mode register */728for (i = 0; i < (sizeof(struct fman_kg_scheme_regs)) / 4; ++i) {729iowrite32be(0, ((uint32_t *)kgse_regs + i));730}731732/* Write AR (Action register) */733tmp_reg = build_ar_scheme(scheme_id, hwport_id, FALSE, TRUE);734err = fman_kg_write_ar_wait(regs, tmp_reg);735return err;736}737738int fman_kg_get_scheme_counter(struct fman_kg_regs *regs,739uint8_t scheme_id,740uint8_t hwport_id,741uint32_t *counter)742{743struct fman_kg_scheme_regs *kgse_regs;744uint32_t tmp_reg;745int err;746747kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]);748749tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, FALSE);750err = fman_kg_write_ar_wait(regs, tmp_reg);751752if (err != 0)753return err;754755*counter = ioread32be(&kgse_regs->kgse_spc);756757return 0;758}759760int fman_kg_set_scheme_counter(struct fman_kg_regs *regs,761uint8_t scheme_id,762uint8_t hwport_id,763uint32_t counter)764{765struct fman_kg_scheme_regs *kgse_regs;766uint32_t tmp_reg;767int err;768769kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]);770771tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, FALSE);772773err = fman_kg_write_ar_wait(regs, tmp_reg);774if (err != 0)775return err;776777/* Keygen indirect access memory contains all scheme_id registers778* by now. Change only counter value. */779iowrite32be(counter, &kgse_regs->kgse_spc);780781/* Write back scheme registers */782tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, TRUE);783err = fman_kg_write_ar_wait(regs, tmp_reg);784785return err;786}787788uint32_t fman_kg_get_schemes_total_counter(struct fman_kg_regs *regs)789{790return ioread32be(®s->fmkg_tpc);791}792793int fman_kg_build_cls_plan(struct fman_kg_cls_plan_params *params,794struct fman_kg_cp_regs *cls_plan_regs)795{796uint8_t entries_set, entry_bit;797int i;798799/* Zero out all group's register */800memset(cls_plan_regs, 0, sizeof(struct fman_kg_cp_regs));801802/* Go over all classification entries in params->entries_mask and803* configure the corresponding cpe register */804entries_set = params->entries_mask;805for (i = 0; entries_set; i++) {806entry_bit = (uint8_t)(0x80 >> i);807if ((entry_bit & entries_set) == 0)808continue;809entries_set ^= entry_bit;810cls_plan_regs->kgcpe[i] = params->mask_vector[i];811}812813return 0;814}815816int fman_kg_write_cls_plan(struct fman_kg_regs *regs,817uint8_t grp_id,818uint8_t entries_mask,819uint8_t hwport_id,820struct fman_kg_cp_regs *cls_plan_regs)821{822struct fman_kg_cp_regs *kgcpe_regs;823uint32_t tmp_reg;824int i, err;825826/* Check group index is valid and the group isn't empty */827if (grp_id >= FM_KG_CLS_PLAN_GRPS_NUM)828return -EINVAL;829830/* Write indirect classification plan registers */831kgcpe_regs = (struct fman_kg_cp_regs *)&(regs->fmkg_indirect[0]);832833for (i = 0; i < FM_KG_NUM_CLS_PLAN_ENTR; i++) {834iowrite32be(cls_plan_regs->kgcpe[i], &kgcpe_regs->kgcpe[i]);835}836837tmp_reg = build_ar_cls_plan(grp_id, entries_mask, hwport_id, TRUE);838err = fman_kg_write_ar_wait(regs, tmp_reg);839return err;840}841842int fman_kg_write_bind_schemes(struct fman_kg_regs *regs,843uint8_t hwport_id,844uint32_t schemes)845{846struct fman_kg_pe_regs *kg_pe_regs;847uint32_t tmp_reg;848int err;849850kg_pe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]);851852iowrite32be(schemes, &kg_pe_regs->fmkg_pe_sp);853854tmp_reg = build_ar_bind_scheme(hwport_id, TRUE);855err = fman_kg_write_ar_wait(regs, tmp_reg);856return err;857}858859int fman_kg_build_bind_cls_plans(uint8_t grp_base,860uint8_t grp_mask,861uint32_t *bind_cls_plans)862{863/* Check grp_base and grp_mask are 5-bits values */864if ((grp_base & ~0x0000001F) || (grp_mask & ~0x0000001F))865return -EINVAL;866867*bind_cls_plans = (uint32_t) ((grp_mask << FMAN_KG_PE_CPP_MASK_SHIFT) | grp_base);868return 0;869}870871872int fman_kg_write_bind_cls_plans(struct fman_kg_regs *regs,873uint8_t hwport_id,874uint32_t bind_cls_plans)875{876struct fman_kg_pe_regs *kg_pe_regs;877uint32_t tmp_reg;878int err;879880kg_pe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]);881882iowrite32be(bind_cls_plans, &kg_pe_regs->fmkg_pe_cpp);883884tmp_reg = build_ar_bind_cls_plan(hwport_id, TRUE);885err = fman_kg_write_ar_wait(regs, tmp_reg);886return err;887}888889890