1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright (C) 2020 Marvell International Ltd.
- *
- * Helper utilities for qlm.
- */
- #include <log.h>
- #include <time.h>
- #include <asm/global_data.h>
- #include <linux/delay.h>
- #include <mach/cvmx-regs.h>
- #include <mach/octeon-model.h>
- #include <mach/cvmx-fuse.h>
- #include <mach/octeon-feature.h>
- #include <mach/cvmx-qlm.h>
- #include <mach/octeon_qlm.h>
- #include <mach/cvmx-pcie.h>
- #include <mach/cvmx-helper.h>
- #include <mach/cvmx-helper-util.h>
- #include <mach/cvmx-bgxx-defs.h>
- #include <mach/cvmx-ciu-defs.h>
- #include <mach/cvmx-gmxx-defs.h>
- #include <mach/cvmx-gserx-defs.h>
- #include <mach/cvmx-mio-defs.h>
- #include <mach/cvmx-pciercx-defs.h>
- #include <mach/cvmx-pemx-defs.h>
- #include <mach/cvmx-pexp-defs.h>
- #include <mach/cvmx-rst-defs.h>
- #include <mach/cvmx-sata-defs.h>
- #include <mach/cvmx-sli-defs.h>
- #include <mach/cvmx-sriomaintx-defs.h>
- #include <mach/cvmx-sriox-defs.h>
- #include <mach/cvmx-helper.h>
- #include <mach/cvmx-helper-jtag.h>
- DECLARE_GLOBAL_DATA_PTR;
- /*
- * Their is a copy of this in bootloader qlm configuration, make sure
- * to update both the places till i figure out
- */
- #define R_25G_REFCLK100 0x0
- #define R_5G_REFCLK100 0x1
- #define R_8G_REFCLK100 0x2
- #define R_125G_REFCLK15625_KX 0x3
- #define R_3125G_REFCLK15625_XAUI 0x4
- #define R_103125G_REFCLK15625_KR 0x5
- #define R_125G_REFCLK15625_SGMII 0x6
- #define R_5G_REFCLK15625_QSGMII 0x7
- #define R_625G_REFCLK15625_RXAUI 0x8
- #define R_25G_REFCLK125 0x9
- #define R_5G_REFCLK125 0xa
- #define R_8G_REFCLK125 0xb
- static const int REF_100MHZ = 100000000;
- static const int REF_125MHZ = 125000000;
- static const int REF_156MHZ = 156250000;
- static qlm_jtag_uint32_t *__cvmx_qlm_jtag_xor_ref;
- /**
- * Return the number of QLMs supported by the chip
- *
- * Return: Number of QLMs
- */
- int cvmx_qlm_get_num(void)
- {
- if (OCTEON_IS_MODEL(OCTEON_CN68XX))
- return 5;
- else if (OCTEON_IS_MODEL(OCTEON_CN66XX))
- return 3;
- else if (OCTEON_IS_MODEL(OCTEON_CN63XX))
- return 3;
- else if (OCTEON_IS_MODEL(OCTEON_CN61XX))
- return 3;
- else if (OCTEON_IS_MODEL(OCTEON_CNF71XX))
- return 2;
- else if (OCTEON_IS_MODEL(OCTEON_CN78XX))
- return 8;
- else if (OCTEON_IS_MODEL(OCTEON_CN73XX))
- return 7;
- else if (OCTEON_IS_MODEL(OCTEON_CNF75XX))
- return 9;
- return 0;
- }
- /**
- * Return the qlm number based on the interface
- *
- * @param xiface interface to look up
- *
- * Return: the qlm number based on the xiface
- */
- int cvmx_qlm_interface(int xiface)
- {
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- if (OCTEON_IS_MODEL(OCTEON_CN61XX)) {
- return (xi.interface == 0) ? 2 : 0;
- } else if (OCTEON_IS_MODEL(OCTEON_CN63XX) || OCTEON_IS_MODEL(OCTEON_CN66XX)) {
- return 2 - xi.interface;
- } else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {
- if (xi.interface == 0)
- return 0;
- debug("Warning: %s: Invalid interface %d\n",
- __func__, xi.interface);
- } else if (octeon_has_feature(OCTEON_FEATURE_BGX)) {
- debug("Warning: not supported\n");
- return -1;
- }
- /* Must be cn68XX */
- switch (xi.interface) {
- case 1:
- return 0;
- default:
- return xi.interface;
- }
- return -1;
- }
- /**
- * Return the qlm number based for a port in the interface
- *
- * @param xiface interface to look up
- * @param index index in an interface
- *
- * Return: the qlm number based on the xiface
- */
- int cvmx_qlm_lmac(int xiface, int index)
- {
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- if (OCTEON_IS_MODEL(OCTEON_CN78XX)) {
- cvmx_bgxx_cmr_global_config_t gconfig;
- cvmx_gserx_phy_ctl_t phy_ctl;
- cvmx_gserx_cfg_t gserx_cfg;
- int qlm;
- if (xi.interface < 6) {
- if (xi.interface < 2) {
- gconfig.u64 =
- csr_rd_node(xi.node,
- CVMX_BGXX_CMR_GLOBAL_CONFIG(xi.interface));
- if (gconfig.s.pmux_sds_sel)
- qlm = xi.interface + 2; /* QLM 2 or 3 */
- else
- qlm = xi.interface; /* QLM 0 or 1 */
- } else {
- qlm = xi.interface + 2; /* QLM 4-7 */
- }
- /* make sure the QLM is powered up and out of reset */
- phy_ctl.u64 = csr_rd_node(xi.node, CVMX_GSERX_PHY_CTL(qlm));
- if (phy_ctl.s.phy_pd || phy_ctl.s.phy_reset)
- return -1;
- gserx_cfg.u64 = csr_rd_node(xi.node, CVMX_GSERX_CFG(qlm));
- if (gserx_cfg.s.bgx)
- return qlm;
- else
- return -1;
- } else if (xi.interface <= 7) { /* ILK */
- int qlm;
- for (qlm = 4; qlm < 8; qlm++) {
- /* Make sure the QLM is powered and out of reset */
- phy_ctl.u64 = csr_rd_node(xi.node, CVMX_GSERX_PHY_CTL(qlm));
- if (phy_ctl.s.phy_pd || phy_ctl.s.phy_reset)
- continue;
- /* Make sure the QLM is in ILK mode */
- gserx_cfg.u64 = csr_rd_node(xi.node, CVMX_GSERX_CFG(qlm));
- if (gserx_cfg.s.ila)
- return qlm;
- }
- }
- return -1;
- } else if (OCTEON_IS_MODEL(OCTEON_CN73XX)) {
- cvmx_gserx_phy_ctl_t phy_ctl;
- cvmx_gserx_cfg_t gserx_cfg;
- int qlm;
- /* (interface)0->QLM2, 1->QLM3, 2->DLM5/3->DLM6 */
- if (xi.interface < 2) {
- qlm = xi.interface + 2; /* (0,1)->ret(2,3) */
- phy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(qlm));
- if (phy_ctl.s.phy_pd || phy_ctl.s.phy_reset)
- return -1;
- gserx_cfg.u64 = csr_rd(CVMX_GSERX_CFG(qlm));
- if (gserx_cfg.s.bgx)
- return qlm;
- else
- return -1;
- } else if (xi.interface == 2) {
- cvmx_gserx_cfg_t g1, g2;
- g1.u64 = csr_rd(CVMX_GSERX_CFG(5));
- g2.u64 = csr_rd(CVMX_GSERX_CFG(6));
- /* Check if both QLM5 & QLM6 are BGX2 */
- if (g2.s.bgx) {
- if (g1.s.bgx) {
- cvmx_gserx_phy_ctl_t phy_ctl1;
- phy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(5));
- phy_ctl1.u64 = csr_rd(CVMX_GSERX_PHY_CTL(6));
- if ((phy_ctl.s.phy_pd || phy_ctl.s.phy_reset) &&
- (phy_ctl1.s.phy_pd || phy_ctl1.s.phy_reset))
- return -1;
- if (index >= 2)
- return 6;
- return 5;
- } else { /* QLM6 is BGX2 */
- phy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(6));
- if (phy_ctl.s.phy_pd || phy_ctl.s.phy_reset)
- return -1;
- return 6;
- }
- } else if (g1.s.bgx) {
- phy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(5));
- if (phy_ctl.s.phy_pd || phy_ctl.s.phy_reset)
- return -1;
- return 5;
- }
- }
- return -1;
- } else if (OCTEON_IS_MODEL(OCTEON_CNF75XX)) {
- cvmx_gserx_phy_ctl_t phy_ctl;
- cvmx_gserx_cfg_t gserx_cfg;
- int qlm;
- if (xi.interface == 0) {
- cvmx_gserx_cfg_t g1, g2;
- g1.u64 = csr_rd(CVMX_GSERX_CFG(4));
- g2.u64 = csr_rd(CVMX_GSERX_CFG(5));
- /* Check if both QLM4 & QLM5 are BGX0 */
- if (g2.s.bgx) {
- if (g1.s.bgx) {
- cvmx_gserx_phy_ctl_t phy_ctl1;
- phy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(4));
- phy_ctl1.u64 = csr_rd(CVMX_GSERX_PHY_CTL(5));
- if ((phy_ctl.s.phy_pd || phy_ctl.s.phy_reset) &&
- (phy_ctl1.s.phy_pd || phy_ctl1.s.phy_reset))
- return -1;
- if (index >= 2)
- return 5;
- return 4;
- }
- /* QLM5 is BGX0 */
- phy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(5));
- if (phy_ctl.s.phy_pd || phy_ctl.s.phy_reset)
- return -1;
- return 5;
- } else if (g1.s.bgx) {
- phy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(4));
- if (phy_ctl.s.phy_pd || phy_ctl.s.phy_reset)
- return -1;
- return 4;
- }
- } else if (xi.interface < 2) {
- qlm = (xi.interface == 1) ? 2 : 3;
- gserx_cfg.u64 = csr_rd(CVMX_GSERX_CFG(qlm));
- if (gserx_cfg.s.srio)
- return qlm;
- }
- return -1;
- }
- return -1;
- }
- /**
- * Return if only DLM5/DLM6/DLM5+DLM6 is used by BGX
- *
- * @param BGX BGX to search for.
- *
- * Return: muxes used 0 = DLM5+DLM6, 1 = DLM5, 2 = DLM6.
- */
- int cvmx_qlm_mux_interface(int bgx)
- {
- int mux = 0;
- cvmx_gserx_cfg_t gser1, gser2;
- int qlm1, qlm2;
- if (OCTEON_IS_MODEL(OCTEON_CN73XX) && bgx != 2)
- return -1;
- else if (OCTEON_IS_MODEL(OCTEON_CNF75XX) && bgx != 0)
- return -1;
- if (OCTEON_IS_MODEL(OCTEON_CN73XX)) {
- qlm1 = 5;
- qlm2 = 6;
- } else if (OCTEON_IS_MODEL(OCTEON_CNF75XX)) {
- qlm1 = 4;
- qlm2 = 5;
- } else {
- return -1;
- }
- gser1.u64 = csr_rd(CVMX_GSERX_CFG(qlm1));
- gser2.u64 = csr_rd(CVMX_GSERX_CFG(qlm2));
- if (gser1.s.bgx && gser2.s.bgx)
- mux = 0;
- else if (gser1.s.bgx)
- mux = 1; // BGX2 is using DLM5 only
- else if (gser2.s.bgx)
- mux = 2; // BGX2 is using DLM6 only
- return mux;
- }
- /**
- * Return number of lanes for a given qlm
- *
- * @param qlm QLM to examine
- *
- * Return: Number of lanes
- */
- int cvmx_qlm_get_lanes(int qlm)
- {
- if (OCTEON_IS_MODEL(OCTEON_CN61XX) && qlm == 1)
- return 2;
- else if (OCTEON_IS_MODEL(OCTEON_CNF71XX))
- return 2;
- else if (OCTEON_IS_MODEL(OCTEON_CN73XX))
- return (qlm < 4) ? 4 /*QLM0,1,2,3*/ : 2 /*DLM4,5,6*/;
- else if (OCTEON_IS_MODEL(OCTEON_CNF75XX))
- return (qlm == 2 || qlm == 3) ? 4 /*QLM2,3*/ : 2 /*DLM0,1,4,5*/;
- return 4;
- }
- /**
- * Get the QLM JTAG fields based on Octeon model on the supported chips.
- *
- * Return: qlm_jtag_field_t structure
- */
- const __cvmx_qlm_jtag_field_t *cvmx_qlm_jtag_get_field(void)
- {
- /* Figure out which JTAG chain description we're using */
- if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
- return __cvmx_qlm_jtag_field_cn68xx;
- } else if (OCTEON_IS_MODEL(OCTEON_CN66XX) || OCTEON_IS_MODEL(OCTEON_CN61XX) ||
- OCTEON_IS_MODEL(OCTEON_CNF71XX)) {
- return __cvmx_qlm_jtag_field_cn66xx;
- } else if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {
- return __cvmx_qlm_jtag_field_cn63xx;
- }
- return NULL;
- }
- /**
- * Get the QLM JTAG length by going through qlm_jtag_field for each
- * Octeon model that is supported
- *
- * Return: return the length.
- */
- int cvmx_qlm_jtag_get_length(void)
- {
- const __cvmx_qlm_jtag_field_t *qlm_ptr = cvmx_qlm_jtag_get_field();
- int length = 0;
- /* Figure out how many bits are in the JTAG chain */
- while (qlm_ptr && qlm_ptr->name) {
- if (qlm_ptr->stop_bit > length)
- length = qlm_ptr->stop_bit + 1;
- qlm_ptr++;
- }
- return length;
- }
- /**
- * Initialize the QLM layer
- */
- void cvmx_qlm_init(void)
- {
- if (OCTEON_IS_OCTEON3())
- return;
- /* ToDo: No support for non-Octeon 3 yet */
- printf("Please add support for unsupported Octeon SoC\n");
- }
- /**
- * Lookup the bit information for a JTAG field name
- *
- * @param name Name to lookup
- *
- * Return: Field info, or NULL on failure
- */
- static const __cvmx_qlm_jtag_field_t *__cvmx_qlm_lookup_field(const char *name)
- {
- const __cvmx_qlm_jtag_field_t *ptr = cvmx_qlm_jtag_get_field();
- while (ptr->name) {
- if (strcmp(name, ptr->name) == 0)
- return ptr;
- ptr++;
- }
- debug("%s: Illegal field name %s\n", __func__, name);
- return NULL;
- }
- /**
- * Get a field in a QLM JTAG chain
- *
- * @param qlm QLM to get
- * @param lane Lane in QLM to get
- * @param name String name of field
- *
- * Return: JTAG field value
- */
- uint64_t cvmx_qlm_jtag_get(int qlm, int lane, const char *name)
- {
- const __cvmx_qlm_jtag_field_t *field = __cvmx_qlm_lookup_field(name);
- int qlm_jtag_length = cvmx_qlm_jtag_get_length();
- int num_lanes = cvmx_qlm_get_lanes(qlm);
- if (!field)
- return 0;
- /* Capture the current settings */
- cvmx_helper_qlm_jtag_capture(qlm);
- /*
- * Shift past lanes we don't care about. CN6XXX/7XXX shifts lane 0 first,
- * CN3XXX/5XXX shifts lane 3 first
- */
- /* Shift to the start of the field */
- cvmx_helper_qlm_jtag_shift_zeros(qlm,
- qlm_jtag_length * (num_lanes - 1 - lane));
- cvmx_helper_qlm_jtag_shift_zeros(qlm, field->start_bit);
- /* Shift out the value and return it */
- return cvmx_helper_qlm_jtag_shift(qlm, field->stop_bit - field->start_bit + 1, 0);
- }
- /**
- * Set a field in a QLM JTAG chain
- *
- * @param qlm QLM to set
- * @param lane Lane in QLM to set, or -1 for all lanes
- * @param name String name of field
- * @param value Value of the field
- */
- void cvmx_qlm_jtag_set(int qlm, int lane, const char *name, uint64_t value)
- {
- int i, l;
- u32 shift_values[CVMX_QLM_JTAG_UINT32];
- int num_lanes = cvmx_qlm_get_lanes(qlm);
- const __cvmx_qlm_jtag_field_t *field = __cvmx_qlm_lookup_field(name);
- int qlm_jtag_length = cvmx_qlm_jtag_get_length();
- int total_length = qlm_jtag_length * num_lanes;
- int bits = 0;
- if (!field)
- return;
- /* Get the current state */
- cvmx_helper_qlm_jtag_capture(qlm);
- for (i = 0; i < CVMX_QLM_JTAG_UINT32; i++)
- shift_values[i] = cvmx_helper_qlm_jtag_shift(qlm, 32, 0);
- /* Put new data in our local array */
- for (l = 0; l < num_lanes; l++) {
- u64 new_value = value;
- int bits;
- int adj_lanes;
- if (l != lane && lane != -1)
- continue;
- adj_lanes = (num_lanes - 1 - l) * qlm_jtag_length;
- for (bits = field->start_bit + adj_lanes; bits <= field->stop_bit + adj_lanes;
- bits++) {
- if (new_value & 1)
- shift_values[bits / 32] |= 1 << (bits & 31);
- else
- shift_values[bits / 32] &= ~(1 << (bits & 31));
- new_value >>= 1;
- }
- }
- /* Shift out data and xor with reference */
- while (bits < total_length) {
- u32 shift = shift_values[bits / 32] ^ __cvmx_qlm_jtag_xor_ref[qlm][bits / 32];
- int width = total_length - bits;
- if (width > 32)
- width = 32;
- cvmx_helper_qlm_jtag_shift(qlm, width, shift);
- bits += 32;
- }
- /* Update the new data */
- cvmx_helper_qlm_jtag_update(qlm);
- /*
- * Always give the QLM 1ms to settle after every update. This may not
- * always be needed, but some of the options make significant
- * electrical changes
- */
- udelay(1000);
- }
- /**
- * Errata G-16094: QLM Gen2 Equalizer Default Setting Change.
- * CN68XX pass 1.x and CN66XX pass 1.x QLM tweak. This function tweaks the
- * JTAG setting for a QLMs to run better at 5 and 6.25Ghz.
- */
- void __cvmx_qlm_speed_tweak(void)
- {
- cvmx_mio_qlmx_cfg_t qlm_cfg;
- int num_qlms = cvmx_qlm_get_num();
- int qlm;
- /* Workaround for Errata (G-16467) */
- if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS2_X)) {
- for (qlm = 0; qlm < num_qlms; qlm++) {
- int ir50dac;
- /*
- * This workaround only applies to QLMs running at
- * 6.25Ghz
- */
- if (cvmx_qlm_get_gbaud_mhz(qlm) == 6250) {
- #ifdef CVMX_QLM_DUMP_STATE
- debug("%s:%d: QLM%d: Applying workaround for Errata G-16467\n",
- __func__, __LINE__, qlm);
- cvmx_qlm_display_registers(qlm);
- debug("\n");
- #endif
- cvmx_qlm_jtag_set(qlm, -1, "cfg_cdr_trunc", 0);
- /* Hold the QLM in reset */
- cvmx_qlm_jtag_set(qlm, -1, "cfg_rst_n_set", 0);
- cvmx_qlm_jtag_set(qlm, -1, "cfg_rst_n_clr", 1);
- /* Forcfe TX to be idle */
- cvmx_qlm_jtag_set(qlm, -1, "cfg_tx_idle_clr", 0);
- cvmx_qlm_jtag_set(qlm, -1, "cfg_tx_idle_set", 1);
- if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS2_0)) {
- ir50dac = cvmx_qlm_jtag_get(qlm, 0, "ir50dac");
- while (++ir50dac <= 31)
- cvmx_qlm_jtag_set(qlm, -1, "ir50dac", ir50dac);
- }
- cvmx_qlm_jtag_set(qlm, -1, "div4_byp", 0);
- cvmx_qlm_jtag_set(qlm, -1, "clkf_byp", 16);
- cvmx_qlm_jtag_set(qlm, -1, "serdes_pll_byp", 1);
- cvmx_qlm_jtag_set(qlm, -1, "spdsel_byp", 1);
- #ifdef CVMX_QLM_DUMP_STATE
- debug("%s:%d: QLM%d: Done applying workaround for Errata G-16467\n",
- __func__, __LINE__, qlm);
- cvmx_qlm_display_registers(qlm);
- debug("\n\n");
- #endif
- /*
- * The QLM will be taken out of reset later
- * when ILK/XAUI are initialized.
- */
- }
- }
- } else if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X) ||
- OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X)) {
- /* Loop through the QLMs */
- for (qlm = 0; qlm < num_qlms; qlm++) {
- /* Read the QLM speed */
- qlm_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(qlm));
- /* If the QLM is at 6.25Ghz or 5Ghz then program JTAG */
- if (qlm_cfg.s.qlm_spd == 5 || qlm_cfg.s.qlm_spd == 12 ||
- qlm_cfg.s.qlm_spd == 0 || qlm_cfg.s.qlm_spd == 6 ||
- qlm_cfg.s.qlm_spd == 11) {
- cvmx_qlm_jtag_set(qlm, -1, "rx_cap_gen2", 0x1);
- cvmx_qlm_jtag_set(qlm, -1, "rx_eq_gen2", 0x8);
- }
- }
- }
- }
- /**
- * Errata G-16174: QLM Gen2 PCIe IDLE DAC change.
- * CN68XX pass 1.x, CN66XX pass 1.x and CN63XX pass 1.0-2.2 QLM tweak.
- * This function tweaks the JTAG setting for a QLMs for PCIe to run better.
- */
- void __cvmx_qlm_pcie_idle_dac_tweak(void)
- {
- int num_qlms = 0;
- int qlm;
- if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X))
- num_qlms = 5;
- else if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X))
- num_qlms = 3;
- else if (OCTEON_IS_MODEL(OCTEON_CN63XX))
- num_qlms = 3;
- else
- return;
- /* Loop through the QLMs */
- for (qlm = 0; qlm < num_qlms; qlm++)
- cvmx_qlm_jtag_set(qlm, -1, "idle_dac", 0x2);
- }
- void __cvmx_qlm_pcie_cfg_rxd_set_tweak(int qlm, int lane)
- {
- if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
- cvmx_qlm_jtag_set(qlm, lane, "cfg_rxd_set", 0x1);
- }
- /**
- * Get the speed (Gbaud) of the QLM in Mhz for a given node.
- *
- * @param node node of the QLM
- * @param qlm QLM to examine
- *
- * Return: Speed in Mhz
- */
- int cvmx_qlm_get_gbaud_mhz_node(int node, int qlm)
- {
- cvmx_gserx_lane_mode_t lane_mode;
- cvmx_gserx_cfg_t cfg;
- if (!octeon_has_feature(OCTEON_FEATURE_MULTINODE))
- return 0;
- if (qlm >= 8)
- return -1; /* FIXME for OCI */
- /* Check if QLM is configured */
- cfg.u64 = csr_rd_node(node, CVMX_GSERX_CFG(qlm));
- if (cfg.u64 == 0)
- return -1;
- if (cfg.s.pcie) {
- int pem = 0;
- cvmx_pemx_cfg_t pemx_cfg;
- switch (qlm) {
- case 0: /* Either PEM0 x4 of PEM0 x8 */
- pem = 0;
- break;
- case 1: /* Either PEM0 x4 of PEM1 x4 */
- pemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(0));
- if (pemx_cfg.cn78xx.lanes8)
- pem = 0;
- else
- pem = 1;
- break;
- case 2: /* Either PEM2 x4 of PEM2 x8 */
- pem = 2;
- break;
- case 3: /* Either PEM2 x8 of PEM3 x4 or x8 */
- /* Can be last 4 lanes of PEM2 */
- pemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(2));
- if (pemx_cfg.cn78xx.lanes8) {
- pem = 2;
- } else {
- pemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(3));
- if (pemx_cfg.cn78xx.lanes8)
- pem = 3;
- else
- pem = 2;
- }
- break;
- case 4: /* Either PEM3 x8 of PEM3 x4 */
- pem = 3;
- break;
- default:
- debug("QLM%d: Should be in PCIe mode\n", qlm);
- break;
- }
- pemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(pem));
- switch (pemx_cfg.s.md) {
- case 0: /* Gen1 */
- return 2500;
- case 1: /* Gen2 */
- return 5000;
- case 2: /* Gen3 */
- return 8000;
- default:
- return 0;
- }
- } else {
- lane_mode.u64 = csr_rd_node(node, CVMX_GSERX_LANE_MODE(qlm));
- switch (lane_mode.s.lmode) {
- case R_25G_REFCLK100:
- return 2500;
- case R_5G_REFCLK100:
- return 5000;
- case R_8G_REFCLK100:
- return 8000;
- case R_125G_REFCLK15625_KX:
- return 1250;
- case R_3125G_REFCLK15625_XAUI:
- return 3125;
- case R_103125G_REFCLK15625_KR:
- return 10312;
- case R_125G_REFCLK15625_SGMII:
- return 1250;
- case R_5G_REFCLK15625_QSGMII:
- return 5000;
- case R_625G_REFCLK15625_RXAUI:
- return 6250;
- case R_25G_REFCLK125:
- return 2500;
- case R_5G_REFCLK125:
- return 5000;
- case R_8G_REFCLK125:
- return 8000;
- default:
- return 0;
- }
- }
- }
- /**
- * Get the speed (Gbaud) of the QLM in Mhz.
- *
- * @param qlm QLM to examine
- *
- * Return: Speed in Mhz
- */
- int cvmx_qlm_get_gbaud_mhz(int qlm)
- {
- if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {
- if (qlm == 2) {
- cvmx_gmxx_inf_mode_t inf_mode;
- inf_mode.u64 = csr_rd(CVMX_GMXX_INF_MODE(0));
- switch (inf_mode.s.speed) {
- case 0:
- return 5000; /* 5 Gbaud */
- case 1:
- return 2500; /* 2.5 Gbaud */
- case 2:
- return 2500; /* 2.5 Gbaud */
- case 3:
- return 1250; /* 1.25 Gbaud */
- case 4:
- return 1250; /* 1.25 Gbaud */
- case 5:
- return 6250; /* 6.25 Gbaud */
- case 6:
- return 5000; /* 5 Gbaud */
- case 7:
- return 2500; /* 2.5 Gbaud */
- case 8:
- return 3125; /* 3.125 Gbaud */
- case 9:
- return 2500; /* 2.5 Gbaud */
- case 10:
- return 1250; /* 1.25 Gbaud */
- case 11:
- return 5000; /* 5 Gbaud */
- case 12:
- return 6250; /* 6.25 Gbaud */
- case 13:
- return 3750; /* 3.75 Gbaud */
- case 14:
- return 3125; /* 3.125 Gbaud */
- default:
- return 0; /* Disabled */
- }
- } else {
- cvmx_sriox_status_reg_t status_reg;
- status_reg.u64 = csr_rd(CVMX_SRIOX_STATUS_REG(qlm));
- if (status_reg.s.srio) {
- cvmx_sriomaintx_port_0_ctl2_t sriomaintx_port_0_ctl2;
- sriomaintx_port_0_ctl2.u32 =
- csr_rd(CVMX_SRIOMAINTX_PORT_0_CTL2(qlm));
- switch (sriomaintx_port_0_ctl2.s.sel_baud) {
- case 1:
- return 1250; /* 1.25 Gbaud */
- case 2:
- return 2500; /* 2.5 Gbaud */
- case 3:
- return 3125; /* 3.125 Gbaud */
- case 4:
- return 5000; /* 5 Gbaud */
- case 5:
- return 6250; /* 6.250 Gbaud */
- default:
- return 0; /* Disabled */
- }
- } else {
- cvmx_pciercx_cfg032_t pciercx_cfg032;
- pciercx_cfg032.u32 = csr_rd(CVMX_PCIERCX_CFG032(qlm));
- switch (pciercx_cfg032.s.ls) {
- case 1:
- return 2500;
- case 2:
- return 5000;
- case 4:
- return 8000;
- default: {
- cvmx_mio_rst_boot_t mio_rst_boot;
- mio_rst_boot.u64 = csr_rd(CVMX_MIO_RST_BOOT);
- if (qlm == 0 && mio_rst_boot.s.qlm0_spd == 0xf)
- return 0;
- if (qlm == 1 && mio_rst_boot.s.qlm1_spd == 0xf)
- return 0;
- /* Best guess I can make */
- return 5000;
- }
- }
- }
- }
- } else if (OCTEON_IS_OCTEON2()) {
- cvmx_mio_qlmx_cfg_t qlm_cfg;
- qlm_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(qlm));
- switch (qlm_cfg.s.qlm_spd) {
- case 0:
- return 5000; /* 5 Gbaud */
- case 1:
- return 2500; /* 2.5 Gbaud */
- case 2:
- return 2500; /* 2.5 Gbaud */
- case 3:
- return 1250; /* 1.25 Gbaud */
- case 4:
- return 1250; /* 1.25 Gbaud */
- case 5:
- return 6250; /* 6.25 Gbaud */
- case 6:
- return 5000; /* 5 Gbaud */
- case 7:
- return 2500; /* 2.5 Gbaud */
- case 8:
- return 3125; /* 3.125 Gbaud */
- case 9:
- return 2500; /* 2.5 Gbaud */
- case 10:
- return 1250; /* 1.25 Gbaud */
- case 11:
- return 5000; /* 5 Gbaud */
- case 12:
- return 6250; /* 6.25 Gbaud */
- case 13:
- return 3750; /* 3.75 Gbaud */
- case 14:
- return 3125; /* 3.125 Gbaud */
- default:
- return 0; /* Disabled */
- }
- } else if (OCTEON_IS_MODEL(OCTEON_CN70XX)) {
- cvmx_gserx_dlmx_mpll_multiplier_t mpll_multiplier;
- u64 meas_refclock;
- u64 freq;
- /* Measure the reference clock */
- meas_refclock = cvmx_qlm_measure_clock(qlm);
- /* Multiply to get the final frequency */
- mpll_multiplier.u64 = csr_rd(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0));
- freq = meas_refclock * mpll_multiplier.s.mpll_multiplier;
- freq = (freq + 500000) / 1000000;
- return freq;
- } else if (OCTEON_IS_MODEL(OCTEON_CN78XX)) {
- return cvmx_qlm_get_gbaud_mhz_node(cvmx_get_node_num(), qlm);
- } else if (OCTEON_IS_MODEL(OCTEON_CN73XX) || OCTEON_IS_MODEL(OCTEON_CNF75XX)) {
- cvmx_gserx_lane_mode_t lane_mode;
- lane_mode.u64 = csr_rd(CVMX_GSERX_LANE_MODE(qlm));
- switch (lane_mode.s.lmode) {
- case R_25G_REFCLK100:
- return 2500;
- case R_5G_REFCLK100:
- return 5000;
- case R_8G_REFCLK100:
- return 8000;
- case R_125G_REFCLK15625_KX:
- return 1250;
- case R_3125G_REFCLK15625_XAUI:
- return 3125;
- case R_103125G_REFCLK15625_KR:
- return 10312;
- case R_125G_REFCLK15625_SGMII:
- return 1250;
- case R_5G_REFCLK15625_QSGMII:
- return 5000;
- case R_625G_REFCLK15625_RXAUI:
- return 6250;
- case R_25G_REFCLK125:
- return 2500;
- case R_5G_REFCLK125:
- return 5000;
- case R_8G_REFCLK125:
- return 8000;
- default:
- return 0;
- }
- }
- return 0;
- }
- static enum cvmx_qlm_mode __cvmx_qlm_get_mode_cn70xx(int qlm)
- {
- switch (qlm) {
- case 0: /* DLM0/DLM1 - SGMII/QSGMII/RXAUI */
- {
- union cvmx_gmxx_inf_mode inf_mode0, inf_mode1;
- inf_mode0.u64 = csr_rd(CVMX_GMXX_INF_MODE(0));
- inf_mode1.u64 = csr_rd(CVMX_GMXX_INF_MODE(1));
- /* SGMII0 SGMII1 */
- switch (inf_mode0.s.mode) {
- case CVMX_GMX_INF_MODE_SGMII:
- switch (inf_mode1.s.mode) {
- case CVMX_GMX_INF_MODE_SGMII:
- return CVMX_QLM_MODE_SGMII_SGMII;
- case CVMX_GMX_INF_MODE_QSGMII:
- return CVMX_QLM_MODE_SGMII_QSGMII;
- default:
- return CVMX_QLM_MODE_SGMII_DISABLED;
- }
- case CVMX_GMX_INF_MODE_QSGMII:
- switch (inf_mode1.s.mode) {
- case CVMX_GMX_INF_MODE_SGMII:
- return CVMX_QLM_MODE_QSGMII_SGMII;
- case CVMX_GMX_INF_MODE_QSGMII:
- return CVMX_QLM_MODE_QSGMII_QSGMII;
- default:
- return CVMX_QLM_MODE_QSGMII_DISABLED;
- }
- case CVMX_GMX_INF_MODE_RXAUI:
- return CVMX_QLM_MODE_RXAUI_1X2;
- default:
- switch (inf_mode1.s.mode) {
- case CVMX_GMX_INF_MODE_SGMII:
- return CVMX_QLM_MODE_DISABLED_SGMII;
- case CVMX_GMX_INF_MODE_QSGMII:
- return CVMX_QLM_MODE_DISABLED_QSGMII;
- default:
- return CVMX_QLM_MODE_DISABLED;
- }
- }
- }
- case 1: /* Sata / pem0 */
- {
- union cvmx_gserx_sata_cfg sata_cfg;
- union cvmx_pemx_cfg pem0_cfg;
- sata_cfg.u64 = csr_rd(CVMX_GSERX_SATA_CFG(0));
- pem0_cfg.u64 = csr_rd(CVMX_PEMX_CFG(0));
- switch (pem0_cfg.cn70xx.md) {
- case CVMX_PEM_MD_GEN2_2LANE:
- case CVMX_PEM_MD_GEN1_2LANE:
- return CVMX_QLM_MODE_PCIE_1X2;
- case CVMX_PEM_MD_GEN2_1LANE:
- case CVMX_PEM_MD_GEN1_1LANE:
- if (sata_cfg.s.sata_en)
- /* Both PEM0 and PEM1 */
- return CVMX_QLM_MODE_PCIE_2X1;
- /* Only PEM0 */
- return CVMX_QLM_MODE_PCIE_1X1;
- case CVMX_PEM_MD_GEN2_4LANE:
- case CVMX_PEM_MD_GEN1_4LANE:
- return CVMX_QLM_MODE_PCIE;
- default:
- return CVMX_QLM_MODE_DISABLED;
- }
- }
- case 2: {
- union cvmx_gserx_sata_cfg sata_cfg;
- union cvmx_pemx_cfg pem0_cfg, pem1_cfg, pem2_cfg;
- sata_cfg.u64 = csr_rd(CVMX_GSERX_SATA_CFG(0));
- pem0_cfg.u64 = csr_rd(CVMX_PEMX_CFG(0));
- pem1_cfg.u64 = csr_rd(CVMX_PEMX_CFG(1));
- pem2_cfg.u64 = csr_rd(CVMX_PEMX_CFG(2));
- if (sata_cfg.s.sata_en)
- return CVMX_QLM_MODE_SATA_2X1;
- if (pem0_cfg.cn70xx.md == CVMX_PEM_MD_GEN2_4LANE ||
- pem0_cfg.cn70xx.md == CVMX_PEM_MD_GEN1_4LANE)
- return CVMX_QLM_MODE_PCIE;
- if (pem1_cfg.cn70xx.md == CVMX_PEM_MD_GEN2_2LANE ||
- pem1_cfg.cn70xx.md == CVMX_PEM_MD_GEN1_2LANE) {
- return CVMX_QLM_MODE_PCIE_1X2;
- }
- if (pem1_cfg.cn70xx.md == CVMX_PEM_MD_GEN2_1LANE ||
- pem1_cfg.cn70xx.md == CVMX_PEM_MD_GEN1_1LANE) {
- if (pem2_cfg.cn70xx.md == CVMX_PEM_MD_GEN2_1LANE ||
- pem2_cfg.cn70xx.md == CVMX_PEM_MD_GEN1_1LANE) {
- return CVMX_QLM_MODE_PCIE_2X1;
- } else {
- return CVMX_QLM_MODE_PCIE_1X1;
- }
- }
- if (pem2_cfg.cn70xx.md == CVMX_PEM_MD_GEN2_1LANE ||
- pem2_cfg.cn70xx.md == CVMX_PEM_MD_GEN1_1LANE)
- return CVMX_QLM_MODE_PCIE_2X1;
- return CVMX_QLM_MODE_DISABLED;
- }
- default:
- return CVMX_QLM_MODE_DISABLED;
- }
- return CVMX_QLM_MODE_DISABLED;
- }
- /*
- * Get the DLM mode for the interface based on the interface type.
- *
- * @param interface_type 0 - SGMII/QSGMII/RXAUI interface
- * 1 - PCIe
- * 2 - SATA
- * @param interface interface to use
- * Return: the qlm mode the interface is
- */
- enum cvmx_qlm_mode cvmx_qlm_get_dlm_mode(int interface_type, int interface)
- {
- switch (interface_type) {
- case 0: /* SGMII/QSGMII/RXAUI */
- {
- enum cvmx_qlm_mode qlm_mode = __cvmx_qlm_get_mode_cn70xx(0);
- switch (interface) {
- case 0:
- switch (qlm_mode) {
- case CVMX_QLM_MODE_SGMII_SGMII:
- case CVMX_QLM_MODE_SGMII_DISABLED:
- case CVMX_QLM_MODE_SGMII_QSGMII:
- return CVMX_QLM_MODE_SGMII;
- case CVMX_QLM_MODE_QSGMII_QSGMII:
- case CVMX_QLM_MODE_QSGMII_DISABLED:
- case CVMX_QLM_MODE_QSGMII_SGMII:
- return CVMX_QLM_MODE_QSGMII;
- case CVMX_QLM_MODE_RXAUI_1X2:
- return CVMX_QLM_MODE_RXAUI;
- default:
- return CVMX_QLM_MODE_DISABLED;
- }
- case 1:
- switch (qlm_mode) {
- case CVMX_QLM_MODE_SGMII_SGMII:
- case CVMX_QLM_MODE_DISABLED_SGMII:
- case CVMX_QLM_MODE_QSGMII_SGMII:
- return CVMX_QLM_MODE_SGMII;
- case CVMX_QLM_MODE_QSGMII_QSGMII:
- case CVMX_QLM_MODE_DISABLED_QSGMII:
- case CVMX_QLM_MODE_SGMII_QSGMII:
- return CVMX_QLM_MODE_QSGMII;
- default:
- return CVMX_QLM_MODE_DISABLED;
- }
- default:
- return qlm_mode;
- }
- }
- case 1: /* PCIe */
- {
- enum cvmx_qlm_mode qlm_mode1 = __cvmx_qlm_get_mode_cn70xx(1);
- enum cvmx_qlm_mode qlm_mode2 = __cvmx_qlm_get_mode_cn70xx(2);
- switch (interface) {
- case 0: /* PCIe0 can be DLM1 with 1, 2 or 4 lanes */
- return qlm_mode1;
- case 1:
- /*
- * PCIe1 can be in DLM1 1 lane(1), DLM2 1 lane(0)
- * or 2 lanes(0-1)
- */
- if (qlm_mode1 == CVMX_QLM_MODE_PCIE_2X1)
- return CVMX_QLM_MODE_PCIE_2X1;
- else if (qlm_mode2 == CVMX_QLM_MODE_PCIE_1X2 ||
- qlm_mode2 == CVMX_QLM_MODE_PCIE_2X1)
- return qlm_mode2;
- else
- return CVMX_QLM_MODE_DISABLED;
- case 2: /* PCIe2 can be DLM2 1 lanes(1) */
- if (qlm_mode2 == CVMX_QLM_MODE_PCIE_2X1)
- return qlm_mode2;
- else
- return CVMX_QLM_MODE_DISABLED;
- default:
- return CVMX_QLM_MODE_DISABLED;
- }
- }
- case 2: /* SATA */
- {
- enum cvmx_qlm_mode qlm_mode = __cvmx_qlm_get_mode_cn70xx(2);
- if (qlm_mode == CVMX_QLM_MODE_SATA_2X1)
- return CVMX_QLM_MODE_SATA_2X1;
- else
- return CVMX_QLM_MODE_DISABLED;
- }
- default:
- return CVMX_QLM_MODE_DISABLED;
- }
- }
- static enum cvmx_qlm_mode __cvmx_qlm_get_mode_cn6xxx(int qlm)
- {
- cvmx_mio_qlmx_cfg_t qlmx_cfg;
- if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
- qlmx_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(qlm));
- /* QLM is disabled when QLM SPD is 15. */
- if (qlmx_cfg.s.qlm_spd == 15)
- return CVMX_QLM_MODE_DISABLED;
- switch (qlmx_cfg.s.qlm_cfg) {
- case 0: /* PCIE */
- return CVMX_QLM_MODE_PCIE;
- case 1: /* ILK */
- return CVMX_QLM_MODE_ILK;
- case 2: /* SGMII */
- return CVMX_QLM_MODE_SGMII;
- case 3: /* XAUI */
- return CVMX_QLM_MODE_XAUI;
- case 7: /* RXAUI */
- return CVMX_QLM_MODE_RXAUI;
- default:
- return CVMX_QLM_MODE_DISABLED;
- }
- } else if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
- qlmx_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(qlm));
- /* QLM is disabled when QLM SPD is 15. */
- if (qlmx_cfg.s.qlm_spd == 15)
- return CVMX_QLM_MODE_DISABLED;
- switch (qlmx_cfg.s.qlm_cfg) {
- case 0x9: /* SGMII */
- return CVMX_QLM_MODE_SGMII;
- case 0xb: /* XAUI */
- return CVMX_QLM_MODE_XAUI;
- case 0x0: /* PCIE gen2 */
- case 0x8: /* PCIE gen2 (alias) */
- case 0x2: /* PCIE gen1 */
- case 0xa: /* PCIE gen1 (alias) */
- return CVMX_QLM_MODE_PCIE;
- case 0x1: /* SRIO 1x4 short */
- case 0x3: /* SRIO 1x4 long */
- return CVMX_QLM_MODE_SRIO_1X4;
- case 0x4: /* SRIO 2x2 short */
- case 0x6: /* SRIO 2x2 long */
- return CVMX_QLM_MODE_SRIO_2X2;
- case 0x5: /* SRIO 4x1 short */
- case 0x7: /* SRIO 4x1 long */
- if (!OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0))
- return CVMX_QLM_MODE_SRIO_4X1;
- fallthrough;
- default:
- return CVMX_QLM_MODE_DISABLED;
- }
- } else if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {
- cvmx_sriox_status_reg_t status_reg;
- /* For now skip qlm2 */
- if (qlm == 2) {
- cvmx_gmxx_inf_mode_t inf_mode;
- inf_mode.u64 = csr_rd(CVMX_GMXX_INF_MODE(0));
- if (inf_mode.s.speed == 15)
- return CVMX_QLM_MODE_DISABLED;
- else if (inf_mode.s.mode == 0)
- return CVMX_QLM_MODE_SGMII;
- else
- return CVMX_QLM_MODE_XAUI;
- }
- status_reg.u64 = csr_rd(CVMX_SRIOX_STATUS_REG(qlm));
- if (status_reg.s.srio)
- return CVMX_QLM_MODE_SRIO_1X4;
- else
- return CVMX_QLM_MODE_PCIE;
- } else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) {
- qlmx_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(qlm));
- /* QLM is disabled when QLM SPD is 15. */
- if (qlmx_cfg.s.qlm_spd == 15)
- return CVMX_QLM_MODE_DISABLED;
- switch (qlm) {
- case 0:
- switch (qlmx_cfg.s.qlm_cfg) {
- case 0: /* PCIe 1x4 gen2 / gen1 */
- return CVMX_QLM_MODE_PCIE;
- case 2: /* SGMII */
- return CVMX_QLM_MODE_SGMII;
- case 3: /* XAUI */
- return CVMX_QLM_MODE_XAUI;
- default:
- return CVMX_QLM_MODE_DISABLED;
- }
- break;
- case 1:
- switch (qlmx_cfg.s.qlm_cfg) {
- case 0: /* PCIe 1x2 gen2 / gen1 */
- return CVMX_QLM_MODE_PCIE_1X2;
- case 1: /* PCIe 2x1 gen2 / gen1 */
- return CVMX_QLM_MODE_PCIE_2X1;
- default:
- return CVMX_QLM_MODE_DISABLED;
- }
- break;
- case 2:
- switch (qlmx_cfg.s.qlm_cfg) {
- case 2: /* SGMII */
- return CVMX_QLM_MODE_SGMII;
- case 3: /* XAUI */
- return CVMX_QLM_MODE_XAUI;
- default:
- return CVMX_QLM_MODE_DISABLED;
- }
- break;
- }
- } else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {
- qlmx_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(qlm));
- /* QLM is disabled when QLM SPD is 15. */
- if (qlmx_cfg.s.qlm_spd == 15)
- return CVMX_QLM_MODE_DISABLED;
- switch (qlm) {
- case 0:
- if (qlmx_cfg.s.qlm_cfg == 2) /* SGMII */
- return CVMX_QLM_MODE_SGMII;
- break;
- case 1:
- switch (qlmx_cfg.s.qlm_cfg) {
- case 0: /* PCIe 1x2 gen2 / gen1 */
- return CVMX_QLM_MODE_PCIE_1X2;
- case 1: /* PCIe 2x1 gen2 / gen1 */
- return CVMX_QLM_MODE_PCIE_2X1;
- default:
- return CVMX_QLM_MODE_DISABLED;
- }
- break;
- }
- }
- return CVMX_QLM_MODE_DISABLED;
- }
- /**
- * @INTERNAL
- * Decrement the MPLL Multiplier for the DLM as per Errata G-20669
- *
- * @param qlm DLM to configure
- * @param baud_mhz Speed of the DLM configured at
- * @param old_multiplier MPLL_MULTIPLIER value to decrement
- */
- void __cvmx_qlm_set_mult(int qlm, int baud_mhz, int old_multiplier)
- {
- cvmx_gserx_dlmx_mpll_multiplier_t mpll_multiplier;
- cvmx_gserx_dlmx_ref_clkdiv2_t clkdiv;
- u64 meas_refclock, mult;
- if (!OCTEON_IS_MODEL(OCTEON_CN70XX))
- return;
- if (qlm == -1)
- return;
- meas_refclock = cvmx_qlm_measure_clock(qlm);
- if (meas_refclock == 0) {
- printf("DLM%d: Reference clock not running\n", qlm);
- return;
- }
- /*
- * The baud rate multiplier needs to be adjusted on the CN70XX if
- * the reference clock is > 100MHz.
- */
- if (qlm == 0) {
- clkdiv.u64 = csr_rd(CVMX_GSERX_DLMX_REF_CLKDIV2(qlm, 0));
- if (clkdiv.s.ref_clkdiv2)
- baud_mhz *= 2;
- }
- mult = (uint64_t)baud_mhz * 1000000 + (meas_refclock / 2);
- mult /= meas_refclock;
- /*
- * 6. Decrease MPLL_MULTIPLIER by one continually until it reaches
- * the desired long-term setting, ensuring that each MPLL_MULTIPLIER
- * value is constant for at least 1 msec before changing to the next
- * value. The desired long-term setting is as indicated in HRM tables
- * 21-1, 21-2, and 21-3. This is not required with the HRM
- * sequence.
- */
- do {
- mpll_multiplier.u64 = csr_rd(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0));
- mpll_multiplier.s.mpll_multiplier = --old_multiplier;
- csr_wr(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0), mpll_multiplier.u64);
- /* Wait for 1 ms */
- udelay(1000);
- } while (old_multiplier > (int)mult);
- }
- enum cvmx_qlm_mode cvmx_qlm_get_mode_cn78xx(int node, int qlm)
- {
- cvmx_gserx_cfg_t gserx_cfg;
- int qlm_mode[2][9] = { { -1, -1, -1, -1, -1, -1, -1, -1 },
- { -1, -1, -1, -1, -1, -1, -1, -1 } };
- if (qlm >= 8)
- return CVMX_QLM_MODE_OCI;
- if (qlm_mode[node][qlm] != -1)
- return qlm_mode[node][qlm];
- gserx_cfg.u64 = csr_rd_node(node, CVMX_GSERX_CFG(qlm));
- if (gserx_cfg.s.pcie) {
- switch (qlm) {
- case 0: /* Either PEM0 x4 or PEM0 x8 */
- case 1: /* Either PEM0 x8 or PEM1 x4 */
- {
- cvmx_pemx_cfg_t pemx_cfg;
- pemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(0));
- if (pemx_cfg.cn78xx.lanes8) {
- /* PEM0 x8 */
- qlm_mode[node][qlm] = CVMX_QLM_MODE_PCIE_1X8;
- } else {
- /* PEM0 x4 */
- qlm_mode[node][qlm] = CVMX_QLM_MODE_PCIE;
- }
- break;
- }
- case 2: /* Either PEM2 x4 or PEM2 x8 */
- {
- cvmx_pemx_cfg_t pemx_cfg;
- pemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(2));
- if (pemx_cfg.cn78xx.lanes8) {
- /* PEM2 x8 */
- qlm_mode[node][qlm] = CVMX_QLM_MODE_PCIE_1X8;
- } else {
- /* PEM2 x4 */
- qlm_mode[node][qlm] = CVMX_QLM_MODE_PCIE;
- }
- break;
- }
- case 3: /* Either PEM2 x8 or PEM3 x4 or PEM3 x8 */
- {
- cvmx_pemx_cfg_t pemx_cfg;
- pemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(2));
- if (pemx_cfg.cn78xx.lanes8) {
- /* PEM2 x8 */
- qlm_mode[node][qlm] = CVMX_QLM_MODE_PCIE_1X8;
- }
- /* Can be first 4 lanes of PEM3 */
- pemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(3));
- if (pemx_cfg.cn78xx.lanes8) {
- /* PEM3 x8 */
- qlm_mode[node][qlm] = CVMX_QLM_MODE_PCIE_1X8;
- } else {
- /* PEM2 x4 */
- qlm_mode[node][qlm] = CVMX_QLM_MODE_PCIE;
- }
- break;
- }
- case 4: /* Either PEM3 x8 or PEM3 x4 */
- {
- cvmx_pemx_cfg_t pemx_cfg;
- pemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(3));
- if (pemx_cfg.cn78xx.lanes8) {
- /* PEM3 x8 */
- qlm_mode[node][qlm] = CVMX_QLM_MODE_PCIE_1X8;
- } else {
- /* PEM3 x4 */
- qlm_mode[node][qlm] = CVMX_QLM_MODE_PCIE;
- }
- break;
- }
- default:
- qlm_mode[node][qlm] = CVMX_QLM_MODE_DISABLED;
- break;
- }
- } else if (gserx_cfg.s.ila) {
- qlm_mode[node][qlm] = CVMX_QLM_MODE_ILK;
- } else if (gserx_cfg.s.bgx) {
- cvmx_bgxx_cmrx_config_t cmr_config;
- cvmx_bgxx_spux_br_pmd_control_t pmd_control;
- int bgx = (qlm < 2) ? qlm : qlm - 2;
- cmr_config.u64 = csr_rd_node(node, CVMX_BGXX_CMRX_CONFIG(0, bgx));
- pmd_control.u64 = csr_rd_node(node, CVMX_BGXX_SPUX_BR_PMD_CONTROL(0, bgx));
- switch (cmr_config.s.lmac_type) {
- case 0:
- qlm_mode[node][qlm] = CVMX_QLM_MODE_SGMII;
- break;
- case 1:
- qlm_mode[node][qlm] = CVMX_QLM_MODE_XAUI;
- break;
- case 2:
- qlm_mode[node][qlm] = CVMX_QLM_MODE_RXAUI;
- break;
- case 3:
- /*
- * Use training to determine if we're in 10GBASE-KR
- * or XFI
- */
- if (pmd_control.s.train_en)
- qlm_mode[node][qlm] = CVMX_QLM_MODE_10G_KR;
- else
- qlm_mode[node][qlm] = CVMX_QLM_MODE_XFI;
- break;
- case 4:
- /*
- * Use training to determine if we're in 40GBASE-KR
- * or XLAUI
- */
- if (pmd_control.s.train_en)
- qlm_mode[node][qlm] = CVMX_QLM_MODE_40G_KR4;
- else
- qlm_mode[node][qlm] = CVMX_QLM_MODE_XLAUI;
- break;
- default:
- qlm_mode[node][qlm] = CVMX_QLM_MODE_DISABLED;
- break;
- }
- } else {
- qlm_mode[node][qlm] = CVMX_QLM_MODE_DISABLED;
- }
- return qlm_mode[node][qlm];
- }
- enum cvmx_qlm_mode __cvmx_qlm_get_mode_cn73xx(int qlm)
- {
- cvmx_gserx_cfg_t gserx_cfg;
- int qlm_mode[7] = { -1, -1, -1, -1, -1, -1, -1 };
- if (qlm_mode[qlm] != -1)
- return qlm_mode[qlm];
- if (qlm > 6) {
- debug("Invalid QLM(%d) passed\n", qlm);
- return -1;
- }
- gserx_cfg.u64 = csr_rd(CVMX_GSERX_CFG(qlm));
- if (gserx_cfg.s.pcie) {
- cvmx_pemx_cfg_t pemx_cfg;
- switch (qlm) {
- case 0: /* Either PEM0 x4 or PEM0 x8 */
- case 1: /* Either PEM0 x8 or PEM1 x4 */
- {
- pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(0));
- if (pemx_cfg.cn78xx.lanes8) {
- /* PEM0 x8 */
- qlm_mode[qlm] = CVMX_QLM_MODE_PCIE_1X8;
- } else {
- /* PEM0/PEM1 x4 */
- qlm_mode[qlm] = CVMX_QLM_MODE_PCIE;
- }
- break;
- }
- case 2: /* Either PEM2 x4 or PEM2 x8 */
- {
- pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(2));
- if (pemx_cfg.cn78xx.lanes8) {
- /* PEM2 x8 */
- qlm_mode[qlm] = CVMX_QLM_MODE_PCIE_1X8;
- } else {
- /* PEM2 x4 */
- qlm_mode[qlm] = CVMX_QLM_MODE_PCIE;
- }
- break;
- }
- case 5:
- case 6: /* PEM3 x2 */
- qlm_mode[qlm] = CVMX_QLM_MODE_PCIE_1X2; /* PEM3 x2 */
- break;
- case 3: /* Either PEM2 x8 or PEM3 x4 */
- {
- pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(2));
- if (pemx_cfg.cn78xx.lanes8) {
- /* PEM2 x8 */
- qlm_mode[qlm] = CVMX_QLM_MODE_PCIE_1X8;
- } else {
- /* PEM3 x4 */
- qlm_mode[qlm] = CVMX_QLM_MODE_PCIE;
- }
- break;
- }
- default:
- qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
- break;
- }
- } else if (gserx_cfg.s.bgx) {
- cvmx_bgxx_cmrx_config_t cmr_config;
- cvmx_bgxx_cmr_rx_lmacs_t bgx_cmr_rx_lmacs;
- cvmx_bgxx_spux_br_pmd_control_t pmd_control;
- int bgx = 0;
- int start = 0, end = 4, index;
- int lane_mask = 0, train_mask = 0;
- int mux = 0; // 0:BGX2 (DLM5/DLM6), 1:BGX2(DLM5), 2:BGX2(DLM6)
- if (qlm < 4) {
- bgx = qlm - 2;
- } else if (qlm == 5 || qlm == 6) {
- bgx = 2;
- mux = cvmx_qlm_mux_interface(bgx);
- if (mux == 0) {
- start = 0;
- end = 4;
- } else if (mux == 1) {
- start = 0;
- end = 2;
- } else if (mux == 2) {
- start = 2;
- end = 4;
- } else {
- qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
- return qlm_mode[qlm];
- }
- }
- for (index = start; index < end; index++) {
- cmr_config.u64 = csr_rd(CVMX_BGXX_CMRX_CONFIG(index, bgx));
- pmd_control.u64 = csr_rd(CVMX_BGXX_SPUX_BR_PMD_CONTROL(index, bgx));
- lane_mask |= (cmr_config.s.lmac_type << (index * 4));
- train_mask |= (pmd_control.s.train_en << (index * 4));
- }
- /* Need to include DLM5 lmacs when only DLM6 DLM is used */
- if (mux == 2)
- bgx_cmr_rx_lmacs.u64 = csr_rd(CVMX_BGXX_CMR_RX_LMACS(2));
- switch (lane_mask) {
- case 0:
- if (mux == 1) {
- qlm_mode[qlm] = CVMX_QLM_MODE_SGMII_2X1;
- } else if (mux == 2) {
- qlm_mode[qlm] = CVMX_QLM_MODE_SGMII_2X1;
- bgx_cmr_rx_lmacs.s.lmacs = 4;
- }
- qlm_mode[qlm] = CVMX_QLM_MODE_SGMII;
- break;
- case 0x1:
- qlm_mode[qlm] = CVMX_QLM_MODE_XAUI;
- break;
- case 0x2:
- if (mux == 1) {
- // NONE+RXAUI
- qlm_mode[qlm] = CVMX_QLM_MODE_RXAUI_1X2;
- } else if (mux == 0) {
- // RXAUI+SGMII
- qlm_mode[qlm] = CVMX_QLM_MODE_MIXED;
- } else {
- qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
- }
- break;
- case 0x202:
- if (mux == 2) {
- // RXAUI+RXAUI
- qlm_mode[qlm] = CVMX_QLM_MODE_RXAUI_1X2;
- bgx_cmr_rx_lmacs.s.lmacs = 4;
- } else if (mux == 1) {
- // RXAUI+RXAUI
- qlm_mode[qlm] = CVMX_QLM_MODE_RXAUI_1X2;
- } else if (mux == 0) {
- qlm_mode[qlm] = CVMX_QLM_MODE_RXAUI;
- } else {
- qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
- }
- break;
- case 0x22:
- qlm_mode[qlm] = CVMX_QLM_MODE_RXAUI;
- break;
- case 0x3333:
- /*
- * Use training to determine if we're in 10GBASE-KR
- * or XFI
- */
- if (train_mask)
- qlm_mode[qlm] = CVMX_QLM_MODE_10G_KR;
- else
- qlm_mode[qlm] = CVMX_QLM_MODE_XFI;
- break;
- case 0x4:
- /*
- * Use training to determine if we're in 40GBASE-KR
- * or XLAUI
- */
- if (train_mask)
- qlm_mode[qlm] = CVMX_QLM_MODE_40G_KR4;
- else
- qlm_mode[qlm] = CVMX_QLM_MODE_XLAUI;
- break;
- case 0x0005:
- qlm_mode[qlm] = CVMX_QLM_MODE_RGMII_SGMII;
- break;
- case 0x3335:
- if (train_mask)
- qlm_mode[qlm] = CVMX_QLM_MODE_RGMII_10G_KR;
- else
- qlm_mode[qlm] = CVMX_QLM_MODE_RGMII_XFI;
- break;
- case 0x45:
- if (train_mask)
- qlm_mode[qlm] = CVMX_QLM_MODE_RGMII_40G_KR4;
- else
- qlm_mode[qlm] = CVMX_QLM_MODE_RGMII_XLAUI;
- break;
- case 0x225:
- qlm_mode[qlm] = CVMX_QLM_MODE_RGMII_RXAUI;
- break;
- case 0x15:
- qlm_mode[qlm] = CVMX_QLM_MODE_RGMII_XAUI;
- break;
- case 0x200:
- if (mux == 2) {
- qlm_mode[qlm] = CVMX_QLM_MODE_RXAUI_1X2;
- bgx_cmr_rx_lmacs.s.lmacs = 4;
- } else
- case 0x205:
- case 0x233:
- case 0x3302:
- case 0x3305:
- if (mux == 0)
- qlm_mode[qlm] = CVMX_QLM_MODE_MIXED;
- else
- qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
- break;
- case 0x3300:
- if (mux == 0) {
- qlm_mode[qlm] = CVMX_QLM_MODE_MIXED;
- } else if (mux == 2) {
- if (train_mask)
- qlm_mode[qlm] = CVMX_QLM_MODE_10G_KR_1X2;
- else
- qlm_mode[qlm] = CVMX_QLM_MODE_XFI_1X2;
- bgx_cmr_rx_lmacs.s.lmacs = 4;
- } else {
- qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
- }
- break;
- case 0x33:
- if (mux == 1 || mux == 2) {
- if (train_mask)
- qlm_mode[qlm] = CVMX_QLM_MODE_10G_KR_1X2;
- else
- qlm_mode[qlm] = CVMX_QLM_MODE_XFI_1X2;
- if (mux == 2)
- bgx_cmr_rx_lmacs.s.lmacs = 4;
- } else {
- qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
- }
- break;
- case 0x0035:
- if (mux == 0)
- qlm_mode[qlm] = CVMX_QLM_MODE_MIXED;
- else if (train_mask)
- qlm_mode[qlm] = CVMX_QLM_MODE_RGMII_10G_KR_1X1;
- else
- qlm_mode[qlm] = CVMX_QLM_MODE_RGMII_XFI_1X1;
- break;
- case 0x235:
- if (mux == 0)
- qlm_mode[qlm] = CVMX_QLM_MODE_MIXED;
- else
- qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
- break;
- default:
- qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
- break;
- }
- if (mux == 2) {
- csr_wr(CVMX_BGXX_CMR_RX_LMACS(2), bgx_cmr_rx_lmacs.u64);
- csr_wr(CVMX_BGXX_CMR_TX_LMACS(2), bgx_cmr_rx_lmacs.u64);
- }
- } else if (gserx_cfg.s.sata) {
- qlm_mode[qlm] = CVMX_QLM_MODE_SATA_2X1;
- } else {
- qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
- }
- return qlm_mode[qlm];
- }
- enum cvmx_qlm_mode __cvmx_qlm_get_mode_cnf75xx(int qlm)
- {
- cvmx_gserx_cfg_t gserx_cfg;
- int qlm_mode[9] = { -1, -1, -1, -1, -1, -1, -1 };
- if (qlm_mode[qlm] != -1)
- return qlm_mode[qlm];
- if (qlm > 9) {
- debug("Invalid QLM(%d) passed\n", qlm);
- return -1;
- }
- if ((qlm == 2 || qlm == 3) && (OCTEON_IS_MODEL(OCTEON_CNF75XX))) {
- cvmx_sriox_status_reg_t status_reg;
- int port = (qlm == 2) ? 0 : 1;
- status_reg.u64 = csr_rd(CVMX_SRIOX_STATUS_REG(port));
- /* FIXME add different width */
- if (status_reg.s.srio)
- qlm_mode[qlm] = CVMX_QLM_MODE_SRIO_1X4;
- else
- qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
- return qlm_mode[qlm];
- }
- gserx_cfg.u64 = csr_rd(CVMX_GSERX_CFG(qlm));
- if (gserx_cfg.s.pcie) {
- switch (qlm) {
- case 0: /* Either PEM0 x2 or PEM0 x4 */
- case 1: /* Either PEM1 x2 or PEM0 x4 */
- {
- /* FIXME later */
- qlm_mode[qlm] = CVMX_QLM_MODE_PCIE;
- break;
- }
- default:
- qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
- break;
- }
- } else if (gserx_cfg.s.bgx) {
- cvmx_bgxx_cmrx_config_t cmr_config;
- cvmx_bgxx_spux_br_pmd_control_t pmd_control;
- int bgx = 0;
- int start = 0, end = 4, index;
- int lane_mask = 0, train_mask = 0;
- int mux = 0; // 0:BGX0 (DLM4/DLM5), 1:BGX0(DLM4), 2:BGX0(DLM5)
- cvmx_gserx_cfg_t gser1, gser2;
- gser1.u64 = csr_rd(CVMX_GSERX_CFG(4));
- gser2.u64 = csr_rd(CVMX_GSERX_CFG(5));
- if (gser1.s.bgx && gser2.s.bgx) {
- start = 0;
- end = 4;
- } else if (gser1.s.bgx) {
- start = 0;
- end = 2;
- mux = 1;
- } else if (gser2.s.bgx) {
- start = 2;
- end = 4;
- mux = 2;
- } else {
- qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
- return qlm_mode[qlm];
- }
- for (index = start; index < end; index++) {
- cmr_config.u64 = csr_rd(CVMX_BGXX_CMRX_CONFIG(index, bgx));
- pmd_control.u64 = csr_rd(CVMX_BGXX_SPUX_BR_PMD_CONTROL(index, bgx));
- lane_mask |= (cmr_config.s.lmac_type << (index * 4));
- train_mask |= (pmd_control.s.train_en << (index * 4));
- }
- switch (lane_mask) {
- case 0:
- if (mux == 1 || mux == 2)
- qlm_mode[qlm] = CVMX_QLM_MODE_SGMII_2X1;
- else
- qlm_mode[qlm] = CVMX_QLM_MODE_SGMII;
- break;
- case 0x3300:
- if (mux == 0)
- qlm_mode[qlm] = CVMX_QLM_MODE_MIXED;
- else if (mux == 2)
- if (train_mask)
- qlm_mode[qlm] = CVMX_QLM_MODE_10G_KR_1X2;
- else
- qlm_mode[qlm] = CVMX_QLM_MODE_XFI_1X2;
- else
- qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
- break;
- default:
- qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
- break;
- }
- } else {
- qlm_mode[qlm] = CVMX_QLM_MODE_DISABLED;
- }
- return qlm_mode[qlm];
- }
- /*
- * Read QLM and return mode.
- */
- enum cvmx_qlm_mode cvmx_qlm_get_mode(int qlm)
- {
- if (OCTEON_IS_OCTEON2())
- return __cvmx_qlm_get_mode_cn6xxx(qlm);
- else if (OCTEON_IS_MODEL(OCTEON_CN70XX))
- return __cvmx_qlm_get_mode_cn70xx(qlm);
- else if (OCTEON_IS_MODEL(OCTEON_CN78XX))
- return cvmx_qlm_get_mode_cn78xx(cvmx_get_node_num(), qlm);
- else if (OCTEON_IS_MODEL(OCTEON_CN73XX))
- return __cvmx_qlm_get_mode_cn73xx(qlm);
- else if (OCTEON_IS_MODEL(OCTEON_CNF75XX))
- return __cvmx_qlm_get_mode_cnf75xx(qlm);
- return CVMX_QLM_MODE_DISABLED;
- }
- int cvmx_qlm_measure_clock_cn7xxx(int node, int qlm)
- {
- cvmx_gserx_cfg_t cfg;
- cvmx_gserx_refclk_sel_t refclk_sel;
- cvmx_gserx_lane_mode_t lane_mode;
- if (OCTEON_IS_MODEL(OCTEON_CN73XX)) {
- if (node != 0 || qlm >= 7)
- return -1;
- } else if (OCTEON_IS_MODEL(OCTEON_CN78XX)) {
- if (qlm >= 8 || node > 1)
- return -1; /* FIXME for OCI */
- } else {
- debug("%s: Unsupported OCTEON model\n", __func__);
- return -1;
- }
- cfg.u64 = csr_rd_node(node, CVMX_GSERX_CFG(qlm));
- if (cfg.s.pcie) {
- refclk_sel.u64 = csr_rd_node(node, CVMX_GSERX_REFCLK_SEL(qlm));
- if (refclk_sel.s.pcie_refclk125)
- return REF_125MHZ; /* Ref 125 Mhz */
- else
- return REF_100MHZ; /* Ref 100Mhz */
- }
- lane_mode.u64 = csr_rd_node(node, CVMX_GSERX_LANE_MODE(qlm));
- switch (lane_mode.s.lmode) {
- case R_25G_REFCLK100:
- return REF_100MHZ;
- case R_5G_REFCLK100:
- return REF_100MHZ;
- case R_8G_REFCLK100:
- return REF_100MHZ;
- case R_125G_REFCLK15625_KX:
- return REF_156MHZ;
- case R_3125G_REFCLK15625_XAUI:
- return REF_156MHZ;
- case R_103125G_REFCLK15625_KR:
- return REF_156MHZ;
- case R_125G_REFCLK15625_SGMII:
- return REF_156MHZ;
- case R_5G_REFCLK15625_QSGMII:
- return REF_156MHZ;
- case R_625G_REFCLK15625_RXAUI:
- return REF_156MHZ;
- case R_25G_REFCLK125:
- return REF_125MHZ;
- case R_5G_REFCLK125:
- return REF_125MHZ;
- case R_8G_REFCLK125:
- return REF_125MHZ;
- default:
- return 0;
- }
- }
- /**
- * Measure the reference clock of a QLM on a multi-node setup
- *
- * @param node node to measure
- * @param qlm QLM to measure
- *
- * Return: Clock rate in Hz
- */
- int cvmx_qlm_measure_clock_node(int node, int qlm)
- {
- if (octeon_has_feature(OCTEON_FEATURE_MULTINODE))
- return cvmx_qlm_measure_clock_cn7xxx(node, qlm);
- else
- return cvmx_qlm_measure_clock(qlm);
- }
- /**
- * Measure the reference clock of a QLM
- *
- * @param qlm QLM to measure
- *
- * Return: Clock rate in Hz
- */
- int cvmx_qlm_measure_clock(int qlm)
- {
- cvmx_mio_ptp_clock_cfg_t ptp_clock;
- u64 count;
- u64 start_cycle, stop_cycle;
- int evcnt_offset = 0x10;
- int incr_count = 1;
- int ref_clock[16] = { 0 };
- if (ref_clock[qlm])
- return ref_clock[qlm];
- if (OCTEON_IS_OCTEON3() && !OCTEON_IS_MODEL(OCTEON_CN70XX))
- return cvmx_qlm_measure_clock_cn7xxx(cvmx_get_node_num(), qlm);
- if (OCTEON_IS_MODEL(OCTEON_CN70XX) && qlm == 0) {
- cvmx_gserx_dlmx_ref_clkdiv2_t ref_clkdiv2;
- ref_clkdiv2.u64 = csr_rd(CVMX_GSERX_DLMX_REF_CLKDIV2(qlm, 0));
- if (ref_clkdiv2.s.ref_clkdiv2)
- incr_count = 2;
- }
- /* Fix reference clock for OCI QLMs */
- /* Disable the PTP event counter while we configure it */
- ptp_clock.u64 = csr_rd(CVMX_MIO_PTP_CLOCK_CFG); /* For CN63XXp1 errata */
- ptp_clock.s.evcnt_en = 0;
- csr_wr(CVMX_MIO_PTP_CLOCK_CFG, ptp_clock.u64);
- /* Count on rising edge, Choose which QLM to count */
- ptp_clock.u64 = csr_rd(CVMX_MIO_PTP_CLOCK_CFG); /* For CN63XXp1 errata */
- ptp_clock.s.evcnt_edge = 0;
- ptp_clock.s.evcnt_in = evcnt_offset + qlm;
- csr_wr(CVMX_MIO_PTP_CLOCK_CFG, ptp_clock.u64);
- /* Clear MIO_PTP_EVT_CNT */
- csr_rd(CVMX_MIO_PTP_EVT_CNT); /* For CN63XXp1 errata */
- count = csr_rd(CVMX_MIO_PTP_EVT_CNT);
- csr_wr(CVMX_MIO_PTP_EVT_CNT, -count);
- /* Set MIO_PTP_EVT_CNT to 1 billion */
- csr_wr(CVMX_MIO_PTP_EVT_CNT, 1000000000);
- /* Enable the PTP event counter */
- ptp_clock.u64 = csr_rd(CVMX_MIO_PTP_CLOCK_CFG); /* For CN63XXp1 errata */
- ptp_clock.s.evcnt_en = 1;
- csr_wr(CVMX_MIO_PTP_CLOCK_CFG, ptp_clock.u64);
- start_cycle = get_ticks();
- /* Wait for 50ms */
- mdelay(50);
- /* Read the counter */
- csr_rd(CVMX_MIO_PTP_EVT_CNT); /* For CN63XXp1 errata */
- count = csr_rd(CVMX_MIO_PTP_EVT_CNT);
- stop_cycle = get_ticks();
- /* Disable the PTP event counter */
- ptp_clock.u64 = csr_rd(CVMX_MIO_PTP_CLOCK_CFG); /* For CN63XXp1 errata */
- ptp_clock.s.evcnt_en = 0;
- csr_wr(CVMX_MIO_PTP_CLOCK_CFG, ptp_clock.u64);
- /* Clock counted down, so reverse it */
- count = 1000000000 - count;
- count *= incr_count;
- /* Return the rate */
- ref_clock[qlm] = count * gd->cpu_clk / (stop_cycle - start_cycle);
- return ref_clock[qlm];
- }
- /*
- * Perform RX equalization on a QLM
- *
- * @param node Node the QLM is on
- * @param qlm QLM to perform RX equalization on
- * @param lane Lane to use, or -1 for all lanes
- *
- * Return: Zero on success, negative if any lane failed RX equalization
- */
- int __cvmx_qlm_rx_equalization(int node, int qlm, int lane)
- {
- cvmx_gserx_phy_ctl_t phy_ctl;
- cvmx_gserx_br_rxx_ctl_t rxx_ctl;
- cvmx_gserx_br_rxx_eer_t rxx_eer;
- cvmx_gserx_rx_eie_detsts_t eie_detsts;
- int fail, gbaud, l, lane_mask;
- enum cvmx_qlm_mode mode;
- int max_lanes = cvmx_qlm_get_lanes(qlm);
- cvmx_gserx_lane_mode_t lmode;
- cvmx_gserx_lane_px_mode_1_t pmode_1;
- int pending = 0;
- u64 timeout;
- /* Don't touch QLMs if it is reset or powered down */
- phy_ctl.u64 = csr_rd_node(node, CVMX_GSERX_PHY_CTL(qlm));
- if (phy_ctl.s.phy_pd || phy_ctl.s.phy_reset)
- return -1;
- /*
- * Check whether GSER PRBS pattern matcher is enabled on any of the
- * applicable lanes. Can't complete RX Equalization while pattern
- * matcher is enabled because it causes errors
- */
- for (l = 0; l < max_lanes; l++) {
- cvmx_gserx_lanex_lbert_cfg_t lbert_cfg;
- if (lane != -1 && lane != l)
- continue;
- lbert_cfg.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_LBERT_CFG(l, qlm));
- if (lbert_cfg.s.lbert_pm_en == 1)
- return -1;
- }
- /* Get Lane Mode */
- lmode.u64 = csr_rd_node(node, CVMX_GSERX_LANE_MODE(qlm));
- /*
- * Check to see if in VMA manual mode is set. If in VMA manual mode
- * don't complete rx equalization
- */
- pmode_1.u64 = csr_rd_node(node, CVMX_GSERX_LANE_PX_MODE_1(lmode.s.lmode, qlm));
- if (pmode_1.s.vma_mm == 1) {
- #ifdef DEBUG_QLM
- debug("N%d:QLM%d: VMA Manual (manual DFE) selected. Not completing Rx equalization\n",
- node, qlm);
- #endif
- return 0;
- }
- if (OCTEON_IS_MODEL(OCTEON_CN78XX)) {
- gbaud = cvmx_qlm_get_gbaud_mhz_node(node, qlm);
- mode = cvmx_qlm_get_mode_cn78xx(node, qlm);
- } else {
- gbaud = cvmx_qlm_get_gbaud_mhz(qlm);
- mode = cvmx_qlm_get_mode(qlm);
- }
- /* Apply RX Equalization for speed >= 8G */
- if (qlm < 8) {
- if (gbaud < 6250)
- return 0;
- }
- /* Don't run on PCIe Links */
- if (mode == CVMX_QLM_MODE_PCIE || mode == CVMX_QLM_MODE_PCIE_1X8 ||
- mode == CVMX_QLM_MODE_PCIE_1X2 || mode == CVMX_QLM_MODE_PCIE_2X1)
- return -1;
- fail = 0;
- /*
- * Before completing Rx equalization wait for
- * GSERx_RX_EIE_DETSTS[CDRLOCK] to be set.
- * This ensures the rx data is valid
- */
- if (lane == -1) {
- /*
- * check all 4 Lanes (cdrlock = 1111/b) for CDR Lock with
- * lane == -1
- */
- if (CVMX_WAIT_FOR_FIELD64_NODE(node, CVMX_GSERX_RX_EIE_DETSTS(qlm),
- cvmx_gserx_rx_eie_detsts_t, cdrlock, ==,
- (1 << max_lanes) - 1, 500)) {
- #ifdef DEBUG_QLM
- eie_detsts.u64 = csr_rd_node(node, CVMX_GSERX_RX_EIE_DETSTS(qlm));
- debug("ERROR: %d:QLM%d: CDR Lock not detected for all 4 lanes. CDR_LOCK(0x%x)\n",
- node, qlm, eie_detsts.s.cdrlock);
- #endif
- return -1;
- }
- } else {
- if (CVMX_WAIT_FOR_FIELD64_NODE(node, CVMX_GSERX_RX_EIE_DETSTS(qlm),
- cvmx_gserx_rx_eie_detsts_t, cdrlock, &, (1 << lane),
- 500)) {
- #ifdef DEBUG_QLM
- eie_detsts.u64 = csr_rd_node(node, CVMX_GSERX_RX_EIE_DETSTS(qlm));
- debug("ERROR: %d:QLM%d: CDR Lock not detected for Lane%d CDR_LOCK(0x%x)\n",
- node, qlm, lane, eie_detsts.s.cdrlock);
- #endif
- return -1;
- }
- }
- /*
- * Errata (GSER-20075) GSER(0..13)_BR_RX3_EER[RXT_ERR] is
- * GSER(0..13)_BR_RX2_EER[RXT_ERR]. Since lanes 2-3 trigger at the
- * same time, we need to setup lane 3 before we loop through the lanes
- */
- if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X) && (lane == -1 || lane == 3)) {
- /* Enable software control */
- rxx_ctl.u64 = csr_rd_node(node, CVMX_GSERX_BR_RXX_CTL(3, qlm));
- rxx_ctl.s.rxt_swm = 1;
- csr_wr_node(node, CVMX_GSERX_BR_RXX_CTL(3, qlm), rxx_ctl.u64);
- /* Clear the completion flag */
- rxx_eer.u64 = csr_rd_node(node, CVMX_GSERX_BR_RXX_EER(3, qlm));
- rxx_eer.s.rxt_esv = 0;
- csr_wr_node(node, CVMX_GSERX_BR_RXX_EER(3, qlm), rxx_eer.u64);
- /* Initiate a new request on lane 2 */
- if (lane == 3) {
- rxx_eer.u64 = csr_rd_node(node, CVMX_GSERX_BR_RXX_EER(2, qlm));
- rxx_eer.s.rxt_eer = 1;
- csr_wr_node(node, CVMX_GSERX_BR_RXX_EER(2, qlm), rxx_eer.u64);
- }
- }
- for (l = 0; l < max_lanes; l++) {
- if (lane != -1 && lane != l)
- continue;
- /*
- * Skip lane 3 on 78p1.x due to Errata (GSER-20075).
- * Handled above
- */
- if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X) && l == 3) {
- /*
- * Need to add lane 3 to pending list for 78xx
- * pass 1.x
- */
- pending |= 1 << 3;
- continue;
- }
- /* Enable software control */
- rxx_ctl.u64 = csr_rd_node(node, CVMX_GSERX_BR_RXX_CTL(l, qlm));
- rxx_ctl.s.rxt_swm = 1;
- csr_wr_node(node, CVMX_GSERX_BR_RXX_CTL(l, qlm), rxx_ctl.u64);
- /* Clear the completion flag and initiate a new request */
- rxx_eer.u64 = csr_rd_node(node, CVMX_GSERX_BR_RXX_EER(l, qlm));
- rxx_eer.s.rxt_esv = 0;
- rxx_eer.s.rxt_eer = 1;
- csr_wr_node(node, CVMX_GSERX_BR_RXX_EER(l, qlm), rxx_eer.u64);
- pending |= 1 << l;
- }
- /*
- * Wait for 250ms, approx 10x times measured value, as XFI/XLAUI
- * can take 21-23ms, other interfaces can take 2-3ms.
- */
- timeout = get_timer(0);
- lane_mask = 0;
- while (pending) {
- /* Wait for RX equalization to complete */
- for (l = 0; l < max_lanes; l++) {
- lane_mask = 1 << l;
- /* Only check lanes that are pending */
- if (!(pending & lane_mask))
- continue;
- /*
- * Read the registers for checking Electrical Idle/CDR
- * lock and the status of the RX equalization
- */
- eie_detsts.u64 = csr_rd_node(node, CVMX_GSERX_RX_EIE_DETSTS(qlm));
- rxx_eer.u64 = csr_rd_node(node, CVMX_GSERX_BR_RXX_EER(l, qlm));
- /*
- * Mark failure if lane entered Electrical Idle or lost
- * CDR Lock. The bit for the lane will have cleared in
- * either EIESTS or CDRLOCK
- */
- if (!(eie_detsts.s.eiests & eie_detsts.s.cdrlock & lane_mask)) {
- fail |= lane_mask;
- pending &= ~lane_mask;
- } else if (rxx_eer.s.rxt_esv) {
- pending &= ~lane_mask;
- }
- }
- /* Breakout of the loop on timeout */
- if (get_timer(timeout) > 250)
- break;
- }
- lane_mask = 0;
- /* Cleanup and report status */
- for (l = 0; l < max_lanes; l++) {
- if (lane != -1 && lane != l)
- continue;
- lane_mask = 1 << l;
- rxx_eer.u64 = csr_rd_node(node, CVMX_GSERX_BR_RXX_EER(l, qlm));
- /* Switch back to hardware control */
- rxx_ctl.u64 = csr_rd_node(node, CVMX_GSERX_BR_RXX_CTL(l, qlm));
- rxx_ctl.s.rxt_swm = 0;
- csr_wr_node(node, CVMX_GSERX_BR_RXX_CTL(l, qlm), rxx_ctl.u64);
- /* Report status */
- if (fail & lane_mask) {
- #ifdef DEBUG_QLM
- debug("%d:QLM%d: Lane%d RX equalization lost CDR Lock or entered Electrical Idle\n",
- node, qlm, l);
- #endif
- } else if ((pending & lane_mask) || !rxx_eer.s.rxt_esv) {
- #ifdef DEBUG_QLM
- debug("%d:QLM%d: Lane %d RX equalization timeout\n", node, qlm, l);
- #endif
- fail |= 1 << l;
- } else {
- #ifdef DEBUG_QLM
- char *dir_label[4] = { "Hold", "Inc", "Dec", "Hold" };
- #ifdef DEBUG_QLM_RX
- cvmx_gserx_lanex_rx_aeq_out_0_t rx_aeq_out_0;
- cvmx_gserx_lanex_rx_aeq_out_1_t rx_aeq_out_1;
- cvmx_gserx_lanex_rx_aeq_out_2_t rx_aeq_out_2;
- cvmx_gserx_lanex_rx_vma_status_0_t rx_vma_status_0;
- #endif
- debug("%d:QLM%d: Lane%d: RX equalization completed.\n", node, qlm, l);
- debug(" Tx Direction Hints TXPRE: %s, TXMAIN: %s, TXPOST: %s, Figure of Merit: %d\n",
- dir_label[(rxx_eer.s.rxt_esm) & 0x3],
- dir_label[((rxx_eer.s.rxt_esm) >> 2) & 0x3],
- dir_label[((rxx_eer.s.rxt_esm) >> 4) & 0x3], rxx_eer.s.rxt_esm >> 6);
- #ifdef DEBUG_QLM_RX
- rx_aeq_out_0.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_AEQ_OUT_0(l, qlm));
- rx_aeq_out_1.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_AEQ_OUT_1(l, qlm));
- rx_aeq_out_2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_AEQ_OUT_2(l, qlm));
- rx_vma_status_0.u64 =
- csr_rd_node(node, CVMX_GSERX_LANEX_RX_VMA_STATUS_0(l, qlm));
- debug(" DFE Tap1:%lu, Tap2:%ld, Tap3:%ld, Tap4:%ld, Tap5:%ld\n",
- (unsigned int long)cvmx_bit_extract(rx_aeq_out_1.u64, 0, 5),
- (unsigned int long)cvmx_bit_extract_smag(rx_aeq_out_1.u64, 5, 9),
- (unsigned int long)cvmx_bit_extract_smag(rx_aeq_out_1.u64, 10, 14),
- (unsigned int long)cvmx_bit_extract_smag(rx_aeq_out_0.u64, 0, 4),
- (unsigned int long)cvmx_bit_extract_smag(rx_aeq_out_0.u64, 5, 9));
- debug(" Pre-CTLE Gain:%lu, Post-CTLE Gain:%lu, CTLE Peak:%lu, CTLE Pole:%lu\n",
- (unsigned int long)cvmx_bit_extract(rx_aeq_out_2.u64, 4, 4),
- (unsigned int long)cvmx_bit_extract(rx_aeq_out_2.u64, 0, 4),
- (unsigned int long)cvmx_bit_extract(rx_vma_status_0.u64, 2, 4),
- (unsigned int long)cvmx_bit_extract(rx_vma_status_0.u64, 0, 2));
- #endif
- #endif
- }
- }
- return (fail) ? -1 : 0;
- }
- /**
- * Errata GSER-27882 -GSER 10GBASE-KR Transmit Equalizer
- * Training may not update PHY Tx Taps. This function is not static
- * so we can share it with BGX KR
- *
- * @param node Node to apply errata workaround
- * @param qlm QLM to apply errata workaround
- * @param lane Lane to apply the errata
- */
- int cvmx_qlm_gser_errata_27882(int node, int qlm, int lane)
- {
- cvmx_gserx_lanex_pcs_ctlifc_0_t clifc0;
- cvmx_gserx_lanex_pcs_ctlifc_2_t clifc2;
- if (!(OCTEON_IS_MODEL(OCTEON_CN73XX_PASS1_0) || OCTEON_IS_MODEL(OCTEON_CN73XX_PASS1_1) ||
- OCTEON_IS_MODEL(OCTEON_CN73XX_PASS1_2) || OCTEON_IS_MODEL(OCTEON_CNF75XX_PASS1_0) ||
- OCTEON_IS_MODEL(OCTEON_CN78XX)))
- return 0;
- if (CVMX_WAIT_FOR_FIELD64_NODE(node, CVMX_GSERX_RX_EIE_DETSTS(qlm),
- cvmx_gserx_rx_eie_detsts_t, cdrlock, &,
- (1 << lane), 200))
- return -1;
- clifc0.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_0(lane, qlm));
- clifc0.s.cfg_tx_coeff_req_ovrrd_val = 1;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_0(lane, qlm), clifc0.u64);
- clifc2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));
- clifc2.s.cfg_tx_coeff_req_ovrrd_en = 1;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), clifc2.u64);
- clifc2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));
- clifc2.s.ctlifc_ovrrd_req = 1;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), clifc2.u64);
- clifc2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));
- clifc2.s.cfg_tx_coeff_req_ovrrd_en = 0;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), clifc2.u64);
- clifc2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));
- clifc2.s.ctlifc_ovrrd_req = 1;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), clifc2.u64);
- return 0;
- }
- /**
- * Updates the RX EQ Default Settings Update (CTLE Bias) to support longer
- * SERDES channels
- *
- * @INTERNAL
- *
- * @param node Node number to configure
- * @param qlm QLM number to configure
- */
- void cvmx_qlm_gser_errata_25992(int node, int qlm)
- {
- int lane;
- int num_lanes = cvmx_qlm_get_lanes(qlm);
- if (!(OCTEON_IS_MODEL(OCTEON_CN73XX_PASS1_0) || OCTEON_IS_MODEL(OCTEON_CN73XX_PASS1_1) ||
- OCTEON_IS_MODEL(OCTEON_CN73XX_PASS1_2) || OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X)))
- return;
- for (lane = 0; lane < num_lanes; lane++) {
- cvmx_gserx_lanex_rx_ctle_ctrl_t rx_ctle_ctrl;
- cvmx_gserx_lanex_rx_cfg_4_t rx_cfg_4;
- rx_ctle_ctrl.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_CTLE_CTRL(lane, qlm));
- rx_ctle_ctrl.s.pcs_sds_rx_ctle_bias_ctrl = 3;
- csr_wr_node(node, CVMX_GSERX_LANEX_RX_CTLE_CTRL(lane, qlm), rx_ctle_ctrl.u64);
- rx_cfg_4.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_CFG_4(lane, qlm));
- rx_cfg_4.s.cfg_rx_errdet_ctrl = 0xcd6f;
- csr_wr_node(node, CVMX_GSERX_LANEX_RX_CFG_4(lane, qlm), rx_cfg_4.u64);
- }
- }
- void cvmx_qlm_display_registers(int qlm)
- {
- int num_lanes = cvmx_qlm_get_lanes(qlm);
- int lane;
- const __cvmx_qlm_jtag_field_t *ptr = cvmx_qlm_jtag_get_field();
- debug("%29s", "Field[<stop bit>:<start bit>]");
- for (lane = 0; lane < num_lanes; lane++)
- debug("\t Lane %d", lane);
- debug("\n");
- while (ptr && ptr->name) {
- debug("%20s[%3d:%3d]", ptr->name, ptr->stop_bit, ptr->start_bit);
- for (lane = 0; lane < num_lanes; lane++) {
- u64 val;
- int tx_byp = 0;
- /*
- * Make sure serdes_tx_byp is set for displaying
- * TX amplitude and TX demphasis field values.
- */
- if (strncmp(ptr->name, "biasdrv_", 8) == 0 ||
- strncmp(ptr->name, "tcoeff_", 7) == 0) {
- tx_byp = cvmx_qlm_jtag_get(qlm, lane, "serdes_tx_byp");
- if (tx_byp == 0) {
- debug("\t \t");
- continue;
- }
- }
- val = cvmx_qlm_jtag_get(qlm, lane, ptr->name);
- debug("\t%4llu (0x%04llx)", (unsigned long long)val,
- (unsigned long long)val);
- }
- debug("\n");
- ptr++;
- }
- }
- /* ToDo: CVMX_DUMP_GSER removed for now (unused!) */
|