1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright (C) 2020 Marvell International Ltd.
- *
- * Helper functions for common, but complicated tasks.
- */
- #include <log.h>
- #include <linux/delay.h>
- #include <mach/cvmx-regs.h>
- #include <mach/cvmx-csr.h>
- #include <mach/cvmx-bootmem.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-coremask.h>
- #include <mach/cvmx-agl-defs.h>
- #include <mach/cvmx-asxx-defs.h>
- #include <mach/cvmx-bgxx-defs.h>
- #include <mach/cvmx-dbg-defs.h>
- #include <mach/cvmx-gmxx-defs.h>
- #include <mach/cvmx-gserx-defs.h>
- #include <mach/cvmx-ipd-defs.h>
- #include <mach/cvmx-l2c-defs.h>
- #include <mach/cvmx-npi-defs.h>
- #include <mach/cvmx-pcsx-defs.h>
- #include <mach/cvmx-pexp-defs.h>
- #include <mach/cvmx-pki-defs.h>
- #include <mach/cvmx-pko-defs.h>
- #include <mach/cvmx-smix-defs.h>
- #include <mach/cvmx-sriox-defs.h>
- #include <mach/cvmx-helper.h>
- #include <mach/cvmx-helper-board.h>
- #include <mach/cvmx-helper-fdt.h>
- #include <mach/cvmx-helper-bgx.h>
- #include <mach/cvmx-helper-cfg.h>
- #include <mach/cvmx-helper-ipd.h>
- #include <mach/cvmx-helper-util.h>
- #include <mach/cvmx-helper-pki.h>
- #include <mach/cvmx-helper-pko.h>
- #include <mach/cvmx-helper-pko3.h>
- #include <mach/cvmx-global-resources.h>
- #include <mach/cvmx-pko-internal-ports-range.h>
- #include <mach/cvmx-pko3-queue.h>
- #include <mach/cvmx-gmx.h>
- #include <mach/cvmx-hwpko.h>
- #include <mach/cvmx-ilk.h>
- #include <mach/cvmx-ipd.h>
- #include <mach/cvmx-pip.h>
- /**
- * @INTERNAL
- * This structure specifies the interface methods used by an interface.
- *
- * @param mode Interface mode.
- *
- * @param enumerate Method the get number of interface ports.
- *
- * @param probe Method to probe an interface to get the number of
- * connected ports.
- *
- * @param enable Method to enable an interface
- *
- * @param link_get Method to get the state of an interface link.
- *
- * @param link_set Method to configure an interface link to the specified
- * state.
- *
- * @param loopback Method to configure a port in loopback.
- */
- struct iface_ops {
- cvmx_helper_interface_mode_t mode;
- int (*enumerate)(int xiface);
- int (*probe)(int xiface);
- int (*enable)(int xiface);
- cvmx_helper_link_info_t (*link_get)(int ipd_port);
- int (*link_set)(int ipd_port, cvmx_helper_link_info_t link_info);
- int (*loopback)(int ipd_port, int en_in, int en_ex);
- };
- /**
- * @INTERNAL
- * This structure is used by disabled interfaces.
- */
- static const struct iface_ops iface_ops_dis = {
- .mode = CVMX_HELPER_INTERFACE_MODE_DISABLED,
- };
- /**
- * @INTERNAL
- * This structure specifies the interface methods used by interfaces
- * configured as gmii.
- */
- static const struct iface_ops iface_ops_gmii = {
- .mode = CVMX_HELPER_INTERFACE_MODE_GMII,
- .enumerate = __cvmx_helper_rgmii_probe,
- .probe = __cvmx_helper_rgmii_probe,
- .enable = __cvmx_helper_rgmii_enable,
- .link_get = __cvmx_helper_gmii_link_get,
- .link_set = __cvmx_helper_rgmii_link_set,
- .loopback = __cvmx_helper_rgmii_configure_loopback,
- };
- /**
- * @INTERNAL
- * This structure specifies the interface methods used by interfaces
- * configured as rgmii.
- */
- static const struct iface_ops iface_ops_rgmii = {
- .mode = CVMX_HELPER_INTERFACE_MODE_RGMII,
- .enumerate = __cvmx_helper_rgmii_probe,
- .probe = __cvmx_helper_rgmii_probe,
- .enable = __cvmx_helper_rgmii_enable,
- .link_get = __cvmx_helper_rgmii_link_get,
- .link_set = __cvmx_helper_rgmii_link_set,
- .loopback = __cvmx_helper_rgmii_configure_loopback,
- };
- /**
- * @INTERNAL
- * This structure specifies the interface methods used by interfaces
- * configured as sgmii that use the gmx mac.
- */
- static const struct iface_ops iface_ops_sgmii = {
- .mode = CVMX_HELPER_INTERFACE_MODE_SGMII,
- .enumerate = __cvmx_helper_sgmii_enumerate,
- .probe = __cvmx_helper_sgmii_probe,
- .enable = __cvmx_helper_sgmii_enable,
- .link_get = __cvmx_helper_sgmii_link_get,
- .link_set = __cvmx_helper_sgmii_link_set,
- .loopback = __cvmx_helper_sgmii_configure_loopback,
- };
- /**
- * @INTERNAL
- * This structure specifies the interface methods used by interfaces
- * configured as sgmii that use the bgx mac.
- */
- static const struct iface_ops iface_ops_bgx_sgmii = {
- .mode = CVMX_HELPER_INTERFACE_MODE_SGMII,
- .enumerate = __cvmx_helper_bgx_enumerate,
- .probe = __cvmx_helper_bgx_probe,
- .enable = __cvmx_helper_bgx_sgmii_enable,
- .link_get = __cvmx_helper_bgx_sgmii_link_get,
- .link_set = __cvmx_helper_bgx_sgmii_link_set,
- .loopback = __cvmx_helper_bgx_sgmii_configure_loopback,
- };
- /**
- * @INTERNAL
- * This structure specifies the interface methods used by interfaces
- * configured as qsgmii.
- */
- static const struct iface_ops iface_ops_qsgmii = {
- .mode = CVMX_HELPER_INTERFACE_MODE_QSGMII,
- .enumerate = __cvmx_helper_sgmii_enumerate,
- .probe = __cvmx_helper_sgmii_probe,
- .enable = __cvmx_helper_sgmii_enable,
- .link_get = __cvmx_helper_sgmii_link_get,
- .link_set = __cvmx_helper_sgmii_link_set,
- .loopback = __cvmx_helper_sgmii_configure_loopback,
- };
- /**
- * @INTERNAL
- * This structure specifies the interface methods used by interfaces
- * configured as xaui using the gmx mac.
- */
- static const struct iface_ops iface_ops_xaui = {
- .mode = CVMX_HELPER_INTERFACE_MODE_XAUI,
- .enumerate = __cvmx_helper_xaui_enumerate,
- .probe = __cvmx_helper_xaui_probe,
- .enable = __cvmx_helper_xaui_enable,
- .link_get = __cvmx_helper_xaui_link_get,
- .link_set = __cvmx_helper_xaui_link_set,
- .loopback = __cvmx_helper_xaui_configure_loopback,
- };
- /**
- * @INTERNAL
- * This structure specifies the interface methods used by interfaces
- * configured as xaui using the gmx mac.
- */
- static const struct iface_ops iface_ops_bgx_xaui = {
- .mode = CVMX_HELPER_INTERFACE_MODE_XAUI,
- .enumerate = __cvmx_helper_bgx_enumerate,
- .probe = __cvmx_helper_bgx_probe,
- .enable = __cvmx_helper_bgx_xaui_enable,
- .link_get = __cvmx_helper_bgx_xaui_link_get,
- .link_set = __cvmx_helper_bgx_xaui_link_set,
- .loopback = __cvmx_helper_bgx_xaui_configure_loopback,
- };
- /**
- * @INTERNAL
- * This structure specifies the interface methods used by interfaces
- * configured as rxaui.
- */
- static const struct iface_ops iface_ops_rxaui = {
- .mode = CVMX_HELPER_INTERFACE_MODE_RXAUI,
- .enumerate = __cvmx_helper_xaui_enumerate,
- .probe = __cvmx_helper_xaui_probe,
- .enable = __cvmx_helper_xaui_enable,
- .link_get = __cvmx_helper_xaui_link_get,
- .link_set = __cvmx_helper_xaui_link_set,
- .loopback = __cvmx_helper_xaui_configure_loopback,
- };
- /**
- * @INTERNAL
- * This structure specifies the interface methods used by interfaces
- * configured as xaui using the gmx mac.
- */
- static const struct iface_ops iface_ops_bgx_rxaui = {
- .mode = CVMX_HELPER_INTERFACE_MODE_RXAUI,
- .enumerate = __cvmx_helper_bgx_enumerate,
- .probe = __cvmx_helper_bgx_probe,
- .enable = __cvmx_helper_bgx_xaui_enable,
- .link_get = __cvmx_helper_bgx_xaui_link_get,
- .link_set = __cvmx_helper_bgx_xaui_link_set,
- .loopback = __cvmx_helper_bgx_xaui_configure_loopback,
- };
- /**
- * @INTERNAL
- * This structure specifies the interface methods used by interfaces
- * configured as xlaui.
- */
- static const struct iface_ops iface_ops_bgx_xlaui = {
- .mode = CVMX_HELPER_INTERFACE_MODE_XLAUI,
- .enumerate = __cvmx_helper_bgx_enumerate,
- .probe = __cvmx_helper_bgx_probe,
- .enable = __cvmx_helper_bgx_xaui_enable,
- .link_get = __cvmx_helper_bgx_xaui_link_get,
- .link_set = __cvmx_helper_bgx_xaui_link_set,
- .loopback = __cvmx_helper_bgx_xaui_configure_loopback,
- };
- /**
- * @INTERNAL
- * This structure specifies the interface methods used by interfaces
- * configured as xfi.
- */
- static const struct iface_ops iface_ops_bgx_xfi = {
- .mode = CVMX_HELPER_INTERFACE_MODE_XFI,
- .enumerate = __cvmx_helper_bgx_enumerate,
- .probe = __cvmx_helper_bgx_probe,
- .enable = __cvmx_helper_bgx_xaui_enable,
- .link_get = __cvmx_helper_bgx_xaui_link_get,
- .link_set = __cvmx_helper_bgx_xaui_link_set,
- .loopback = __cvmx_helper_bgx_xaui_configure_loopback,
- };
- static const struct iface_ops iface_ops_bgx_10G_KR = {
- .mode = CVMX_HELPER_INTERFACE_MODE_10G_KR,
- .enumerate = __cvmx_helper_bgx_enumerate,
- .probe = __cvmx_helper_bgx_probe,
- .enable = __cvmx_helper_bgx_xaui_enable,
- .link_get = __cvmx_helper_bgx_xaui_link_get,
- .link_set = __cvmx_helper_bgx_xaui_link_set,
- .loopback = __cvmx_helper_bgx_xaui_configure_loopback,
- };
- static const struct iface_ops iface_ops_bgx_40G_KR4 = {
- .mode = CVMX_HELPER_INTERFACE_MODE_40G_KR4,
- .enumerate = __cvmx_helper_bgx_enumerate,
- .probe = __cvmx_helper_bgx_probe,
- .enable = __cvmx_helper_bgx_xaui_enable,
- .link_get = __cvmx_helper_bgx_xaui_link_get,
- .link_set = __cvmx_helper_bgx_xaui_link_set,
- .loopback = __cvmx_helper_bgx_xaui_configure_loopback,
- };
- /**
- * @INTERNAL
- * This structure specifies the interface methods used by interfaces
- * configured as ilk.
- */
- static const struct iface_ops iface_ops_ilk = {
- .mode = CVMX_HELPER_INTERFACE_MODE_ILK,
- .enumerate = __cvmx_helper_ilk_enumerate,
- .probe = __cvmx_helper_ilk_probe,
- .enable = __cvmx_helper_ilk_enable,
- .link_get = __cvmx_helper_ilk_link_get,
- .link_set = __cvmx_helper_ilk_link_set,
- };
- /**
- * @INTERNAL
- * This structure specifies the interface methods used by interfaces
- * configured as npi.
- */
- static const struct iface_ops iface_ops_npi = {
- .mode = CVMX_HELPER_INTERFACE_MODE_NPI,
- .enumerate = __cvmx_helper_npi_probe,
- .probe = __cvmx_helper_npi_probe,
- .enable = __cvmx_helper_npi_enable,
- };
- /**
- * @INTERNAL
- * This structure specifies the interface methods used by interfaces
- * configured as srio.
- */
- static const struct iface_ops iface_ops_srio = {
- .mode = CVMX_HELPER_INTERFACE_MODE_SRIO,
- .enumerate = __cvmx_helper_srio_probe,
- .probe = __cvmx_helper_srio_probe,
- .enable = __cvmx_helper_srio_enable,
- .link_get = __cvmx_helper_srio_link_get,
- .link_set = __cvmx_helper_srio_link_set,
- };
- /**
- * @INTERNAL
- * This structure specifies the interface methods used by interfaces
- * configured as agl.
- */
- static const struct iface_ops iface_ops_agl = {
- .mode = CVMX_HELPER_INTERFACE_MODE_AGL,
- .enumerate = __cvmx_helper_agl_enumerate,
- .probe = __cvmx_helper_agl_probe,
- .enable = __cvmx_helper_agl_enable,
- .link_get = __cvmx_helper_agl_link_get,
- .link_set = __cvmx_helper_agl_link_set,
- };
- /**
- * @INTERNAL
- * This structure specifies the interface methods used by interfaces
- * configured as mixed mode, some ports are sgmii and some are xfi.
- */
- static const struct iface_ops iface_ops_bgx_mixed = {
- .mode = CVMX_HELPER_INTERFACE_MODE_MIXED,
- .enumerate = __cvmx_helper_bgx_enumerate,
- .probe = __cvmx_helper_bgx_probe,
- .enable = __cvmx_helper_bgx_mixed_enable,
- .link_get = __cvmx_helper_bgx_mixed_link_get,
- .link_set = __cvmx_helper_bgx_mixed_link_set,
- .loopback = __cvmx_helper_bgx_mixed_configure_loopback,
- };
- /**
- * @INTERNAL
- * This structure specifies the interface methods used by interfaces
- * configured as loop.
- */
- static const struct iface_ops iface_ops_loop = {
- .mode = CVMX_HELPER_INTERFACE_MODE_LOOP,
- .enumerate = __cvmx_helper_loop_enumerate,
- .probe = __cvmx_helper_loop_probe,
- };
- const struct iface_ops *iface_node_ops[CVMX_MAX_NODES][CVMX_HELPER_MAX_IFACE];
- #define iface_ops iface_node_ops[0]
- struct cvmx_iface {
- int cvif_ipd_nports;
- int cvif_has_fcs; /* PKO fcs for this interface. */
- enum cvmx_pko_padding cvif_padding;
- cvmx_helper_link_info_t *cvif_ipd_port_link_info;
- };
- /*
- * This has to be static as u-boot expects to probe an interface and
- * gets the number of its ports.
- */
- static struct cvmx_iface cvmx_interfaces[CVMX_MAX_NODES][CVMX_HELPER_MAX_IFACE];
- int __cvmx_helper_get_num_ipd_ports(int xiface)
- {
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- struct cvmx_iface *piface;
- if (xi.interface >= cvmx_helper_get_number_of_interfaces())
- return -1;
- piface = &cvmx_interfaces[xi.node][xi.interface];
- return piface->cvif_ipd_nports;
- }
- enum cvmx_pko_padding __cvmx_helper_get_pko_padding(int xiface)
- {
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- struct cvmx_iface *piface;
- if (xi.interface >= cvmx_helper_get_number_of_interfaces())
- return CVMX_PKO_PADDING_NONE;
- piface = &cvmx_interfaces[xi.node][xi.interface];
- return piface->cvif_padding;
- }
- int __cvmx_helper_init_interface(int xiface, int num_ipd_ports, int has_fcs,
- enum cvmx_pko_padding pad)
- {
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- struct cvmx_iface *piface;
- cvmx_helper_link_info_t *p;
- int i;
- int sz;
- u64 addr;
- char name[32];
- if (xi.interface >= cvmx_helper_get_number_of_interfaces())
- return -1;
- piface = &cvmx_interfaces[xi.node][xi.interface];
- piface->cvif_ipd_nports = num_ipd_ports;
- piface->cvif_padding = pad;
- piface->cvif_has_fcs = has_fcs;
- /*
- * allocate the per-ipd_port link_info structure
- */
- sz = piface->cvif_ipd_nports * sizeof(cvmx_helper_link_info_t);
- snprintf(name, sizeof(name), "__int_%d_link_info", xi.interface);
- addr = CAST64(cvmx_bootmem_alloc_named_range_once(sz, 0, 0,
- __alignof(cvmx_helper_link_info_t),
- name, NULL));
- piface->cvif_ipd_port_link_info =
- (cvmx_helper_link_info_t *)__cvmx_phys_addr_to_ptr(addr, sz);
- if (!piface->cvif_ipd_port_link_info) {
- if (sz != 0)
- debug("iface %d failed to alloc link info\n", xi.interface);
- return -1;
- }
- /* Initialize them */
- p = piface->cvif_ipd_port_link_info;
- for (i = 0; i < piface->cvif_ipd_nports; i++) {
- (*p).u64 = 0;
- p++;
- }
- return 0;
- }
- /*
- * Shut down the interfaces; free the resources.
- * @INTERNAL
- */
- void __cvmx_helper_shutdown_interfaces_node(unsigned int node)
- {
- int i;
- int nifaces; /* number of interfaces */
- struct cvmx_iface *piface;
- nifaces = cvmx_helper_get_number_of_interfaces();
- for (i = 0; i < nifaces; i++) {
- piface = &cvmx_interfaces[node][i];
- /*
- * For SE apps, bootmem was meant to be allocated and never
- * freed.
- */
- piface->cvif_ipd_port_link_info = 0;
- }
- }
- void __cvmx_helper_shutdown_interfaces(void)
- {
- unsigned int node = cvmx_get_node_num();
- __cvmx_helper_shutdown_interfaces_node(node);
- }
- int __cvmx_helper_set_link_info(int xiface, int index, cvmx_helper_link_info_t link_info)
- {
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- struct cvmx_iface *piface;
- if (xi.interface >= cvmx_helper_get_number_of_interfaces())
- return -1;
- piface = &cvmx_interfaces[xi.node][xi.interface];
- if (piface->cvif_ipd_port_link_info) {
- piface->cvif_ipd_port_link_info[index] = link_info;
- return 0;
- }
- return -1;
- }
- cvmx_helper_link_info_t __cvmx_helper_get_link_info(int xiface, int port)
- {
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- struct cvmx_iface *piface;
- cvmx_helper_link_info_t err;
- err.u64 = 0;
- if (xi.interface >= cvmx_helper_get_number_of_interfaces())
- return err;
- piface = &cvmx_interfaces[xi.node][xi.interface];
- if (piface->cvif_ipd_port_link_info)
- return piface->cvif_ipd_port_link_info[port];
- return err;
- }
- /**
- * Returns if FCS is enabled for the specified interface and port
- *
- * @param xiface - interface to check
- *
- * Return: zero if FCS is not used, otherwise FCS is used.
- */
- int __cvmx_helper_get_has_fcs(int xiface)
- {
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- return cvmx_interfaces[xi.node][xi.interface].cvif_has_fcs;
- }
- u64 cvmx_rgmii_backpressure_dis = 1;
- typedef int (*cvmx_export_config_t)(void);
- cvmx_export_config_t cvmx_export_app_config;
- void cvmx_rgmii_set_back_pressure(uint64_t backpressure_dis)
- {
- cvmx_rgmii_backpressure_dis = backpressure_dis;
- }
- /*
- * internal functions that are not exported in the .h file but must be
- * declared to make gcc happy.
- */
- extern cvmx_helper_link_info_t __cvmx_helper_get_link_info(int interface, int port);
- /**
- * cvmx_override_iface_phy_mode(int interface, int index) is a function pointer.
- * It is meant to allow customization of interfaces which do not have a PHY.
- *
- * @returns 0 if MAC decides TX_CONFIG_REG or 1 if PHY decides TX_CONFIG_REG.
- *
- * If this function pointer is NULL then it defaults to the MAC.
- */
- int (*cvmx_override_iface_phy_mode)(int interface, int index);
- /**
- * cvmx_override_ipd_port_setup(int ipd_port) is a function
- * pointer. It is meant to allow customization of the IPD
- * port/port kind setup before packet input/output comes online.
- * It is called after cvmx-helper does the default IPD configuration,
- * but before IPD is enabled. Users should set this pointer to a
- * function before calling any cvmx-helper operations.
- */
- void (*cvmx_override_ipd_port_setup)(int ipd_port) = NULL;
- /**
- * Return the number of interfaces the chip has. Each interface
- * may have multiple ports. Most chips support two interfaces,
- * but the CNX0XX and CNX1XX are exceptions. These only support
- * one interface.
- *
- * Return: Number of interfaces on chip
- */
- int cvmx_helper_get_number_of_interfaces(void)
- {
- if (OCTEON_IS_MODEL(OCTEON_CN68XX))
- return 9;
- else if (OCTEON_IS_MODEL(OCTEON_CN66XX))
- if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0))
- return 7;
- else
- return 8;
- else if (OCTEON_IS_MODEL(OCTEON_CN63XX))
- return 6;
- else if (OCTEON_IS_MODEL(OCTEON_CN61XX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
- return 4;
- else if (OCTEON_IS_MODEL(OCTEON_CN70XX))
- return 5;
- else if (OCTEON_IS_MODEL(OCTEON_CN78XX))
- return 10;
- else if (OCTEON_IS_MODEL(OCTEON_CNF75XX))
- return 5;
- else if (OCTEON_IS_MODEL(OCTEON_CN73XX))
- return 5;
- else
- return 3;
- }
- int __cvmx_helper_early_ports_on_interface(int interface)
- {
- int ports;
- if (octeon_has_feature(OCTEON_FEATURE_PKND))
- return cvmx_helper_interface_enumerate(interface);
- ports = cvmx_helper_interface_enumerate(interface);
- ports = __cvmx_helper_board_interface_probe(interface, ports);
- return ports;
- }
- /**
- * Return the number of ports on an interface. Depending on the
- * chip and configuration, this can be 1-16. A value of 0
- * specifies that the interface doesn't exist or isn't usable.
- *
- * @param xiface xiface to get the port count for
- *
- * Return: Number of ports on interface. Can be Zero.
- */
- int cvmx_helper_ports_on_interface(int xiface)
- {
- if (octeon_has_feature(OCTEON_FEATURE_PKND))
- return cvmx_helper_interface_enumerate(xiface);
- else
- return __cvmx_helper_get_num_ipd_ports(xiface);
- }
- /**
- * @INTERNAL
- * Return interface mode for CN70XX.
- */
- static cvmx_helper_interface_mode_t __cvmx_get_mode_cn70xx(int interface)
- {
- /* SGMII/RXAUI/QSGMII */
- if (interface < 2) {
- enum cvmx_qlm_mode qlm_mode =
- cvmx_qlm_get_dlm_mode(0, interface);
- if (qlm_mode == CVMX_QLM_MODE_SGMII)
- iface_ops[interface] = &iface_ops_sgmii;
- else if (qlm_mode == CVMX_QLM_MODE_QSGMII)
- iface_ops[interface] = &iface_ops_qsgmii;
- else if (qlm_mode == CVMX_QLM_MODE_RXAUI)
- iface_ops[interface] = &iface_ops_rxaui;
- else
- iface_ops[interface] = &iface_ops_dis;
- } else if (interface == 2) { /* DPI */
- iface_ops[interface] = &iface_ops_npi;
- } else if (interface == 3) { /* LOOP */
- iface_ops[interface] = &iface_ops_loop;
- } else if (interface == 4) { /* RGMII (AGL) */
- cvmx_agl_prtx_ctl_t prtx_ctl;
- prtx_ctl.u64 = csr_rd(CVMX_AGL_PRTX_CTL(0));
- if (prtx_ctl.s.mode == 0)
- iface_ops[interface] = &iface_ops_agl;
- else
- iface_ops[interface] = &iface_ops_dis;
- } else {
- iface_ops[interface] = &iface_ops_dis;
- }
- return iface_ops[interface]->mode;
- }
- /**
- * @INTERNAL
- * Return interface mode for CN78XX.
- */
- static cvmx_helper_interface_mode_t __cvmx_get_mode_cn78xx(int xiface)
- {
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- /* SGMII/RXAUI/XAUI */
- if (xi.interface < 6) {
- int qlm = cvmx_qlm_lmac(xiface, 0);
- enum cvmx_qlm_mode qlm_mode;
- if (qlm == -1) {
- iface_node_ops[xi.node][xi.interface] = &iface_ops_dis;
- return iface_node_ops[xi.node][xi.interface]->mode;
- }
- qlm_mode = cvmx_qlm_get_mode_cn78xx(xi.node, qlm);
- if (qlm_mode == CVMX_QLM_MODE_SGMII)
- iface_node_ops[xi.node][xi.interface] = &iface_ops_bgx_sgmii;
- else if (qlm_mode == CVMX_QLM_MODE_XAUI)
- iface_node_ops[xi.node][xi.interface] = &iface_ops_bgx_xaui;
- else if (qlm_mode == CVMX_QLM_MODE_XLAUI)
- iface_node_ops[xi.node][xi.interface] = &iface_ops_bgx_xlaui;
- else if (qlm_mode == CVMX_QLM_MODE_XFI)
- iface_node_ops[xi.node][xi.interface] = &iface_ops_bgx_xfi;
- else if (qlm_mode == CVMX_QLM_MODE_RXAUI)
- iface_node_ops[xi.node][xi.interface] = &iface_ops_bgx_rxaui;
- else
- iface_node_ops[xi.node][xi.interface] = &iface_ops_dis;
- } else if (xi.interface < 8) {
- enum cvmx_qlm_mode qlm_mode;
- int found = 0;
- int i;
- int intf, lane_mask;
- if (xi.interface == 6) {
- intf = 6;
- lane_mask = cvmx_ilk_lane_mask[xi.node][0];
- } else {
- intf = 7;
- lane_mask = cvmx_ilk_lane_mask[xi.node][1];
- }
- switch (lane_mask) {
- default:
- case 0x0:
- iface_node_ops[xi.node][intf] = &iface_ops_dis;
- break;
- case 0xf:
- qlm_mode = cvmx_qlm_get_mode_cn78xx(xi.node, 4);
- if (qlm_mode == CVMX_QLM_MODE_ILK)
- iface_node_ops[xi.node][intf] = &iface_ops_ilk;
- else
- iface_node_ops[xi.node][intf] = &iface_ops_dis;
- break;
- case 0xff:
- found = 0;
- for (i = 4; i < 6; i++) {
- qlm_mode = cvmx_qlm_get_mode_cn78xx(xi.node, i);
- if (qlm_mode == CVMX_QLM_MODE_ILK)
- found++;
- }
- if (found == 2)
- iface_node_ops[xi.node][intf] = &iface_ops_ilk;
- else
- iface_node_ops[xi.node][intf] = &iface_ops_dis;
- break;
- case 0xfff:
- found = 0;
- for (i = 4; i < 7; i++) {
- qlm_mode = cvmx_qlm_get_mode_cn78xx(xi.node, i);
- if (qlm_mode == CVMX_QLM_MODE_ILK)
- found++;
- }
- if (found == 3)
- iface_node_ops[xi.node][intf] = &iface_ops_ilk;
- else
- iface_node_ops[xi.node][intf] = &iface_ops_dis;
- break;
- case 0xff00:
- found = 0;
- for (i = 6; i < 8; i++) {
- qlm_mode = cvmx_qlm_get_mode_cn78xx(xi.node, i);
- if (qlm_mode == CVMX_QLM_MODE_ILK)
- found++;
- }
- if (found == 2)
- iface_node_ops[xi.node][intf] = &iface_ops_ilk;
- else
- iface_node_ops[xi.node][intf] = &iface_ops_dis;
- break;
- case 0xf0:
- qlm_mode = cvmx_qlm_get_mode_cn78xx(xi.node, 5);
- if (qlm_mode == CVMX_QLM_MODE_ILK)
- iface_node_ops[xi.node][intf] = &iface_ops_ilk;
- else
- iface_node_ops[xi.node][intf] = &iface_ops_dis;
- break;
- case 0xf00:
- qlm_mode = cvmx_qlm_get_mode_cn78xx(xi.node, 6);
- if (qlm_mode == CVMX_QLM_MODE_ILK)
- iface_node_ops[xi.node][intf] = &iface_ops_ilk;
- else
- iface_node_ops[xi.node][intf] = &iface_ops_dis;
- break;
- case 0xf000:
- qlm_mode = cvmx_qlm_get_mode_cn78xx(xi.node, 7);
- if (qlm_mode == CVMX_QLM_MODE_ILK)
- iface_node_ops[xi.node][intf] = &iface_ops_ilk;
- else
- iface_node_ops[xi.node][intf] = &iface_ops_dis;
- break;
- case 0xfff0:
- found = 0;
- for (i = 5; i < 8; i++) {
- qlm_mode = cvmx_qlm_get_mode_cn78xx(xi.node, i);
- if (qlm_mode == CVMX_QLM_MODE_ILK)
- found++;
- }
- if (found == 3)
- iface_node_ops[xi.node][intf] = &iface_ops_ilk;
- else
- iface_node_ops[xi.node][intf] = &iface_ops_dis;
- break;
- }
- } else if (xi.interface == 8) { /* DPI */
- int qlm = 0;
- for (qlm = 0; qlm < 5; qlm++) {
- /* if GSERX_CFG[pcie] == 1, then enable npi */
- if (csr_rd_node(xi.node, CVMX_GSERX_CFG(qlm)) & 0x1) {
- iface_node_ops[xi.node][xi.interface] =
- &iface_ops_npi;
- return iface_node_ops[xi.node][xi.interface]->mode;
- }
- }
- iface_node_ops[xi.node][xi.interface] = &iface_ops_dis;
- } else if (xi.interface == 9) { /* LOOP */
- iface_node_ops[xi.node][xi.interface] = &iface_ops_loop;
- } else {
- iface_node_ops[xi.node][xi.interface] = &iface_ops_dis;
- }
- return iface_node_ops[xi.node][xi.interface]->mode;
- }
- /**
- * @INTERNAL
- * Return interface mode for CN73XX.
- */
- static cvmx_helper_interface_mode_t __cvmx_get_mode_cn73xx(int xiface)
- {
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- int interface = xi.interface;
- /* SGMII/XAUI/XLAUI/XFI */
- if (interface < 3) {
- int qlm = cvmx_qlm_lmac(xiface, 0);
- enum cvmx_qlm_mode qlm_mode;
- if (qlm == -1) {
- iface_ops[interface] = &iface_ops_dis;
- return iface_ops[interface]->mode;
- }
- qlm_mode = cvmx_qlm_get_mode(qlm);
- switch (qlm_mode) {
- case CVMX_QLM_MODE_SGMII:
- case CVMX_QLM_MODE_SGMII_2X1:
- case CVMX_QLM_MODE_RGMII_SGMII:
- case CVMX_QLM_MODE_RGMII_SGMII_1X1:
- iface_ops[interface] = &iface_ops_bgx_sgmii;
- break;
- case CVMX_QLM_MODE_XAUI:
- case CVMX_QLM_MODE_RGMII_XAUI:
- iface_ops[interface] = &iface_ops_bgx_xaui;
- break;
- case CVMX_QLM_MODE_RXAUI:
- case CVMX_QLM_MODE_RXAUI_1X2:
- case CVMX_QLM_MODE_RGMII_RXAUI:
- iface_ops[interface] = &iface_ops_bgx_rxaui;
- break;
- case CVMX_QLM_MODE_XLAUI:
- case CVMX_QLM_MODE_RGMII_XLAUI:
- iface_ops[interface] = &iface_ops_bgx_xlaui;
- break;
- case CVMX_QLM_MODE_XFI:
- case CVMX_QLM_MODE_XFI_1X2:
- case CVMX_QLM_MODE_RGMII_XFI:
- iface_ops[interface] = &iface_ops_bgx_xfi;
- break;
- case CVMX_QLM_MODE_10G_KR:
- case CVMX_QLM_MODE_10G_KR_1X2:
- case CVMX_QLM_MODE_RGMII_10G_KR:
- iface_ops[interface] = &iface_ops_bgx_10G_KR;
- break;
- case CVMX_QLM_MODE_40G_KR4:
- case CVMX_QLM_MODE_RGMII_40G_KR4:
- iface_ops[interface] = &iface_ops_bgx_40G_KR4;
- break;
- case CVMX_QLM_MODE_MIXED:
- iface_ops[interface] = &iface_ops_bgx_mixed;
- break;
- default:
- iface_ops[interface] = &iface_ops_dis;
- break;
- }
- } else if (interface == 3) { /* DPI */
- iface_ops[interface] = &iface_ops_npi;
- } else if (interface == 4) { /* LOOP */
- iface_ops[interface] = &iface_ops_loop;
- } else {
- iface_ops[interface] = &iface_ops_dis;
- }
- return iface_ops[interface]->mode;
- }
- /**
- * @INTERNAL
- * Return interface mode for CNF75XX.
- *
- * CNF75XX has a single BGX block, which is attached to two DLMs,
- * the first, GSER4 only supports SGMII mode, while the second,
- * GSER5 supports 1G/10G single late modes, i.e. SGMII, XFI, 10G-KR.
- * Each half-BGX is thus designated as a separate interface with two ports each.
- */
- static cvmx_helper_interface_mode_t __cvmx_get_mode_cnf75xx(int xiface)
- {
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- int interface = xi.interface;
- /* BGX0: SGMII (DLM4/DLM5)/XFI(DLM5) */
- if (interface < 1) {
- enum cvmx_qlm_mode qlm_mode;
- int qlm = cvmx_qlm_lmac(xiface, 0);
- if (qlm == -1) {
- iface_ops[interface] = &iface_ops_dis;
- return iface_ops[interface]->mode;
- }
- qlm_mode = cvmx_qlm_get_mode(qlm);
- switch (qlm_mode) {
- case CVMX_QLM_MODE_SGMII:
- case CVMX_QLM_MODE_SGMII_2X1:
- iface_ops[interface] = &iface_ops_bgx_sgmii;
- break;
- case CVMX_QLM_MODE_XFI_1X2:
- iface_ops[interface] = &iface_ops_bgx_xfi;
- break;
- case CVMX_QLM_MODE_10G_KR_1X2:
- iface_ops[interface] = &iface_ops_bgx_10G_KR;
- break;
- case CVMX_QLM_MODE_MIXED:
- iface_ops[interface] = &iface_ops_bgx_mixed;
- break;
- default:
- iface_ops[interface] = &iface_ops_dis;
- break;
- }
- } else if ((interface < 3) && OCTEON_IS_MODEL(OCTEON_CNF75XX)) {
- cvmx_sriox_status_reg_t sriox_status_reg;
- int srio_port = interface - 1;
- sriox_status_reg.u64 = csr_rd(CVMX_SRIOX_STATUS_REG(srio_port));
- if (sriox_status_reg.s.srio)
- iface_ops[interface] = &iface_ops_srio;
- else
- iface_ops[interface] = &iface_ops_dis;
- } else if (interface == 3) { /* DPI */
- iface_ops[interface] = &iface_ops_npi;
- } else if (interface == 4) { /* LOOP */
- iface_ops[interface] = &iface_ops_loop;
- } else {
- iface_ops[interface] = &iface_ops_dis;
- }
- return iface_ops[interface]->mode;
- }
- /**
- * @INTERNAL
- * Return interface mode for CN68xx.
- */
- static cvmx_helper_interface_mode_t __cvmx_get_mode_cn68xx(int interface)
- {
- union cvmx_mio_qlmx_cfg qlm_cfg;
- switch (interface) {
- case 0:
- qlm_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(0));
- /* QLM is disabled when QLM SPD is 15. */
- if (qlm_cfg.s.qlm_spd == 15)
- iface_ops[interface] = &iface_ops_dis;
- else if (qlm_cfg.s.qlm_cfg == 7)
- iface_ops[interface] = &iface_ops_rxaui;
- else if (qlm_cfg.s.qlm_cfg == 2)
- iface_ops[interface] = &iface_ops_sgmii;
- else if (qlm_cfg.s.qlm_cfg == 3)
- iface_ops[interface] = &iface_ops_xaui;
- else
- iface_ops[interface] = &iface_ops_dis;
- break;
- case 1:
- qlm_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(0));
- /* QLM is disabled when QLM SPD is 15. */
- if (qlm_cfg.s.qlm_spd == 15)
- iface_ops[interface] = &iface_ops_dis;
- else if (qlm_cfg.s.qlm_cfg == 7)
- iface_ops[interface] = &iface_ops_rxaui;
- else
- iface_ops[interface] = &iface_ops_dis;
- break;
- case 2:
- case 3:
- case 4:
- qlm_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(interface));
- /* QLM is disabled when QLM SPD is 15. */
- if (qlm_cfg.s.qlm_spd == 15)
- iface_ops[interface] = &iface_ops_dis;
- else if (qlm_cfg.s.qlm_cfg == 2)
- iface_ops[interface] = &iface_ops_sgmii;
- else if (qlm_cfg.s.qlm_cfg == 3)
- iface_ops[interface] = &iface_ops_xaui;
- else
- iface_ops[interface] = &iface_ops_dis;
- break;
- case 5:
- case 6:
- qlm_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(interface - 4));
- /* QLM is disabled when QLM SPD is 15. */
- if (qlm_cfg.s.qlm_spd == 15)
- iface_ops[interface] = &iface_ops_dis;
- else if (qlm_cfg.s.qlm_cfg == 1)
- iface_ops[interface] = &iface_ops_ilk;
- else
- iface_ops[interface] = &iface_ops_dis;
- break;
- case 7: {
- union cvmx_mio_qlmx_cfg qlm_cfg1;
- /* Check if PCIe0/PCIe1 is configured for PCIe */
- qlm_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(3));
- qlm_cfg1.u64 = csr_rd(CVMX_MIO_QLMX_CFG(1));
- /* QLM is disabled when QLM SPD is 15. */
- if ((qlm_cfg.s.qlm_spd != 15 && qlm_cfg.s.qlm_cfg == 0) ||
- (qlm_cfg1.s.qlm_spd != 15 && qlm_cfg1.s.qlm_cfg == 0))
- iface_ops[interface] = &iface_ops_npi;
- else
- iface_ops[interface] = &iface_ops_dis;
- } break;
- case 8:
- iface_ops[interface] = &iface_ops_loop;
- break;
- default:
- iface_ops[interface] = &iface_ops_dis;
- break;
- }
- return iface_ops[interface]->mode;
- }
- /**
- * @INTERNAL
- * Return interface mode for an Octeon II
- */
- static cvmx_helper_interface_mode_t __cvmx_get_mode_octeon2(int interface)
- {
- union cvmx_gmxx_inf_mode mode;
- if (OCTEON_IS_MODEL(OCTEON_CN68XX))
- return __cvmx_get_mode_cn68xx(interface);
- if (interface == 2) {
- iface_ops[interface] = &iface_ops_npi;
- } else if (interface == 3) {
- iface_ops[interface] = &iface_ops_loop;
- } else if ((OCTEON_IS_MODEL(OCTEON_CN63XX) &&
- (interface == 4 || interface == 5)) ||
- (OCTEON_IS_MODEL(OCTEON_CN66XX) && interface >= 4 &&
- interface <= 7)) {
- /* Only present in CN63XX & CN66XX Octeon model */
- union cvmx_sriox_status_reg sriox_status_reg;
- /* cn66xx pass1.0 has only 2 SRIO interfaces. */
- if ((interface == 5 || interface == 7) &&
- OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0)) {
- iface_ops[interface] = &iface_ops_dis;
- } else if (interface == 5 && OCTEON_IS_MODEL(OCTEON_CN66XX)) {
- /*
- * Later passes of cn66xx support SRIO0 - x4/x2/x1,
- * SRIO2 - x2/x1, SRIO3 - x1
- */
- iface_ops[interface] = &iface_ops_dis;
- } else {
- sriox_status_reg.u64 =
- csr_rd(CVMX_SRIOX_STATUS_REG(interface - 4));
- if (sriox_status_reg.s.srio)
- iface_ops[interface] = &iface_ops_srio;
- else
- iface_ops[interface] = &iface_ops_dis;
- }
- } else if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
- union cvmx_mio_qlmx_cfg mio_qlm_cfg;
- /* QLM2 is SGMII0 and QLM1 is SGMII1 */
- if (interface == 0) {
- mio_qlm_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(2));
- } else if (interface == 1) {
- mio_qlm_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(1));
- } else {
- iface_ops[interface] = &iface_ops_dis;
- return iface_ops[interface]->mode;
- }
- if (mio_qlm_cfg.s.qlm_spd == 15)
- iface_ops[interface] = &iface_ops_dis;
- else if (mio_qlm_cfg.s.qlm_cfg == 9)
- iface_ops[interface] = &iface_ops_sgmii;
- else if (mio_qlm_cfg.s.qlm_cfg == 11)
- iface_ops[interface] = &iface_ops_xaui;
- else
- iface_ops[interface] = &iface_ops_dis;
- } else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) {
- union cvmx_mio_qlmx_cfg qlm_cfg;
- if (interface == 0) {
- qlm_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(2));
- } else if (interface == 1) {
- qlm_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(0));
- } else {
- iface_ops[interface] = &iface_ops_dis;
- return iface_ops[interface]->mode;
- }
- if (qlm_cfg.s.qlm_spd == 15)
- iface_ops[interface] = &iface_ops_dis;
- else if (qlm_cfg.s.qlm_cfg == 2)
- iface_ops[interface] = &iface_ops_sgmii;
- else if (qlm_cfg.s.qlm_cfg == 3)
- iface_ops[interface] = &iface_ops_xaui;
- else
- iface_ops[interface] = &iface_ops_dis;
- } else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {
- if (interface == 0) {
- union cvmx_mio_qlmx_cfg qlm_cfg;
- qlm_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(0));
- if (qlm_cfg.s.qlm_cfg == 2)
- iface_ops[interface] = &iface_ops_sgmii;
- else
- iface_ops[interface] = &iface_ops_dis;
- } else {
- iface_ops[interface] = &iface_ops_dis;
- }
- } else if (interface == 1 && OCTEON_IS_MODEL(OCTEON_CN63XX)) {
- iface_ops[interface] = &iface_ops_dis;
- } else {
- mode.u64 = csr_rd(CVMX_GMXX_INF_MODE(interface));
- if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {
- switch (mode.cn63xx.mode) {
- case 0:
- iface_ops[interface] = &iface_ops_sgmii;
- break;
- case 1:
- iface_ops[interface] = &iface_ops_xaui;
- break;
- default:
- iface_ops[interface] = &iface_ops_dis;
- break;
- }
- } else {
- if (!mode.s.en)
- iface_ops[interface] = &iface_ops_dis;
- else if (mode.s.type)
- iface_ops[interface] = &iface_ops_gmii;
- else
- iface_ops[interface] = &iface_ops_rgmii;
- }
- }
- return iface_ops[interface]->mode;
- }
- /**
- * Get the operating mode of an interface. Depending on the Octeon
- * chip and configuration, this function returns an enumeration
- * of the type of packet I/O supported by an interface.
- *
- * @param xiface Interface to probe
- *
- * Return: Mode of the interface. Unknown or unsupported interfaces return
- * DISABLED.
- */
- cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int xiface)
- {
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- if (xi.interface < 0 ||
- xi.interface >= cvmx_helper_get_number_of_interfaces())
- return CVMX_HELPER_INTERFACE_MODE_DISABLED;
- /*
- * Check if the interface mode has been already cached. If it has,
- * simply return it. Otherwise, fall through the rest of the code to
- * determine the interface mode and cache it in iface_ops.
- */
- if (iface_node_ops[xi.node][xi.interface]) {
- cvmx_helper_interface_mode_t mode;
- mode = iface_node_ops[xi.node][xi.interface]->mode;
- return mode;
- }
- /*
- * OCTEON III models
- */
- if (OCTEON_IS_MODEL(OCTEON_CN70XX))
- return __cvmx_get_mode_cn70xx(xi.interface);
- if (OCTEON_IS_MODEL(OCTEON_CN78XX))
- return __cvmx_get_mode_cn78xx(xiface);
- if (OCTEON_IS_MODEL(OCTEON_CNF75XX)) {
- cvmx_helper_interface_mode_t mode;
- mode = __cvmx_get_mode_cnf75xx(xiface);
- return mode;
- }
- if (OCTEON_IS_MODEL(OCTEON_CN73XX)) {
- cvmx_helper_interface_mode_t mode;
- mode = __cvmx_get_mode_cn73xx(xiface);
- return mode;
- }
- /*
- * Octeon II models
- */
- if (OCTEON_IS_OCTEON2())
- return __cvmx_get_mode_octeon2(xi.interface);
- /*
- * Octeon and Octeon Plus models
- */
- if (xi.interface == 2) {
- iface_ops[xi.interface] = &iface_ops_npi;
- } else if (xi.interface == 3) {
- iface_ops[xi.interface] = &iface_ops_dis;
- } else {
- union cvmx_gmxx_inf_mode mode;
- mode.u64 = csr_rd(CVMX_GMXX_INF_MODE(xi.interface));
- if (!mode.s.en)
- iface_ops[xi.interface] = &iface_ops_dis;
- else if (mode.s.type)
- iface_ops[xi.interface] = &iface_ops_gmii;
- else
- iface_ops[xi.interface] = &iface_ops_rgmii;
- }
- return iface_ops[xi.interface]->mode;
- }
- /**
- * Determine the actual number of hardware ports connected to an
- * interface. It doesn't setup the ports or enable them.
- *
- * @param xiface Interface to enumerate
- *
- * Return: The number of ports on the interface, negative on failure
- */
- int cvmx_helper_interface_enumerate(int xiface)
- {
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- int result = 0;
- cvmx_helper_interface_get_mode(xiface);
- if (iface_node_ops[xi.node][xi.interface]->enumerate)
- result = iface_node_ops[xi.node][xi.interface]->enumerate(xiface);
- return result;
- }
- /**
- * This function probes an interface to determine the actual number of
- * hardware ports connected to it. It does some setup the ports but
- * doesn't enable them. The main goal here is to set the global
- * interface_port_count[interface] correctly. Final hardware setup of
- * the ports will be performed later.
- *
- * @param xiface Interface to probe
- *
- * Return: Zero on success, negative on failure
- */
- int cvmx_helper_interface_probe(int xiface)
- {
- /*
- * At this stage in the game we don't want packets to be
- * moving yet. The following probe calls should perform
- * hardware setup needed to determine port counts. Receive
- * must still be disabled.
- */
- int nports;
- int has_fcs;
- enum cvmx_pko_padding padding = CVMX_PKO_PADDING_NONE;
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- nports = -1;
- has_fcs = 0;
- cvmx_helper_interface_get_mode(xiface);
- if (iface_node_ops[xi.node][xi.interface]->probe)
- nports = iface_node_ops[xi.node][xi.interface]->probe(xiface);
- switch (iface_node_ops[xi.node][xi.interface]->mode) {
- /* These types don't support ports to IPD/PKO */
- case CVMX_HELPER_INTERFACE_MODE_DISABLED:
- case CVMX_HELPER_INTERFACE_MODE_PCIE:
- nports = 0;
- break;
- /* XAUI is a single high speed port */
- case CVMX_HELPER_INTERFACE_MODE_XAUI:
- case CVMX_HELPER_INTERFACE_MODE_RXAUI:
- case CVMX_HELPER_INTERFACE_MODE_XLAUI:
- case CVMX_HELPER_INTERFACE_MODE_XFI:
- case CVMX_HELPER_INTERFACE_MODE_10G_KR:
- case CVMX_HELPER_INTERFACE_MODE_40G_KR4:
- case CVMX_HELPER_INTERFACE_MODE_MIXED:
- has_fcs = 1;
- padding = CVMX_PKO_PADDING_60;
- break;
- /*
- * RGMII/GMII/MII are all treated about the same. Most
- * functions refer to these ports as RGMII.
- */
- case CVMX_HELPER_INTERFACE_MODE_RGMII:
- case CVMX_HELPER_INTERFACE_MODE_GMII:
- padding = CVMX_PKO_PADDING_60;
- break;
- /*
- * SPI4 can have 1-16 ports depending on the device at
- * the other end.
- */
- case CVMX_HELPER_INTERFACE_MODE_SPI:
- padding = CVMX_PKO_PADDING_60;
- break;
- /*
- * SGMII can have 1-4 ports depending on how many are
- * hooked up.
- */
- case CVMX_HELPER_INTERFACE_MODE_SGMII:
- case CVMX_HELPER_INTERFACE_MODE_QSGMII:
- padding = CVMX_PKO_PADDING_60;
- case CVMX_HELPER_INTERFACE_MODE_PICMG:
- has_fcs = 1;
- break;
- /* PCI target Network Packet Interface */
- case CVMX_HELPER_INTERFACE_MODE_NPI:
- break;
- /*
- * Special loopback only ports. These are not the same
- * as other ports in loopback mode.
- */
- case CVMX_HELPER_INTERFACE_MODE_LOOP:
- break;
- /* SRIO has 2^N ports, where N is number of interfaces */
- case CVMX_HELPER_INTERFACE_MODE_SRIO:
- break;
- case CVMX_HELPER_INTERFACE_MODE_ILK:
- padding = CVMX_PKO_PADDING_60;
- has_fcs = 1;
- break;
- case CVMX_HELPER_INTERFACE_MODE_AGL:
- has_fcs = 1;
- break;
- }
- if (nports == -1)
- return -1;
- if (!octeon_has_feature(OCTEON_FEATURE_PKND))
- has_fcs = 0;
- nports = __cvmx_helper_board_interface_probe(xiface, nports);
- __cvmx_helper_init_interface(xiface, nports, has_fcs, padding);
- /* Make sure all global variables propagate to other cores */
- CVMX_SYNCWS;
- return 0;
- }
- /**
- * @INTERNAL
- * Setup backpressure.
- *
- * Return: Zero on success, negative on failure
- */
- static int __cvmx_helper_global_setup_backpressure(int node)
- {
- cvmx_qos_proto_t qos_proto;
- cvmx_qos_pkt_mode_t qos_mode;
- int port, xipdport;
- unsigned int bpmask;
- int interface, xiface, ports;
- int num_interfaces = cvmx_helper_get_number_of_interfaces();
- if (cvmx_rgmii_backpressure_dis) {
- qos_proto = CVMX_QOS_PROTO_NONE;
- qos_mode = CVMX_QOS_PKT_MODE_DROP;
- } else {
- qos_proto = CVMX_QOS_PROTO_PAUSE;
- qos_mode = CVMX_QOS_PKT_MODE_HWONLY;
- }
- for (interface = 0; interface < num_interfaces; interface++) {
- xiface = cvmx_helper_node_interface_to_xiface(node, interface);
- ports = cvmx_helper_ports_on_interface(xiface);
- switch (cvmx_helper_interface_get_mode(xiface)) {
- case CVMX_HELPER_INTERFACE_MODE_DISABLED:
- case CVMX_HELPER_INTERFACE_MODE_PCIE:
- case CVMX_HELPER_INTERFACE_MODE_SRIO:
- case CVMX_HELPER_INTERFACE_MODE_ILK:
- case CVMX_HELPER_INTERFACE_MODE_NPI:
- case CVMX_HELPER_INTERFACE_MODE_PICMG:
- break;
- case CVMX_HELPER_INTERFACE_MODE_LOOP:
- case CVMX_HELPER_INTERFACE_MODE_XAUI:
- case CVMX_HELPER_INTERFACE_MODE_RXAUI:
- case CVMX_HELPER_INTERFACE_MODE_XLAUI:
- case CVMX_HELPER_INTERFACE_MODE_XFI:
- case CVMX_HELPER_INTERFACE_MODE_10G_KR:
- case CVMX_HELPER_INTERFACE_MODE_40G_KR4:
- bpmask = (cvmx_rgmii_backpressure_dis) ? 0xF : 0;
- if (octeon_has_feature(OCTEON_FEATURE_BGX)) {
- for (port = 0; port < ports; port++) {
- xipdport = cvmx_helper_get_ipd_port(xiface, port);
- cvmx_bgx_set_flowctl_mode(xipdport, qos_proto, qos_mode);
- }
- cvmx_bgx_set_backpressure_override(xiface, bpmask);
- }
- break;
- case CVMX_HELPER_INTERFACE_MODE_RGMII:
- case CVMX_HELPER_INTERFACE_MODE_GMII:
- case CVMX_HELPER_INTERFACE_MODE_SPI:
- case CVMX_HELPER_INTERFACE_MODE_SGMII:
- case CVMX_HELPER_INTERFACE_MODE_QSGMII:
- case CVMX_HELPER_INTERFACE_MODE_MIXED:
- bpmask = (cvmx_rgmii_backpressure_dis) ? 0xF : 0;
- if (octeon_has_feature(OCTEON_FEATURE_BGX)) {
- for (port = 0; port < ports; port++) {
- xipdport = cvmx_helper_get_ipd_port(xiface, port);
- cvmx_bgx_set_flowctl_mode(xipdport, qos_proto, qos_mode);
- }
- cvmx_bgx_set_backpressure_override(xiface, bpmask);
- } else {
- cvmx_gmx_set_backpressure_override(interface, bpmask);
- }
- break;
- case CVMX_HELPER_INTERFACE_MODE_AGL:
- bpmask = (cvmx_rgmii_backpressure_dis) ? 0x1 : 0;
- cvmx_agl_set_backpressure_override(interface, bpmask);
- break;
- }
- }
- return 0;
- }
- /**
- * @INTERNAL
- * Verify the per port IPD backpressure is aligned properly.
- * Return: Zero if working, non zero if misaligned
- */
- int __cvmx_helper_backpressure_is_misaligned(void)
- {
- return 0;
- }
- /**
- * @INTERNAL
- * Enable packet input/output from the hardware. This function is
- * called after all internal setup is complete and IPD is enabled.
- * After this function completes, packets will be accepted from the
- * hardware ports. PKO should still be disabled to make sure packets
- * aren't sent out partially setup hardware.
- *
- * @param xiface Interface to enable
- *
- * Return: Zero on success, negative on failure
- */
- int __cvmx_helper_packet_hardware_enable(int xiface)
- {
- int result = 0;
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- if (iface_node_ops[xi.node][xi.interface]->enable)
- result = iface_node_ops[xi.node][xi.interface]->enable(xiface);
- result |= __cvmx_helper_board_hardware_enable(xiface);
- return result;
- }
- int cvmx_helper_ipd_and_packet_input_enable(void)
- {
- return cvmx_helper_ipd_and_packet_input_enable_node(cvmx_get_node_num());
- }
- /**
- * Called after all internal packet IO paths are setup. This
- * function enables IPD/PIP and begins packet input and output.
- *
- * Return: Zero on success, negative on failure
- */
- int cvmx_helper_ipd_and_packet_input_enable_node(int node)
- {
- int num_interfaces;
- int interface;
- int num_ports;
- if (octeon_has_feature(OCTEON_FEATURE_PKI)) {
- cvmx_helper_pki_enable(node);
- } else {
- /* Enable IPD */
- cvmx_ipd_enable();
- }
- /*
- * Time to enable hardware ports packet input and output. Note
- * that at this point IPD/PIP must be fully functional and PKO
- * must be disabled .
- */
- num_interfaces = cvmx_helper_get_number_of_interfaces();
- for (interface = 0; interface < num_interfaces; interface++) {
- int xiface = cvmx_helper_node_interface_to_xiface(node, interface);
- num_ports = cvmx_helper_ports_on_interface(xiface);
- if (num_ports > 0)
- __cvmx_helper_packet_hardware_enable(xiface);
- }
- /* Finally enable PKO now that the entire path is up and running */
- /* enable pko */
- if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE))
- ; // cvmx_pko_enable_78xx(0); already enabled
- else
- cvmx_pko_enable();
- return 0;
- }
- /**
- * Initialize the PIP, IPD, and PKO hardware to support
- * simple priority based queues for the ethernet ports. Each
- * port is configured with a number of priority queues based
- * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower
- * priority than the previous.
- *
- * Return: Zero on success, non-zero on failure
- */
- int cvmx_helper_initialize_packet_io_node(unsigned int node)
- {
- int result = 0;
- int interface;
- int xiface;
- union cvmx_l2c_cfg l2c_cfg;
- union cvmx_smix_en smix_en;
- const int num_interfaces = cvmx_helper_get_number_of_interfaces();
- /*
- * Tell L2 to give the IOB statically higher priority compared
- * to the cores. This avoids conditions where IO blocks might
- * be starved under very high L2 loads.
- */
- if (OCTEON_IS_OCTEON2() || OCTEON_IS_OCTEON3()) {
- union cvmx_l2c_ctl l2c_ctl;
- l2c_ctl.u64 = csr_rd_node(node, CVMX_L2C_CTL);
- l2c_ctl.s.rsp_arb_mode = 1;
- l2c_ctl.s.xmc_arb_mode = 0;
- csr_wr_node(node, CVMX_L2C_CTL, l2c_ctl.u64);
- } else {
- l2c_cfg.u64 = csr_rd(CVMX_L2C_CFG);
- l2c_cfg.s.lrf_arb_mode = 0;
- l2c_cfg.s.rfb_arb_mode = 0;
- csr_wr(CVMX_L2C_CFG, l2c_cfg.u64);
- }
- int smi_inf;
- int i;
- /* Newer chips have more than one SMI/MDIO interface */
- if (OCTEON_IS_MODEL(OCTEON_CN68XX) || OCTEON_IS_MODEL(OCTEON_CN78XX))
- smi_inf = 4;
- else if (OCTEON_IS_MODEL(OCTEON_CN73XX) || OCTEON_IS_MODEL(OCTEON_CNF75XX))
- smi_inf = 2;
- else
- smi_inf = 2;
- for (i = 0; i < smi_inf; i++) {
- /* Make sure SMI/MDIO is enabled so we can query PHYs */
- smix_en.u64 = csr_rd_node(node, CVMX_SMIX_EN(i));
- if (!smix_en.s.en) {
- smix_en.s.en = 1;
- csr_wr_node(node, CVMX_SMIX_EN(i), smix_en.u64);
- }
- }
- //vinita_to_do ask it need to be modify for multinode
- __cvmx_helper_init_port_valid();
- for (interface = 0; interface < num_interfaces; interface++) {
- xiface = cvmx_helper_node_interface_to_xiface(node, interface);
- result |= cvmx_helper_interface_probe(xiface);
- }
- /* PKO3 init precedes that of interfaces */
- if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
- __cvmx_helper_init_port_config_data(node);
- result = cvmx_helper_pko3_init_global(node);
- } else {
- result = cvmx_helper_pko_init();
- }
- /* Errata SSO-29000, Disabling power saving SSO conditional clocking */
- if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
- cvmx_sso_ws_cfg_t cfg;
- cfg.u64 = csr_rd_node(node, CVMX_SSO_WS_CFG);
- cfg.s.sso_cclk_dis = 1;
- csr_wr_node(node, CVMX_SSO_WS_CFG, cfg.u64);
- }
- if (result < 0)
- return result;
- for (interface = 0; interface < num_interfaces; interface++) {
- xiface = cvmx_helper_node_interface_to_xiface(node, interface);
- /* Skip invalid/disabled interfaces */
- if (cvmx_helper_ports_on_interface(xiface) <= 0)
- continue;
- printf("Node %d Interface %d has %d ports (%s)\n", node, interface,
- cvmx_helper_ports_on_interface(xiface),
- cvmx_helper_interface_mode_to_string(
- cvmx_helper_interface_get_mode(xiface)));
- result |= __cvmx_helper_ipd_setup_interface(xiface);
- if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE))
- result |= cvmx_helper_pko3_init_interface(xiface);
- else
- result |= __cvmx_helper_interface_setup_pko(interface);
- }
- if (octeon_has_feature(OCTEON_FEATURE_PKI))
- result |= __cvmx_helper_pki_global_setup(node);
- else
- result |= __cvmx_helper_ipd_global_setup();
- /* Enable any flow control and backpressure */
- result |= __cvmx_helper_global_setup_backpressure(node);
- /* export app config if set */
- if (cvmx_export_app_config)
- result |= (*cvmx_export_app_config)();
- if (cvmx_ipd_cfg.ipd_enable && cvmx_pki_dflt_init[node])
- result |= cvmx_helper_ipd_and_packet_input_enable_node(node);
- return result;
- }
- /**
- * Initialize the PIP, IPD, and PKO hardware to support
- * simple priority based queues for the ethernet ports. Each
- * port is configured with a number of priority queues based
- * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower
- * priority than the previous.
- *
- * Return: Zero on success, non-zero on failure
- */
- int cvmx_helper_initialize_packet_io_global(void)
- {
- unsigned int node = cvmx_get_node_num();
- return cvmx_helper_initialize_packet_io_node(node);
- }
- /**
- * Does core local initialization for packet io
- *
- * Return: Zero on success, non-zero on failure
- */
- int cvmx_helper_initialize_packet_io_local(void)
- {
- if (octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE))
- __cvmx_pko3_dq_table_setup();
- return 0;
- }
- struct cvmx_buffer_list {
- struct cvmx_buffer_list *next;
- };
- /**
- * Disables the sending of flow control (pause) frames on the specified
- * GMX port(s).
- *
- * @param interface Which interface (0 or 1)
- * @param port_mask Mask (4bits) of which ports on the interface to disable
- * backpressure on.
- * 1 => disable backpressure
- * 0 => enable backpressure
- *
- * Return: 0 on success
- * -1 on error
- */
- int cvmx_gmx_set_backpressure_override(u32 interface, uint32_t port_mask)
- {
- union cvmx_gmxx_tx_ovr_bp gmxx_tx_ovr_bp;
- /* Check for valid arguments */
- if (port_mask & ~0xf || interface & ~0x1)
- return -1;
- if (interface >= CVMX_HELPER_MAX_GMX)
- return -1;
- gmxx_tx_ovr_bp.u64 = 0;
- gmxx_tx_ovr_bp.s.en = port_mask; /* Per port Enable back pressure override */
- gmxx_tx_ovr_bp.s.ign_full = port_mask; /* Ignore the RX FIFO full when computing BP */
- csr_wr(CVMX_GMXX_TX_OVR_BP(interface), gmxx_tx_ovr_bp.u64);
- return 0;
- }
- /**
- * Disables the sending of flow control (pause) frames on the specified
- * AGL (RGMII) port(s).
- *
- * @param interface Which interface (0 or 1)
- * @param port_mask Mask (4bits) of which ports on the interface to disable
- * backpressure on.
- * 1 => disable backpressure
- * 0 => enable backpressure
- *
- * Return: 0 on success
- * -1 on error
- */
- int cvmx_agl_set_backpressure_override(u32 interface, uint32_t port_mask)
- {
- union cvmx_agl_gmx_tx_ovr_bp agl_gmx_tx_ovr_bp;
- int port = cvmx_helper_agl_get_port(interface);
- if (port == -1)
- return -1;
- /* Check for valid arguments */
- agl_gmx_tx_ovr_bp.u64 = 0;
- /* Per port Enable back pressure override */
- agl_gmx_tx_ovr_bp.s.en = port_mask;
- /* Ignore the RX FIFO full when computing BP */
- agl_gmx_tx_ovr_bp.s.ign_full = port_mask;
- csr_wr(CVMX_GMXX_TX_OVR_BP(port), agl_gmx_tx_ovr_bp.u64);
- return 0;
- }
- /**
- * Helper function for global packet IO shutdown
- */
- int cvmx_helper_shutdown_packet_io_global_cn78xx(int node)
- {
- int num_interfaces = cvmx_helper_get_number_of_interfaces();
- cvmx_wqe_t *work;
- int interface;
- int result = 0;
- /* Shut down all interfaces and disable TX and RX on all ports */
- for (interface = 0; interface < num_interfaces; interface++) {
- int xiface = cvmx_helper_node_interface_to_xiface(node, interface);
- int index;
- int num_ports = cvmx_helper_ports_on_interface(xiface);
- if (num_ports > 4)
- num_ports = 4;
- cvmx_bgx_set_backpressure_override(xiface, 0);
- for (index = 0; index < num_ports; index++) {
- cvmx_helper_link_info_t link_info;
- if (!cvmx_helper_is_port_valid(xiface, index))
- continue;
- cvmx_helper_bgx_shutdown_port(xiface, index);
- /* Turn off link LEDs */
- link_info.u64 = 0;
- cvmx_helper_update_link_led(xiface, index, link_info);
- }
- }
- /* Stop input first */
- cvmx_helper_pki_shutdown(node);
- /* Retrieve all packets from the SSO and free them */
- result = 0;
- while ((work = cvmx_pow_work_request_sync(CVMX_POW_WAIT))) {
- cvmx_helper_free_pki_pkt_data(work);
- cvmx_wqe_pki_free(work);
- result++;
- }
- if (result > 0)
- debug("%s: Purged %d packets from SSO\n", __func__, result);
- /*
- * No need to wait for PKO queues to drain,
- * dq_close() drains the queues to NULL.
- */
- /* Shutdown PKO interfaces */
- for (interface = 0; interface < num_interfaces; interface++) {
- int xiface = cvmx_helper_node_interface_to_xiface(node, interface);
- cvmx_helper_pko3_shut_interface(xiface);
- }
- /* Disable MAC address filtering */
- for (interface = 0; interface < num_interfaces; interface++) {
- int xiface = cvmx_helper_node_interface_to_xiface(node, interface);
- switch (cvmx_helper_interface_get_mode(xiface)) {
- case CVMX_HELPER_INTERFACE_MODE_XAUI:
- case CVMX_HELPER_INTERFACE_MODE_RXAUI:
- case CVMX_HELPER_INTERFACE_MODE_XLAUI:
- case CVMX_HELPER_INTERFACE_MODE_XFI:
- case CVMX_HELPER_INTERFACE_MODE_10G_KR:
- case CVMX_HELPER_INTERFACE_MODE_40G_KR4:
- case CVMX_HELPER_INTERFACE_MODE_SGMII:
- case CVMX_HELPER_INTERFACE_MODE_MIXED: {
- int index;
- int num_ports = cvmx_helper_ports_on_interface(xiface);
- for (index = 0; index < num_ports; index++) {
- if (!cvmx_helper_is_port_valid(xiface, index))
- continue;
- /* Reset MAC filtering */
- cvmx_helper_bgx_rx_adr_ctl(node, interface, index, 0, 0, 0);
- }
- break;
- }
- default:
- break;
- }
- }
- for (interface = 0; interface < num_interfaces; interface++) {
- int index;
- int xiface = cvmx_helper_node_interface_to_xiface(node, interface);
- int num_ports = cvmx_helper_ports_on_interface(xiface);
- for (index = 0; index < num_ports; index++) {
- /* Doing this twice should clear it since no packets
- * can be received.
- */
- cvmx_update_rx_activity_led(xiface, index, false);
- cvmx_update_rx_activity_led(xiface, index, false);
- }
- }
- /* Shutdown the PKO unit */
- result = cvmx_helper_pko3_shutdown(node);
- /* Release interface structures */
- __cvmx_helper_shutdown_interfaces();
- return result;
- }
- /**
- * Undo the initialization performed in
- * cvmx_helper_initialize_packet_io_global(). After calling this routine and the
- * local version on each core, packet IO for Octeon will be disabled and placed
- * in the initial reset state. It will then be safe to call the initialize
- * later on. Note that this routine does not empty the FPA pools. It frees all
- * buffers used by the packet IO hardware to the FPA so a function emptying the
- * FPA after shutdown should find all packet buffers in the FPA.
- *
- * Return: Zero on success, negative on failure.
- */
- int cvmx_helper_shutdown_packet_io_global(void)
- {
- const int timeout = 5; /* Wait up to 5 seconds for timeouts */
- int result = 0;
- int num_interfaces = cvmx_helper_get_number_of_interfaces();
- int interface;
- int num_ports;
- int index;
- struct cvmx_buffer_list *pool0_buffers;
- struct cvmx_buffer_list *pool0_buffers_tail;
- cvmx_wqe_t *work;
- union cvmx_ipd_ctl_status ipd_ctl_status;
- int wqe_pool = (int)cvmx_fpa_get_wqe_pool();
- int node = cvmx_get_node_num();
- cvmx_pcsx_mrx_control_reg_t control_reg;
- if (octeon_has_feature(OCTEON_FEATURE_BGX))
- return cvmx_helper_shutdown_packet_io_global_cn78xx(node);
- /* Step 1: Disable all backpressure */
- for (interface = 0; interface < num_interfaces; interface++) {
- cvmx_helper_interface_mode_t mode =
- cvmx_helper_interface_get_mode(interface);
- if (mode == CVMX_HELPER_INTERFACE_MODE_AGL)
- cvmx_agl_set_backpressure_override(interface, 0x1);
- else if (mode != CVMX_HELPER_INTERFACE_MODE_DISABLED)
- cvmx_gmx_set_backpressure_override(interface, 0xf);
- }
- /* Step 2: Wait for the PKO queues to drain */
- result = __cvmx_helper_pko_drain();
- if (result < 0) {
- debug("WARNING: %s: Failed to drain some PKO queues\n",
- __func__);
- }
- /* Step 3: Disable TX and RX on all ports */
- for (interface = 0; interface < num_interfaces; interface++) {
- int xiface = cvmx_helper_node_interface_to_xiface(node,
- interface);
- switch (cvmx_helper_interface_get_mode(interface)) {
- case CVMX_HELPER_INTERFACE_MODE_DISABLED:
- case CVMX_HELPER_INTERFACE_MODE_PCIE:
- /* Not a packet interface */
- break;
- case CVMX_HELPER_INTERFACE_MODE_NPI:
- case CVMX_HELPER_INTERFACE_MODE_SRIO:
- case CVMX_HELPER_INTERFACE_MODE_ILK:
- /*
- * We don't handle the NPI/NPEI/SRIO packet
- * engines. The caller must know these are
- * idle.
- */
- break;
- case CVMX_HELPER_INTERFACE_MODE_LOOP:
- /*
- * Nothing needed. Once PKO is idle, the
- * loopback devices must be idle.
- */
- break;
- case CVMX_HELPER_INTERFACE_MODE_SPI:
- /*
- * SPI cannot be disabled from Octeon. It is
- * the responsibility of the caller to make
- * sure SPI is idle before doing shutdown.
- *
- * Fall through and do the same processing as
- * RGMII/GMII.
- */
- fallthrough;
- case CVMX_HELPER_INTERFACE_MODE_GMII:
- case CVMX_HELPER_INTERFACE_MODE_RGMII:
- /* Disable outermost RX at the ASX block */
- csr_wr(CVMX_ASXX_RX_PRT_EN(interface), 0);
- num_ports = cvmx_helper_ports_on_interface(xiface);
- if (num_ports > 4)
- num_ports = 4;
- for (index = 0; index < num_ports; index++) {
- union cvmx_gmxx_prtx_cfg gmx_cfg;
- if (!cvmx_helper_is_port_valid(interface, index))
- continue;
- gmx_cfg.u64 = csr_rd(CVMX_GMXX_PRTX_CFG(index, interface));
- gmx_cfg.s.en = 0;
- csr_wr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
- /* Poll the GMX state machine waiting for it to become idle */
- csr_wr(CVMX_NPI_DBG_SELECT,
- interface * 0x800 + index * 0x100 + 0x880);
- if (CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, union cvmx_dbg_data,
- data & 7, ==, 0, timeout * 1000000)) {
- debug("GMX RX path timeout waiting for idle\n");
- result = -1;
- }
- if (CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, union cvmx_dbg_data,
- data & 0xf, ==, 0, timeout * 1000000)) {
- debug("GMX TX path timeout waiting for idle\n");
- result = -1;
- }
- }
- /* Disable outermost TX at the ASX block */
- csr_wr(CVMX_ASXX_TX_PRT_EN(interface), 0);
- /* Disable interrupts for interface */
- csr_wr(CVMX_ASXX_INT_EN(interface), 0);
- csr_wr(CVMX_GMXX_TX_INT_EN(interface), 0);
- break;
- case CVMX_HELPER_INTERFACE_MODE_XAUI:
- case CVMX_HELPER_INTERFACE_MODE_RXAUI:
- case CVMX_HELPER_INTERFACE_MODE_SGMII:
- case CVMX_HELPER_INTERFACE_MODE_QSGMII:
- case CVMX_HELPER_INTERFACE_MODE_PICMG:
- num_ports = cvmx_helper_ports_on_interface(xiface);
- if (num_ports > 4)
- num_ports = 4;
- for (index = 0; index < num_ports; index++) {
- union cvmx_gmxx_prtx_cfg gmx_cfg;
- if (!cvmx_helper_is_port_valid(interface, index))
- continue;
- gmx_cfg.u64 = csr_rd(CVMX_GMXX_PRTX_CFG(index, interface));
- gmx_cfg.s.en = 0;
- csr_wr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
- if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface),
- union cvmx_gmxx_prtx_cfg, rx_idle, ==, 1,
- timeout * 1000000)) {
- debug("GMX RX path timeout waiting for idle\n");
- result = -1;
- }
- if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface),
- union cvmx_gmxx_prtx_cfg, tx_idle, ==, 1,
- timeout * 1000000)) {
- debug("GMX TX path timeout waiting for idle\n");
- result = -1;
- }
- /* For SGMII some PHYs require that the PCS
- * interface be powered down and reset (i.e.
- * Atheros/Qualcomm PHYs).
- */
- if (cvmx_helper_interface_get_mode(interface) ==
- CVMX_HELPER_INTERFACE_MODE_SGMII) {
- u64 reg;
- reg = CVMX_PCSX_MRX_CONTROL_REG(index, interface);
- /* Power down the interface */
- control_reg.u64 = csr_rd(reg);
- control_reg.s.pwr_dn = 1;
- csr_wr(reg, control_reg.u64);
- csr_rd(reg);
- }
- }
- break;
- case CVMX_HELPER_INTERFACE_MODE_AGL: {
- int port = cvmx_helper_agl_get_port(interface);
- union cvmx_agl_gmx_prtx_cfg agl_gmx_cfg;
- agl_gmx_cfg.u64 = csr_rd(CVMX_AGL_GMX_PRTX_CFG(port));
- agl_gmx_cfg.s.en = 0;
- csr_wr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_cfg.u64);
- if (CVMX_WAIT_FOR_FIELD64(CVMX_AGL_GMX_PRTX_CFG(port),
- union cvmx_agl_gmx_prtx_cfg, rx_idle, ==, 1,
- timeout * 1000000)) {
- debug("AGL RX path timeout waiting for idle\n");
- result = -1;
- }
- if (CVMX_WAIT_FOR_FIELD64(CVMX_AGL_GMX_PRTX_CFG(port),
- union cvmx_agl_gmx_prtx_cfg, tx_idle, ==, 1,
- timeout * 1000000)) {
- debug("AGL TX path timeout waiting for idle\n");
- result = -1;
- }
- } break;
- default:
- break;
- }
- }
- /* Step 4: Retrieve all packets from the POW and free them */
- while ((work = cvmx_pow_work_request_sync(CVMX_POW_WAIT))) {
- cvmx_helper_free_packet_data(work);
- cvmx_fpa1_free(work, wqe_pool, 0);
- }
- /* Step 5 */
- cvmx_ipd_disable();
- /*
- * Step 6: Drain all prefetched buffers from IPD/PIP. Note that IPD/PIP
- * have not been reset yet
- */
- __cvmx_ipd_free_ptr();
- /* Step 7: Free the PKO command buffers and put PKO in reset */
- cvmx_pko_shutdown();
- /* Step 8: Disable MAC address filtering */
- for (interface = 0; interface < num_interfaces; interface++) {
- int xiface = cvmx_helper_node_interface_to_xiface(node, interface);
- switch (cvmx_helper_interface_get_mode(interface)) {
- case CVMX_HELPER_INTERFACE_MODE_DISABLED:
- case CVMX_HELPER_INTERFACE_MODE_PCIE:
- case CVMX_HELPER_INTERFACE_MODE_SRIO:
- case CVMX_HELPER_INTERFACE_MODE_ILK:
- case CVMX_HELPER_INTERFACE_MODE_NPI:
- case CVMX_HELPER_INTERFACE_MODE_LOOP:
- break;
- case CVMX_HELPER_INTERFACE_MODE_XAUI:
- case CVMX_HELPER_INTERFACE_MODE_RXAUI:
- case CVMX_HELPER_INTERFACE_MODE_GMII:
- case CVMX_HELPER_INTERFACE_MODE_RGMII:
- case CVMX_HELPER_INTERFACE_MODE_SPI:
- case CVMX_HELPER_INTERFACE_MODE_SGMII:
- case CVMX_HELPER_INTERFACE_MODE_QSGMII:
- case CVMX_HELPER_INTERFACE_MODE_PICMG:
- num_ports = cvmx_helper_ports_on_interface(xiface);
- if (num_ports > 4)
- num_ports = 4;
- for (index = 0; index < num_ports; index++) {
- if (!cvmx_helper_is_port_valid(interface, index))
- continue;
- csr_wr(CVMX_GMXX_RXX_ADR_CTL(index, interface), 1);
- csr_wr(CVMX_GMXX_RXX_ADR_CAM_EN(index, interface), 0);
- csr_wr(CVMX_GMXX_RXX_ADR_CAM0(index, interface), 0);
- csr_wr(CVMX_GMXX_RXX_ADR_CAM1(index, interface), 0);
- csr_wr(CVMX_GMXX_RXX_ADR_CAM2(index, interface), 0);
- csr_wr(CVMX_GMXX_RXX_ADR_CAM3(index, interface), 0);
- csr_wr(CVMX_GMXX_RXX_ADR_CAM4(index, interface), 0);
- csr_wr(CVMX_GMXX_RXX_ADR_CAM5(index, interface), 0);
- }
- break;
- case CVMX_HELPER_INTERFACE_MODE_AGL: {
- int port = cvmx_helper_agl_get_port(interface);
- csr_wr(CVMX_AGL_GMX_RXX_ADR_CTL(port), 1);
- csr_wr(CVMX_AGL_GMX_RXX_ADR_CAM_EN(port), 0);
- csr_wr(CVMX_AGL_GMX_RXX_ADR_CAM0(port), 0);
- csr_wr(CVMX_AGL_GMX_RXX_ADR_CAM1(port), 0);
- csr_wr(CVMX_AGL_GMX_RXX_ADR_CAM2(port), 0);
- csr_wr(CVMX_AGL_GMX_RXX_ADR_CAM3(port), 0);
- csr_wr(CVMX_AGL_GMX_RXX_ADR_CAM4(port), 0);
- csr_wr(CVMX_AGL_GMX_RXX_ADR_CAM5(port), 0);
- } break;
- default:
- break;
- }
- }
- /*
- * Step 9: Drain all FPA buffers out of pool 0 before we reset
- * IPD/PIP. This is needed to keep IPD_QUE0_FREE_PAGE_CNT in
- * sync. We temporarily keep the buffers in the pool0_buffers
- * list.
- */
- pool0_buffers = NULL;
- pool0_buffers_tail = NULL;
- while (1) {
- struct cvmx_buffer_list *buffer = cvmx_fpa1_alloc(0);
- if (buffer) {
- buffer->next = NULL;
- if (!pool0_buffers)
- pool0_buffers = buffer;
- else
- pool0_buffers_tail->next = buffer;
- pool0_buffers_tail = buffer;
- } else {
- break;
- }
- }
- /* Step 10: Reset IPD and PIP */
- ipd_ctl_status.u64 = csr_rd(CVMX_IPD_CTL_STATUS);
- ipd_ctl_status.s.reset = 1;
- csr_wr(CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64);
- /* Make sure IPD has finished reset. */
- if (OCTEON_IS_OCTEON2() || OCTEON_IS_MODEL(OCTEON_CN70XX)) {
- if (CVMX_WAIT_FOR_FIELD64(CVMX_IPD_CTL_STATUS, union cvmx_ipd_ctl_status, rst_done,
- ==, 0, 1000)) {
- debug("IPD reset timeout waiting for idle\n");
- result = -1;
- }
- }
- /* Step 11: Restore the FPA buffers into pool 0 */
- while (pool0_buffers) {
- struct cvmx_buffer_list *n = pool0_buffers->next;
- cvmx_fpa1_free(pool0_buffers, 0, 0);
- pool0_buffers = n;
- }
- /* Step 12: Release interface structures */
- __cvmx_helper_shutdown_interfaces();
- return result;
- }
- /**
- * Does core local shutdown of packet io
- *
- * Return: Zero on success, non-zero on failure
- */
- int cvmx_helper_shutdown_packet_io_local(void)
- {
- /*
- * Currently there is nothing to do per core. This may change
- * in the future.
- */
- return 0;
- }
- /**
- * Auto configure an IPD/PKO port link state and speed. This
- * function basically does the equivalent of:
- * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port));
- *
- * @param xipd_port IPD/PKO port to auto configure
- *
- * Return: Link state after configure
- */
- cvmx_helper_link_info_t cvmx_helper_link_autoconf(int xipd_port)
- {
- cvmx_helper_link_info_t link_info;
- int xiface = cvmx_helper_get_interface_num(xipd_port);
- int index = cvmx_helper_get_interface_index_num(xipd_port);
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- int interface = xi.interface;
- if (interface == -1 || index == -1 || index >= cvmx_helper_ports_on_interface(xiface)) {
- link_info.u64 = 0;
- return link_info;
- }
- link_info = cvmx_helper_link_get(xipd_port);
- if (link_info.u64 == (__cvmx_helper_get_link_info(xiface, index)).u64)
- return link_info;
- if (!link_info.s.link_up)
- cvmx_error_disable_group(CVMX_ERROR_GROUP_ETHERNET, xipd_port);
- /* If we fail to set the link speed, port_link_info will not change */
- cvmx_helper_link_set(xipd_port, link_info);
- if (link_info.s.link_up)
- cvmx_error_enable_group(CVMX_ERROR_GROUP_ETHERNET, xipd_port);
- return link_info;
- }
- /**
- * Return the link state of an IPD/PKO port as returned by
- * auto negotiation. The result of this function may not match
- * Octeon's link config if auto negotiation has changed since
- * the last call to cvmx_helper_link_set().
- *
- * @param xipd_port IPD/PKO port to query
- *
- * Return: Link state
- */
- cvmx_helper_link_info_t cvmx_helper_link_get(int xipd_port)
- {
- cvmx_helper_link_info_t result;
- int xiface = cvmx_helper_get_interface_num(xipd_port);
- int index = cvmx_helper_get_interface_index_num(xipd_port);
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- struct cvmx_fdt_sfp_info *sfp_info;
- /*
- * The default result will be a down link unless the code
- * below changes it.
- */
- result.u64 = 0;
- if (__cvmx_helper_xiface_is_null(xiface) || index == -1 ||
- index >= cvmx_helper_ports_on_interface(xiface)) {
- return result;
- }
- if (iface_node_ops[xi.node][xi.interface]->link_get)
- result = iface_node_ops[xi.node][xi.interface]->link_get(xipd_port);
- if (xipd_port >= 0) {
- cvmx_helper_update_link_led(xiface, index, result);
- sfp_info = cvmx_helper_cfg_get_sfp_info(xiface, index);
- while (sfp_info) {
- if ((!result.s.link_up || (result.s.link_up && sfp_info->last_mod_abs)))
- cvmx_sfp_check_mod_abs(sfp_info, sfp_info->mod_abs_data);
- sfp_info = sfp_info->next_iface_sfp;
- }
- }
- return result;
- }
- /**
- * Configure an IPD/PKO port for the specified link state. This
- * function does not influence auto negotiation at the PHY level.
- * The passed link state must always match the link state returned
- * by cvmx_helper_link_get(). It is normally best to use
- * cvmx_helper_link_autoconf() instead.
- *
- * @param xipd_port IPD/PKO port to configure
- * @param link_info The new link state
- *
- * Return: Zero on success, negative on failure
- */
- int cvmx_helper_link_set(int xipd_port, cvmx_helper_link_info_t link_info)
- {
- int result = -1;
- int xiface = cvmx_helper_get_interface_num(xipd_port);
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- int index = cvmx_helper_get_interface_index_num(xipd_port);
- if (__cvmx_helper_xiface_is_null(xiface) || index == -1 ||
- index >= cvmx_helper_ports_on_interface(xiface))
- return -1;
- if (iface_node_ops[xi.node][xi.interface]->link_set)
- result = iface_node_ops[xi.node][xi.interface]->link_set(xipd_port, link_info);
- /*
- * Set the port_link_info here so that the link status is
- * updated no matter how cvmx_helper_link_set is called. We
- * don't change the value if link_set failed.
- */
- if (result == 0)
- __cvmx_helper_set_link_info(xiface, index, link_info);
- return result;
- }
- /**
- * Configure a port for internal and/or external loopback. Internal loopback
- * causes packets sent by the port to be received by Octeon. External loopback
- * causes packets received from the wire to sent out again.
- *
- * @param xipd_port IPD/PKO port to loopback.
- * @param enable_internal
- * Non zero if you want internal loopback
- * @param enable_external
- * Non zero if you want external loopback
- *
- * Return: Zero on success, negative on failure.
- */
- int cvmx_helper_configure_loopback(int xipd_port, int enable_internal, int enable_external)
- {
- int result = -1;
- int xiface = cvmx_helper_get_interface_num(xipd_port);
- struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
- int index = cvmx_helper_get_interface_index_num(xipd_port);
- if (index >= cvmx_helper_ports_on_interface(xiface))
- return -1;
- cvmx_helper_interface_get_mode(xiface);
- if (iface_node_ops[xi.node][xi.interface]->loopback)
- result = iface_node_ops[xi.node][xi.interface]->loopback(xipd_port, enable_internal,
- enable_external);
- return result;
- }
- void cvmx_helper_setup_simulator_io_buffer_counts(int node, int num_packet_buffers, int pko_buffers)
- {
- if (octeon_has_feature(OCTEON_FEATURE_PKI)) {
- cvmx_helper_pki_set_dflt_pool_buffer(node, num_packet_buffers);
- cvmx_helper_pki_set_dflt_aura_buffer(node, num_packet_buffers);
- } else {
- cvmx_ipd_set_packet_pool_buffer_count(num_packet_buffers);
- cvmx_ipd_set_wqe_pool_buffer_count(num_packet_buffers);
- cvmx_pko_set_cmd_queue_pool_buffer_count(pko_buffers);
- }
- }
- void *cvmx_helper_mem_alloc(int node, uint64_t alloc_size, uint64_t align)
- {
- s64 paddr;
- paddr = cvmx_bootmem_phy_alloc_range(alloc_size, align, cvmx_addr_on_node(node, 0ull),
- cvmx_addr_on_node(node, 0xffffffffff));
- if (paddr <= 0ll) {
- printf("ERROR: %s failed size %u\n", __func__, (unsigned int)alloc_size);
- return NULL;
- }
- return cvmx_phys_to_ptr(paddr);
- }
- void cvmx_helper_mem_free(void *buffer, uint64_t size)
- {
- __cvmx_bootmem_phy_free(cvmx_ptr_to_phys(buffer), size, 0);
- }
- int cvmx_helper_qos_config_init(cvmx_qos_proto_t qos_proto, cvmx_qos_config_t *qos_cfg)
- {
- int i;
- memset(qos_cfg, 0, sizeof(cvmx_qos_config_t));
- qos_cfg->pkt_mode = CVMX_QOS_PKT_MODE_HWONLY; /* Process PAUSEs in hardware only.*/
- qos_cfg->pool_mode = CVMX_QOS_POOL_PER_PORT; /* One Pool per BGX:LMAC.*/
- qos_cfg->pktbuf_size = 2048; /* Fit WQE + MTU in one buffer.*/
- qos_cfg->aura_size = 1024; /* 1K buffers typically enough for any application.*/
- qos_cfg->pko_pfc_en = 1; /* Enable PKO layout for PFC feature. */
- qos_cfg->vlan_num = 1; /* For Stacked VLAN, use 2nd VLAN in the QPG algorithm.*/
- qos_cfg->qos_proto = qos_proto; /* Use PFC flow-control protocol.*/
- qos_cfg->qpg_base = -1; /* QPG Table index is undefined.*/
- qos_cfg->p_time = 0x60; /* PAUSE packets time window.*/
- qos_cfg->p_interval = 0x10; /* PAUSE packets interval.*/
- for (i = 0; i < CVMX_QOS_NUM; i++) {
- qos_cfg->groups[i] = i; /* SSO Groups = 0...7 */
- qos_cfg->group_prio[i] = i; /* SSO Group priority = QOS. */
- qos_cfg->drop_thresh[i] = 99; /* 99% of the Aura size.*/
- qos_cfg->red_thresh[i] = 90; /* 90% of the Aura size.*/
- qos_cfg->bp_thresh[i] = 70; /* 70% of the Aura size.*/
- }
- return 0;
- }
- int cvmx_helper_qos_port_config_update(int xipdport, cvmx_qos_config_t *qos_cfg)
- {
- cvmx_user_static_pko_queue_config_t pkocfg;
- cvmx_xport_t xp = cvmx_helper_ipd_port_to_xport(xipdport);
- int xiface = cvmx_helper_get_interface_num(xipdport);
- cvmx_xiface_t xi = cvmx_helper_xiface_to_node_interface(xiface);
- /* Configure PKO port for PFC SQ layout: */
- cvmx_helper_pko_queue_config_get(xp.node, &pkocfg);
- pkocfg.pknd.pko_cfg_iface[xi.interface].pfc_enable = 1;
- cvmx_helper_pko_queue_config_set(xp.node, &pkocfg);
- return 0;
- }
- int cvmx_helper_qos_port_setup(int xipdport, cvmx_qos_config_t *qos_cfg)
- {
- const int channles = CVMX_QOS_NUM;
- int bufsize = qos_cfg->pktbuf_size;
- int aura_size = qos_cfg->aura_size;
- cvmx_xport_t xp = cvmx_helper_ipd_port_to_xport(xipdport);
- int node = xp.node;
- int ipdport = xp.port;
- int port = cvmx_helper_get_interface_index_num(xp.port);
- int xiface = cvmx_helper_get_interface_num(xipdport);
- cvmx_xiface_t xi = cvmx_helper_xiface_to_node_interface(xiface);
- cvmx_fpa3_pool_t gpool;
- cvmx_fpa3_gaura_t gaura;
- cvmx_bgxx_cmr_rx_ovr_bp_t ovrbp;
- struct cvmx_pki_qpg_config qpgcfg;
- struct cvmx_pki_style_config stcfg, stcfg_dflt;
- struct cvmx_pki_pkind_config pkcfg;
- int chan, bpid, group, qpg;
- int bpen, reden, dropen, passthr, dropthr, bpthr;
- int nbufs, pkind, style;
- char name[32];
- if (qos_cfg->pool_mode == CVMX_QOS_POOL_PER_PORT) {
- /* Allocate and setup packet Pool: */
- nbufs = aura_size * channles;
- sprintf(name, "QOS.P%d", ipdport);
- gpool = cvmx_fpa3_setup_fill_pool(node, -1 /*auto*/, name, bufsize, nbufs, NULL);
- if (!__cvmx_fpa3_pool_valid(gpool)) {
- printf("%s: Failed to setup FPA Pool\n", __func__);
- return -1;
- }
- for (chan = 0; chan < channles; chan++)
- qos_cfg->gpools[chan] = gpool;
- } else {
- printf("%s: Invalid pool_mode %d\n", __func__, qos_cfg->pool_mode);
- return -1;
- }
- /* Allocate QPG entries: */
- qos_cfg->qpg_base = cvmx_pki_qpg_entry_alloc(node, -1 /*auto*/, channles);
- if (qos_cfg->qpg_base < 0) {
- printf("%s: Failed to allocate QPG entry\n", __func__);
- return -1;
- }
- for (chan = 0; chan < channles; chan++) {
- /* Allocate and setup Aura, setup BP threshold: */
- gpool = qos_cfg->gpools[chan];
- sprintf(name, "QOS.A%d", ipdport + chan);
- gaura = cvmx_fpa3_set_aura_for_pool(gpool, -1 /*auto*/, name, bufsize, aura_size);
- if (!__cvmx_fpa3_aura_valid(gaura)) {
- printf("%s: Failed to setup FPA Aura for Channel %d\n", __func__, chan);
- return -1;
- }
- qos_cfg->gauras[chan] = gaura;
- bpen = 1;
- reden = 1;
- dropen = 1;
- dropthr = (qos_cfg->drop_thresh[chan] * 10 * aura_size) / 1000;
- passthr = (qos_cfg->red_thresh[chan] * 10 * aura_size) / 1000;
- bpthr = (qos_cfg->bp_thresh[chan] * 10 * aura_size) / 1000;
- cvmx_fpa3_setup_aura_qos(gaura, reden, passthr, dropthr, bpen, bpthr);
- cvmx_pki_enable_aura_qos(node, gaura.laura, reden, dropen, bpen);
- /* Allocate BPID, link Aura and Channel using BPID: */
- bpid = cvmx_pki_bpid_alloc(node, -1 /*auto*/);
- if (bpid < 0) {
- printf("%s: Failed to allocate BPID for channel %d\n",
- __func__, chan);
- return -1;
- }
- qos_cfg->bpids[chan] = bpid;
- cvmx_pki_write_aura_bpid(node, gaura.laura, bpid);
- cvmx_pki_write_channel_bpid(node, ipdport + chan, bpid);
- /* Setup QPG entries: */
- group = qos_cfg->groups[chan];
- qpg = qos_cfg->qpg_base + chan;
- cvmx_pki_read_qpg_entry(node, qpg, &qpgcfg);
- qpgcfg.port_add = chan;
- qpgcfg.aura_num = gaura.laura;
- qpgcfg.grp_ok = (node << CVMX_WQE_GRP_NODE_SHIFT) | group;
- qpgcfg.grp_bad = (node << CVMX_WQE_GRP_NODE_SHIFT) | group;
- qpgcfg.grptag_ok = (node << CVMX_WQE_GRP_NODE_SHIFT) | 0;
- qpgcfg.grptag_bad = (node << CVMX_WQE_GRP_NODE_SHIFT) | 0;
- cvmx_pki_write_qpg_entry(node, qpg, &qpgcfg);
- }
- /* Allocate and setup STYLE: */
- cvmx_helper_pki_get_dflt_style(node, &stcfg_dflt);
- style = cvmx_pki_style_alloc(node, -1 /*auto*/);
- cvmx_pki_read_style_config(node, style, CVMX_PKI_CLUSTER_ALL, &stcfg);
- stcfg.tag_cfg = stcfg_dflt.tag_cfg;
- stcfg.parm_cfg.tag_type = CVMX_POW_TAG_TYPE_ORDERED;
- stcfg.parm_cfg.qpg_qos = CVMX_PKI_QPG_QOS_VLAN;
- stcfg.parm_cfg.qpg_base = qos_cfg->qpg_base;
- stcfg.parm_cfg.qpg_port_msb = 0;
- stcfg.parm_cfg.qpg_port_sh = 0;
- stcfg.parm_cfg.qpg_dis_grptag = 1;
- stcfg.parm_cfg.fcs_strip = 1;
- stcfg.parm_cfg.mbuff_size = bufsize - 64; /* Do not use 100% of the buffer. */
- stcfg.parm_cfg.force_drop = 0;
- stcfg.parm_cfg.nodrop = 0;
- stcfg.parm_cfg.rawdrp = 0;
- stcfg.parm_cfg.cache_mode = 2; /* 1st buffer in L2 */
- stcfg.parm_cfg.wqe_vs = qos_cfg->vlan_num;
- cvmx_pki_write_style_config(node, style, CVMX_PKI_CLUSTER_ALL, &stcfg);
- /* Setup PKIND: */
- pkind = cvmx_helper_get_pknd(xiface, port);
- cvmx_pki_read_pkind_config(node, pkind, &pkcfg);
- pkcfg.cluster_grp = 0; /* OCTEON3 has only one cluster group = 0 */
- pkcfg.initial_style = style;
- pkcfg.initial_parse_mode = CVMX_PKI_PARSE_LA_TO_LG;
- cvmx_pki_write_pkind_config(node, pkind, &pkcfg);
- /* Setup parameters of the QOS packet and enable QOS flow-control: */
- cvmx_bgx_set_pause_pkt_param(xipdport, 0, 0x0180c2000001, 0x8808, qos_cfg->p_time,
- qos_cfg->p_interval);
- cvmx_bgx_set_flowctl_mode(xipdport, qos_cfg->qos_proto, qos_cfg->pkt_mode);
- /* Enable PKI channel backpressure in the BGX: */
- ovrbp.u64 = csr_rd_node(node, CVMX_BGXX_CMR_RX_OVR_BP(xi.interface));
- ovrbp.s.en &= ~(1 << port);
- ovrbp.s.ign_fifo_bp &= ~(1 << port);
- csr_wr_node(node, CVMX_BGXX_CMR_RX_OVR_BP(xi.interface), ovrbp.u64);
- return 0;
- }
- int cvmx_helper_qos_sso_setup(int xipdport, cvmx_qos_config_t *qos_cfg)
- {
- const int channels = CVMX_QOS_NUM;
- cvmx_sso_grpx_pri_t grppri;
- int chan, qos, group;
- cvmx_xport_t xp = cvmx_helper_ipd_port_to_xport(xipdport);
- int node = xp.node;
- for (chan = 0; chan < channels; chan++) {
- qos = cvmx_helper_qos2prio(chan);
- group = qos_cfg->groups[qos];
- grppri.u64 = csr_rd_node(node, CVMX_SSO_GRPX_PRI(group));
- grppri.s.pri = qos_cfg->group_prio[chan];
- csr_wr_node(node, CVMX_SSO_GRPX_PRI(group), grppri.u64);
- }
- return 0;
- }
- int cvmx_helper_get_chan_e_name(int chan, char *namebuf, int buflen)
- {
- int n, dpichans;
- if ((unsigned int)chan >= CVMX_PKO3_IPD_NUM_MAX) {
- printf("%s: Channel %d is out of range (0..4095)\n", __func__, chan);
- return -1;
- }
- if (OCTEON_IS_MODEL(OCTEON_CN78XX))
- dpichans = 64;
- else
- dpichans = 128;
- if (chan >= 0 && chan < 64)
- n = snprintf(namebuf, buflen, "LBK%d", chan);
- else if (chan >= 0x100 && chan < (0x100 + dpichans))
- n = snprintf(namebuf, buflen, "DPI%d", chan - 0x100);
- else if (chan == 0x200)
- n = snprintf(namebuf, buflen, "NQM");
- else if (chan >= 0x240 && chan < (0x240 + (1 << 1) + 2))
- n = snprintf(namebuf, buflen, "SRIO%d:%d", (chan - 0x240) >> 1,
- (chan - 0x240) & 0x1);
- else if (chan >= 0x400 && chan < (0x400 + (1 << 8) + 256))
- n = snprintf(namebuf, buflen, "ILK%d:%d", (chan - 0x400) >> 8,
- (chan - 0x400) & 0xFF);
- else if (chan >= 0x800 && chan < (0x800 + (5 << 8) + (3 << 4) + 16))
- n = snprintf(namebuf, buflen, "BGX%d:%d:%d", (chan - 0x800) >> 8,
- ((chan - 0x800) >> 4) & 0x3, (chan - 0x800) & 0xF);
- else
- n = snprintf(namebuf, buflen, "--");
- return n;
- }
- #ifdef CVMX_DUMP_DIAGNOSTICS
- void cvmx_helper_dump_for_diagnostics(int node)
- {
- if (!(OCTEON_IS_OCTEON3() && !OCTEON_IS_MODEL(OCTEON_CN70XX))) {
- printf("Diagnostics are not implemented for this model\n");
- return;
- }
- #ifdef CVMX_DUMP_GSER
- {
- int qlm, num_qlms;
- num_qlms = cvmx_qlm_get_num();
- for (qlm = 0; qlm < num_qlms; qlm++) {
- cvmx_dump_gser_config_node(node, qlm);
- cvmx_dump_gser_status_node(node, qlm);
- }
- }
- #endif
- #ifdef CVMX_DUMP_BGX
- {
- int bgx;
- for (bgx = 0; bgx < CVMX_HELPER_MAX_GMX; bgx++) {
- cvmx_dump_bgx_config_node(node, bgx);
- cvmx_dump_bgx_status_node(node, bgx);
- }
- }
- #endif
- #ifdef CVMX_DUMP_PKI
- cvmx_pki_config_dump(node);
- cvmx_pki_stats_dump(node);
- #endif
- #ifdef CVMX_DUMP_PKO
- cvmx_helper_pko3_config_dump(node);
- cvmx_helper_pko3_stats_dump(node);
- #endif
- #ifdef CVMX_DUMO_SSO
- cvmx_sso_config_dump(node);
- #endif
- }
- #endif
|