123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright (C) 2020 Marvell International Ltd.
- */
- #include <dm.h>
- #include <time.h>
- #include <linux/delay.h>
- #include <mach/cvmx-regs.h>
- #include <mach/octeon-model.h>
- #include <mach/cvmx-fuse.h>
- #include <mach/cvmx-qlm.h>
- #include <mach/octeon_qlm.h>
- #include <mach/cvmx-pcie.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>
- DECLARE_GLOBAL_DATA_PTR;
- /** 2.5GHz with 100MHz reference clock */
- #define R_2_5G_REFCLK100 0x0
- /** 5.0GHz with 100MHz reference clock */
- #define R_5G_REFCLK100 0x1
- /** 8.0GHz with 100MHz reference clock */
- #define R_8G_REFCLK100 0x2
- /** 1.25GHz with 156.25MHz reference clock */
- #define R_125G_REFCLK15625_KX 0x3
- /** 3.125Ghz with 156.25MHz reference clock (XAUI) */
- #define R_3125G_REFCLK15625_XAUI 0x4
- /** 10.3125GHz with 156.25MHz reference clock (XFI/XLAUI) */
- #define R_103125G_REFCLK15625_KR 0x5
- /** 1.25GHz with 156.25MHz reference clock (SGMII) */
- #define R_125G_REFCLK15625_SGMII 0x6
- /** 5GHz with 156.25MHz reference clock (QSGMII) */
- #define R_5G_REFCLK15625_QSGMII 0x7
- /** 6.25GHz with 156.25MHz reference clock (RXAUI/25G) */
- #define R_625G_REFCLK15625_RXAUI 0x8
- /** 2.5GHz with 125MHz reference clock */
- #define R_2_5G_REFCLK125 0x9
- /** 5GHz with 125MHz reference clock */
- #define R_5G_REFCLK125 0xa
- /** 8GHz with 125MHz reference clock */
- #define R_8G_REFCLK125 0xb
- /** Must be last, number of modes */
- #define R_NUM_LANE_MODES 0xc
- int cvmx_qlm_is_ref_clock(int qlm, int reference_mhz)
- {
- int ref_clock = cvmx_qlm_measure_clock(qlm);
- int mhz = ref_clock / 1000000;
- int range = reference_mhz / 10;
- return ((mhz >= reference_mhz - range) && (mhz <= reference_mhz + range));
- }
- static int __get_qlm_spd(int qlm, int speed)
- {
- int qlm_spd = 0xf;
- if (cvmx_qlm_is_ref_clock(qlm, 100)) {
- if (speed == 1250)
- qlm_spd = 0x3;
- else if (speed == 2500)
- qlm_spd = 0x2;
- else if (speed == 5000)
- qlm_spd = 0x0;
- else
- qlm_spd = 0xf;
- } else if (cvmx_qlm_is_ref_clock(qlm, 125)) {
- if (speed == 1250)
- qlm_spd = 0xa;
- else if (speed == 2500)
- qlm_spd = 0x9;
- else if (speed == 3125)
- qlm_spd = 0x8;
- else if (speed == 5000)
- qlm_spd = 0x6;
- else if (speed == 6250)
- qlm_spd = 0x5;
- else
- qlm_spd = 0xf;
- } else if (cvmx_qlm_is_ref_clock(qlm, 156)) {
- if (speed == 1250)
- qlm_spd = 0x4;
- else if (speed == 2500)
- qlm_spd = 0x7;
- else if (speed == 3125)
- qlm_spd = 0xe;
- else if (speed == 3750)
- qlm_spd = 0xd;
- else if (speed == 5000)
- qlm_spd = 0xb;
- else if (speed == 6250)
- qlm_spd = 0xc;
- else
- qlm_spd = 0xf;
- } else if (cvmx_qlm_is_ref_clock(qlm, 161)) {
- if (speed == 6316)
- qlm_spd = 0xc;
- }
- return qlm_spd;
- }
- static void __set_qlm_pcie_mode_61xx(int pcie_port, int root_complex)
- {
- int rc = root_complex ? 1 : 0;
- int ep = root_complex ? 0 : 1;
- cvmx_ciu_soft_prst1_t soft_prst1;
- cvmx_ciu_soft_prst_t soft_prst;
- cvmx_mio_rst_ctlx_t rst_ctl;
- if (pcie_port) {
- soft_prst1.u64 = csr_rd(CVMX_CIU_SOFT_PRST1);
- soft_prst1.s.soft_prst = 1;
- csr_wr(CVMX_CIU_SOFT_PRST1, soft_prst1.u64);
- } else {
- soft_prst.u64 = csr_rd(CVMX_CIU_SOFT_PRST);
- soft_prst.s.soft_prst = 1;
- csr_wr(CVMX_CIU_SOFT_PRST, soft_prst.u64);
- }
- rst_ctl.u64 = csr_rd(CVMX_MIO_RST_CTLX(pcie_port));
- rst_ctl.s.prst_link = rc;
- rst_ctl.s.rst_link = ep;
- rst_ctl.s.prtmode = rc;
- rst_ctl.s.rst_drv = rc;
- rst_ctl.s.rst_rcv = 0;
- rst_ctl.s.rst_chip = ep;
- csr_wr(CVMX_MIO_RST_CTLX(pcie_port), rst_ctl.u64);
- if (root_complex == 0) {
- if (pcie_port) {
- soft_prst1.u64 = csr_rd(CVMX_CIU_SOFT_PRST1);
- soft_prst1.s.soft_prst = 0;
- csr_wr(CVMX_CIU_SOFT_PRST1, soft_prst1.u64);
- } else {
- soft_prst.u64 = csr_rd(CVMX_CIU_SOFT_PRST);
- soft_prst.s.soft_prst = 0;
- csr_wr(CVMX_CIU_SOFT_PRST, soft_prst.u64);
- }
- }
- }
- /**
- * Configure qlm speed and mode. MIO_QLMX_CFG[speed,mode] are not set
- * for CN61XX.
- *
- * @param qlm The QLM to configure
- * @param speed The speed the QLM needs to be configured in Mhz.
- * @param mode The QLM to be configured as SGMII/XAUI/PCIe.
- * QLM 0: 0 = PCIe0 1X4, 1 = Reserved, 2 = SGMII1, 3 = XAUI1
- * QLM 1: 0 = PCIe1 1x2, 1 = PCIe(0/1) 2x1, 2 - 3 = Reserved
- * QLM 2: 0 - 1 = Reserved, 2 = SGMII0, 3 = XAUI0
- * @param rc Only used for PCIe, rc = 1 for root complex mode, 0 for EP
- * mode.
- * @param pcie2x1 Only used when QLM1 is in PCIE2x1 mode. The QLM_SPD has a
- * different value on how PEMx needs to be configured:
- * 0x0 - both PEM0 & PEM1 are in gen1 mode.
- * 0x1 - PEM0 in gen2 and PEM1 in gen1 mode.
- * 0x2 - PEM0 in gen1 and PEM1 in gen2 mode.
- * 0x3 - both PEM0 & PEM1 are in gen2 mode.
- * SPEED value is ignored in this mode. QLM_SPD is set based on
- * pcie2x1 value in this mode.
- *
- * Return: Return 0 on success or -1.
- */
- static int octeon_configure_qlm_cn61xx(int qlm, int speed, int mode, int rc, int pcie2x1)
- {
- cvmx_mio_qlmx_cfg_t qlm_cfg;
- /* The QLM speed varies for SGMII/XAUI and PCIe mode. And depends on
- * reference clock.
- */
- if (!OCTEON_IS_MODEL(OCTEON_CN61XX))
- return -1;
- if (qlm < 3) {
- qlm_cfg.u64 = csr_rd(CVMX_MIO_QLMX_CFG(qlm));
- } else {
- debug("WARNING: Invalid QLM(%d) passed\n", qlm);
- return -1;
- }
- switch (qlm) {
- /* SGMII/XAUI mode */
- case 2: {
- if (mode < 2) {
- qlm_cfg.s.qlm_spd = 0xf;
- break;
- }
- qlm_cfg.s.qlm_spd = __get_qlm_spd(qlm, speed);
- qlm_cfg.s.qlm_cfg = mode;
- break;
- }
- case 1: {
- if (mode == 1) { /* 2x1 mode */
- cvmx_mio_qlmx_cfg_t qlm0;
- /* When QLM0 is configured as PCIe(QLM_CFG=0x0)
- * and enabled (QLM_SPD != 0xf), QLM1 cannot be
- * configured as PCIe 2x1 mode (QLM_CFG=0x1)
- * and enabled (QLM_SPD != 0xf).
- */
- qlm0.u64 = csr_rd(CVMX_MIO_QLMX_CFG(0));
- if (qlm0.s.qlm_spd != 0xf && qlm0.s.qlm_cfg == 0) {
- debug("Invalid mode(%d) for QLM(%d) as QLM1 is PCIe mode\n",
- mode, qlm);
- qlm_cfg.s.qlm_spd = 0xf;
- break;
- }
- /* Set QLM_SPD based on reference clock and mode */
- if (cvmx_qlm_is_ref_clock(qlm, 100)) {
- if (pcie2x1 == 0x3)
- qlm_cfg.s.qlm_spd = 0x0;
- else if (pcie2x1 == 0x1)
- qlm_cfg.s.qlm_spd = 0x2;
- else if (pcie2x1 == 0x2)
- qlm_cfg.s.qlm_spd = 0x1;
- else if (pcie2x1 == 0x0)
- qlm_cfg.s.qlm_spd = 0x3;
- else
- qlm_cfg.s.qlm_spd = 0xf;
- } else if (cvmx_qlm_is_ref_clock(qlm, 125)) {
- if (pcie2x1 == 0x3)
- qlm_cfg.s.qlm_spd = 0x4;
- else if (pcie2x1 == 0x1)
- qlm_cfg.s.qlm_spd = 0x6;
- else if (pcie2x1 == 0x2)
- qlm_cfg.s.qlm_spd = 0x9;
- else if (pcie2x1 == 0x0)
- qlm_cfg.s.qlm_spd = 0x7;
- else
- qlm_cfg.s.qlm_spd = 0xf;
- }
- qlm_cfg.s.qlm_cfg = mode;
- csr_wr(CVMX_MIO_QLMX_CFG(qlm), qlm_cfg.u64);
- /* Set PCIe mode bits */
- __set_qlm_pcie_mode_61xx(0, rc);
- __set_qlm_pcie_mode_61xx(1, rc);
- return 0;
- } else if (mode > 1) {
- debug("Invalid mode(%d) for QLM(%d).\n", mode, qlm);
- qlm_cfg.s.qlm_spd = 0xf;
- break;
- }
- /* Set speed and mode for PCIe 1x2 mode. */
- if (cvmx_qlm_is_ref_clock(qlm, 100)) {
- if (speed == 5000)
- qlm_cfg.s.qlm_spd = 0x1;
- else if (speed == 2500)
- qlm_cfg.s.qlm_spd = 0x2;
- else
- qlm_cfg.s.qlm_spd = 0xf;
- } else if (cvmx_qlm_is_ref_clock(qlm, 125)) {
- if (speed == 5000)
- qlm_cfg.s.qlm_spd = 0x4;
- else if (speed == 2500)
- qlm_cfg.s.qlm_spd = 0x6;
- else
- qlm_cfg.s.qlm_spd = 0xf;
- } else {
- qlm_cfg.s.qlm_spd = 0xf;
- }
- qlm_cfg.s.qlm_cfg = mode;
- csr_wr(CVMX_MIO_QLMX_CFG(qlm), qlm_cfg.u64);
- /* Set PCIe mode bits */
- __set_qlm_pcie_mode_61xx(1, rc);
- return 0;
- }
- case 0: {
- /* QLM_CFG = 0x1 - Reserved */
- if (mode == 1) {
- qlm_cfg.s.qlm_spd = 0xf;
- break;
- }
- /* QLM_CFG = 0x0 - PCIe 1x4(PEM0) */
- if (mode == 0 && speed != 5000 && speed != 2500) {
- qlm_cfg.s.qlm_spd = 0xf;
- break;
- }
- /* Set speed and mode */
- qlm_cfg.s.qlm_spd = __get_qlm_spd(qlm, speed);
- qlm_cfg.s.qlm_cfg = mode;
- csr_wr(CVMX_MIO_QLMX_CFG(qlm), qlm_cfg.u64);
- /* Set PCIe mode bits */
- if (mode == 0)
- __set_qlm_pcie_mode_61xx(0, rc);
- return 0;
- }
- default:
- debug("WARNING: Invalid QLM(%d) passed\n", qlm);
- qlm_cfg.s.qlm_spd = 0xf;
- }
- csr_wr(CVMX_MIO_QLMX_CFG(qlm), qlm_cfg.u64);
- return 0;
- }
- /* qlm : DLM to configure
- * baud_mhz : speed of the DLM
- * ref_clk_sel : reference clock speed selection where:
- * 0: 100MHz
- * 1: 125MHz
- * 2: 156.25MHz
- *
- * ref_clk_input: reference clock input where:
- * 0: DLMC_REF_CLK0_[P,N]
- * 1: DLMC_REF_CLK1_[P,N]
- * 2: DLM0_REF_CLK_[P,N] (only valid for QLM 0)
- * is_sff7000_rxaui : boolean to indicate whether qlm is RXAUI on SFF7000
- */
- static int __dlm_setup_pll_cn70xx(int qlm, int baud_mhz, int ref_clk_sel, int ref_clk_input,
- int is_sff7000_rxaui)
- {
- cvmx_gserx_dlmx_test_powerdown_t dlmx_test_powerdown;
- cvmx_gserx_dlmx_ref_ssp_en_t dlmx_ref_ssp_en;
- cvmx_gserx_dlmx_mpll_en_t dlmx_mpll_en;
- cvmx_gserx_dlmx_phy_reset_t dlmx_phy_reset;
- cvmx_gserx_dlmx_tx_amplitude_t tx_amplitude;
- cvmx_gserx_dlmx_tx_preemph_t tx_preemph;
- cvmx_gserx_dlmx_rx_eq_t rx_eq;
- cvmx_gserx_dlmx_ref_clkdiv2_t ref_clkdiv2;
- cvmx_gserx_dlmx_mpll_multiplier_t mpll_multiplier;
- int gmx_ref_clk = 100;
- debug("%s(%d, %d, %d, %d, %d)\n", __func__, qlm, baud_mhz, ref_clk_sel, ref_clk_input,
- is_sff7000_rxaui);
- if (ref_clk_sel == 1)
- gmx_ref_clk = 125;
- else if (ref_clk_sel == 2)
- gmx_ref_clk = 156;
- if (qlm != 0 && ref_clk_input == 2) {
- printf("%s: Error: can only use reference clock inputs 0 or 1 for DLM %d\n",
- __func__, qlm);
- return -1;
- }
- /* Hardware defaults are invalid */
- tx_amplitude.u64 = csr_rd(CVMX_GSERX_DLMX_TX_AMPLITUDE(qlm, 0));
- if (is_sff7000_rxaui) {
- tx_amplitude.s.tx0_amplitude = 100;
- tx_amplitude.s.tx1_amplitude = 100;
- } else {
- tx_amplitude.s.tx0_amplitude = 65;
- tx_amplitude.s.tx1_amplitude = 65;
- }
- csr_wr(CVMX_GSERX_DLMX_TX_AMPLITUDE(qlm, 0), tx_amplitude.u64);
- tx_preemph.u64 = csr_rd(CVMX_GSERX_DLMX_TX_PREEMPH(qlm, 0));
- if (is_sff7000_rxaui) {
- tx_preemph.s.tx0_preemph = 0;
- tx_preemph.s.tx1_preemph = 0;
- } else {
- tx_preemph.s.tx0_preemph = 22;
- tx_preemph.s.tx1_preemph = 22;
- }
- csr_wr(CVMX_GSERX_DLMX_TX_PREEMPH(qlm, 0), tx_preemph.u64);
- rx_eq.u64 = csr_rd(CVMX_GSERX_DLMX_RX_EQ(qlm, 0));
- rx_eq.s.rx0_eq = 0;
- rx_eq.s.rx1_eq = 0;
- csr_wr(CVMX_GSERX_DLMX_RX_EQ(qlm, 0), rx_eq.u64);
- /* 1. Write GSER0_DLM0_REF_USE_PAD[REF_USE_PAD] = 1 (to select
- * reference-clock input)
- * The documentation for this register in the HRM is useless since
- * it says it selects between two different clocks that are not
- * documented anywhere. What it really does is select between
- * DLM0_REF_CLK_[P,N] if 1 and DLMC_REF_CLK[0,1]_[P,N] if 0.
- *
- * This register must be 0 for DLMs 1 and 2 and can only be 1 for
- * DLM 0.
- */
- csr_wr(CVMX_GSERX_DLMX_REF_USE_PAD(0, 0), ((ref_clk_input == 2) && (qlm == 0)) ? 1 : 0);
- /* Reference clock was already chosen before we got here */
- /* 2. Write GSER0_DLM0_REFCLK_SEL[REFCLK_SEL] if required for
- * reference-clock selection.
- *
- * If GSERX_DLMX_REF_USE_PAD is 1 then this register is ignored.
- */
- csr_wr(CVMX_GSERX_DLMX_REFCLK_SEL(0, 0), ref_clk_input & 1);
- /* Reference clock was already chosen before we got here */
- /* 3. If required, write GSER0_DLM0_REF_CLKDIV2[REF_CLKDIV2] (must be
- * set if reference clock > 100 MHz)
- */
- /* Apply workaround for Errata (G-20669) MPLL may not come up. */
- ref_clkdiv2.u64 = csr_rd(CVMX_GSERX_DLMX_REF_CLKDIV2(qlm, 0));
- if (gmx_ref_clk == 100)
- ref_clkdiv2.s.ref_clkdiv2 = 0;
- else
- ref_clkdiv2.s.ref_clkdiv2 = 1;
- csr_wr(CVMX_GSERX_DLMX_REF_CLKDIV2(qlm, 0), ref_clkdiv2.u64);
- /* 1. Ensure GSER(0)_DLM(0..2)_PHY_RESET[PHY_RESET] is set. */
- dlmx_phy_reset.u64 = csr_rd(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0));
- dlmx_phy_reset.s.phy_reset = 1;
- csr_wr(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0), dlmx_phy_reset.u64);
- /* 2. If SGMII or QSGMII or RXAUI (i.e. if DLM0) set
- * GSER(0)_DLM(0)_MPLL_EN[MPLL_EN] to one.
- */
- /* 7. Set GSER0_DLM0_MPLL_EN[MPLL_EN] = 1 */
- dlmx_mpll_en.u64 = csr_rd(CVMX_GSERX_DLMX_MPLL_EN(0, 0));
- dlmx_mpll_en.s.mpll_en = 1;
- csr_wr(CVMX_GSERX_DLMX_MPLL_EN(0, 0), dlmx_mpll_en.u64);
- /* 3. Set GSER(0)_DLM(0..2)_MPLL_MULTIPLIER[MPLL_MULTIPLIER]
- * to the value in the preceding table, which is different
- * than the desired setting prescribed by the HRM.
- */
- mpll_multiplier.u64 = csr_rd(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0));
- if (gmx_ref_clk == 100)
- mpll_multiplier.s.mpll_multiplier = 35;
- else if (gmx_ref_clk == 125)
- mpll_multiplier.s.mpll_multiplier = 56;
- else
- mpll_multiplier.s.mpll_multiplier = 45;
- debug("%s: Setting mpll multiplier to %u for DLM%d, baud %d, clock rate %uMHz\n",
- __func__, mpll_multiplier.s.mpll_multiplier, qlm, baud_mhz, gmx_ref_clk);
- csr_wr(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0), mpll_multiplier.u64);
- /* 5. Clear GSER0_DLM0_TEST_POWERDOWN[TEST_POWERDOWN] */
- dlmx_test_powerdown.u64 = csr_rd(CVMX_GSERX_DLMX_TEST_POWERDOWN(qlm, 0));
- dlmx_test_powerdown.s.test_powerdown = 0;
- csr_wr(CVMX_GSERX_DLMX_TEST_POWERDOWN(qlm, 0), dlmx_test_powerdown.u64);
- /* 6. Set GSER0_DLM0_REF_SSP_EN[REF_SSP_EN] = 1 */
- dlmx_ref_ssp_en.u64 = csr_rd(CVMX_GSERX_DLMX_REF_SSP_EN(qlm, 0));
- dlmx_ref_ssp_en.s.ref_ssp_en = 1;
- csr_wr(CVMX_GSERX_DLMX_REF_SSP_EN(0, 0), dlmx_ref_ssp_en.u64);
- /* 8. Clear GSER0_DLM0_PHY_RESET[PHY_RESET] = 0 */
- dlmx_phy_reset.u64 = csr_rd(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0));
- dlmx_phy_reset.s.phy_reset = 0;
- csr_wr(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0), dlmx_phy_reset.u64);
- /* 5. If PCIe or SATA (i.e. if DLM1 or DLM2), set both MPLL_EN
- * and MPLL_EN_OVRD to one in GSER(0)_PHY(1..2)_OVRD_IN_LO.
- */
- /* 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.
- */
- mpll_multiplier.u64 = csr_rd(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0));
- __cvmx_qlm_set_mult(qlm, baud_mhz, mpll_multiplier.s.mpll_multiplier);
- /* 9. Poll until the MPLL locks. Wait for
- * GSER0_DLM0_MPLL_STATUS[MPLL_STATUS] = 1
- */
- if (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_DLMX_MPLL_STATUS(qlm, 0),
- cvmx_gserx_dlmx_mpll_status_t, mpll_status, ==, 1, 10000)) {
- printf("PLL for DLM%d failed to lock\n", qlm);
- return -1;
- }
- return 0;
- }
- static int __dlm0_setup_tx_cn70xx(int speed, int ref_clk_sel)
- {
- int need0, need1;
- cvmx_gmxx_inf_mode_t mode0, mode1;
- cvmx_gserx_dlmx_tx_rate_t rate;
- cvmx_gserx_dlmx_tx_en_t en;
- cvmx_gserx_dlmx_tx_cm_en_t cm_en;
- cvmx_gserx_dlmx_tx_data_en_t data_en;
- cvmx_gserx_dlmx_tx_reset_t tx_reset;
- debug("%s(%d, %d)\n", __func__, speed, ref_clk_sel);
- mode0.u64 = csr_rd(CVMX_GMXX_INF_MODE(0));
- mode1.u64 = csr_rd(CVMX_GMXX_INF_MODE(1));
- /* Which lanes do we need? */
- need0 = (mode0.s.mode != CVMX_GMX_INF_MODE_DISABLED);
- need1 = (mode1.s.mode != CVMX_GMX_INF_MODE_DISABLED) ||
- (mode0.s.mode == CVMX_GMX_INF_MODE_RXAUI);
- /* 1. Write GSER0_DLM0_TX_RATE[TXn_RATE] (Set according to required
- * data rate (see Table 21-1).
- */
- rate.u64 = csr_rd(CVMX_GSERX_DLMX_TX_RATE(0, 0));
- debug("%s: speed: %d\n", __func__, speed);
- switch (speed) {
- case 1250:
- case 2500:
- switch (ref_clk_sel) {
- case OCTEON_QLM_REF_CLK_100MHZ: /* 100MHz */
- case OCTEON_QLM_REF_CLK_125MHZ: /* 125MHz */
- case OCTEON_QLM_REF_CLK_156MHZ: /* 156.25MHz */
- rate.s.tx0_rate = (mode0.s.mode == CVMX_GMX_INF_MODE_SGMII) ? 2 : 0;
- rate.s.tx1_rate = (mode1.s.mode == CVMX_GMX_INF_MODE_SGMII) ? 2 : 0;
- break;
- default:
- printf("Invalid reference clock select %d\n", ref_clk_sel);
- return -1;
- }
- break;
- case 3125:
- switch (ref_clk_sel) {
- case OCTEON_QLM_REF_CLK_125MHZ: /* 125MHz */
- case OCTEON_QLM_REF_CLK_156MHZ: /* 156.25MHz */
- rate.s.tx0_rate = (mode0.s.mode == CVMX_GMX_INF_MODE_SGMII) ? 1 : 0;
- rate.s.tx1_rate = (mode1.s.mode == CVMX_GMX_INF_MODE_SGMII) ? 1 : 0;
- break;
- default:
- printf("Invalid reference clock select %d\n", ref_clk_sel);
- return -1;
- }
- break;
- case 5000: /* QSGMII only */
- switch (ref_clk_sel) {
- case OCTEON_QLM_REF_CLK_100MHZ: /* 100MHz */
- rate.s.tx0_rate = 0;
- rate.s.tx1_rate = 0;
- break;
- case OCTEON_QLM_REF_CLK_125MHZ: /* 125MHz */
- case OCTEON_QLM_REF_CLK_156MHZ: /* 156.25MHz */
- rate.s.tx0_rate = 0;
- rate.s.tx1_rate = 0;
- break;
- default:
- printf("Invalid reference clock select %d\n", ref_clk_sel);
- return -1;
- }
- break;
- case 6250:
- switch (ref_clk_sel) {
- case OCTEON_QLM_REF_CLK_125MHZ: /* 125MHz */
- case OCTEON_QLM_REF_CLK_156MHZ: /* 156.25MHz */
- rate.s.tx0_rate = 0;
- rate.s.tx1_rate = 0;
- break;
- default:
- printf("Invalid reference clock select %d\n", ref_clk_sel);
- return -1;
- }
- break;
- default:
- printf("%s: Invalid rate %d\n", __func__, speed);
- return -1;
- }
- debug("%s: tx 0 rate: %d, tx 1 rate: %d\n", __func__, rate.s.tx0_rate, rate.s.tx1_rate);
- csr_wr(CVMX_GSERX_DLMX_TX_RATE(0, 0), rate.u64);
- /* 2. Set GSER0_DLM0_TX_EN[TXn_EN] = 1 */
- en.u64 = csr_rd(CVMX_GSERX_DLMX_TX_EN(0, 0));
- en.s.tx0_en = need0;
- en.s.tx1_en = need1;
- csr_wr(CVMX_GSERX_DLMX_TX_EN(0, 0), en.u64);
- /* 3 set GSER0_DLM0_TX_CM_EN[TXn_CM_EN] = 1 */
- cm_en.u64 = csr_rd(CVMX_GSERX_DLMX_TX_CM_EN(0, 0));
- cm_en.s.tx0_cm_en = need0;
- cm_en.s.tx1_cm_en = need1;
- csr_wr(CVMX_GSERX_DLMX_TX_CM_EN(0, 0), cm_en.u64);
- /* 4. Set GSER0_DLM0_TX_DATA_EN[TXn_DATA_EN] = 1 */
- data_en.u64 = csr_rd(CVMX_GSERX_DLMX_TX_DATA_EN(0, 0));
- data_en.s.tx0_data_en = need0;
- data_en.s.tx1_data_en = need1;
- csr_wr(CVMX_GSERX_DLMX_TX_DATA_EN(0, 0), data_en.u64);
- /* 5. Clear GSER0_DLM0_TX_RESET[TXn_DATA_EN] = 0 */
- tx_reset.u64 = csr_rd(CVMX_GSERX_DLMX_TX_RESET(0, 0));
- tx_reset.s.tx0_reset = !need0;
- tx_reset.s.tx1_reset = !need1;
- csr_wr(CVMX_GSERX_DLMX_TX_RESET(0, 0), tx_reset.u64);
- /* 6. Poll GSER0_DLM0_TX_STATUS[TXn_STATUS, TXn_CM_STATUS] until both
- * are set to 1. This prevents GMX from transmitting until the DLM
- * is ready.
- */
- if (need0) {
- if (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_DLMX_TX_STATUS(0, 0),
- cvmx_gserx_dlmx_tx_status_t, tx0_status, ==, 1, 10000)) {
- printf("DLM0 TX0 status fail\n");
- return -1;
- }
- if (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_DLMX_TX_STATUS(0, 0),
- cvmx_gserx_dlmx_tx_status_t, tx0_cm_status, ==, 1,
- 10000)) {
- printf("DLM0 TX0 CM status fail\n");
- return -1;
- }
- }
- if (need1) {
- if (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_DLMX_TX_STATUS(0, 0),
- cvmx_gserx_dlmx_tx_status_t, tx1_status, ==, 1, 10000)) {
- printf("DLM0 TX1 status fail\n");
- return -1;
- }
- if (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_DLMX_TX_STATUS(0, 0),
- cvmx_gserx_dlmx_tx_status_t, tx1_cm_status, ==, 1,
- 10000)) {
- printf("DLM0 TX1 CM status fail\n");
- return -1;
- }
- }
- return 0;
- }
- static int __dlm0_setup_rx_cn70xx(int speed, int ref_clk_sel)
- {
- int need0, need1;
- cvmx_gmxx_inf_mode_t mode0, mode1;
- cvmx_gserx_dlmx_rx_rate_t rate;
- cvmx_gserx_dlmx_rx_pll_en_t pll_en;
- cvmx_gserx_dlmx_rx_data_en_t data_en;
- cvmx_gserx_dlmx_rx_reset_t rx_reset;
- debug("%s(%d, %d)\n", __func__, speed, ref_clk_sel);
- mode0.u64 = csr_rd(CVMX_GMXX_INF_MODE(0));
- mode1.u64 = csr_rd(CVMX_GMXX_INF_MODE(1));
- /* Which lanes do we need? */
- need0 = (mode0.s.mode != CVMX_GMX_INF_MODE_DISABLED);
- need1 = (mode1.s.mode != CVMX_GMX_INF_MODE_DISABLED) ||
- (mode0.s.mode == CVMX_GMX_INF_MODE_RXAUI);
- /* 1. Write GSER0_DLM0_RX_RATE[RXn_RATE] (must match the
- * GER0_DLM0_TX_RATE[TXn_RATE] setting).
- */
- rate.u64 = csr_rd(CVMX_GSERX_DLMX_RX_RATE(0, 0));
- switch (speed) {
- case 1250:
- case 2500:
- switch (ref_clk_sel) {
- case OCTEON_QLM_REF_CLK_100MHZ: /* 100MHz */
- case OCTEON_QLM_REF_CLK_125MHZ: /* 125MHz */
- case OCTEON_QLM_REF_CLK_156MHZ: /* 156.25MHz */
- rate.s.rx0_rate = (mode0.s.mode == CVMX_GMX_INF_MODE_SGMII) ? 2 : 0;
- rate.s.rx1_rate = (mode1.s.mode == CVMX_GMX_INF_MODE_SGMII) ? 2 : 0;
- break;
- default:
- printf("Invalid reference clock select %d\n", ref_clk_sel);
- return -1;
- }
- break;
- case 3125:
- switch (ref_clk_sel) {
- case OCTEON_QLM_REF_CLK_125MHZ: /* 125MHz */
- case OCTEON_QLM_REF_CLK_156MHZ: /* 156.25MHz */
- rate.s.rx0_rate = (mode0.s.mode == CVMX_GMX_INF_MODE_SGMII) ? 1 : 0;
- rate.s.rx1_rate = (mode1.s.mode == CVMX_GMX_INF_MODE_SGMII) ? 1 : 0;
- break;
- default:
- printf("Invalid reference clock select %d\n", ref_clk_sel);
- return -1;
- }
- break;
- case 5000: /* QSGMII only */
- switch (ref_clk_sel) {
- case OCTEON_QLM_REF_CLK_100MHZ: /* 100MHz */
- case OCTEON_QLM_REF_CLK_125MHZ: /* 125MHz */
- case OCTEON_QLM_REF_CLK_156MHZ: /* 156.25MHz */
- rate.s.rx0_rate = 0;
- rate.s.rx1_rate = 0;
- break;
- default:
- printf("Invalid reference clock select %d\n", ref_clk_sel);
- return -1;
- }
- break;
- case 6250:
- switch (ref_clk_sel) {
- case OCTEON_QLM_REF_CLK_125MHZ: /* 125MHz */
- case OCTEON_QLM_REF_CLK_156MHZ: /* 156.25MHz */
- rate.s.rx0_rate = 0;
- rate.s.rx1_rate = 0;
- break;
- default:
- printf("Invalid reference clock select %d\n", ref_clk_sel);
- return -1;
- }
- break;
- default:
- printf("%s: Invalid rate %d\n", __func__, speed);
- return -1;
- }
- debug("%s: rx 0 rate: %d, rx 1 rate: %d\n", __func__, rate.s.rx0_rate, rate.s.rx1_rate);
- csr_wr(CVMX_GSERX_DLMX_RX_RATE(0, 0), rate.u64);
- /* 2. Set GSER0_DLM0_RX_PLL_EN[RXn_PLL_EN] = 1 */
- pll_en.u64 = csr_rd(CVMX_GSERX_DLMX_RX_PLL_EN(0, 0));
- pll_en.s.rx0_pll_en = need0;
- pll_en.s.rx1_pll_en = need1;
- csr_wr(CVMX_GSERX_DLMX_RX_PLL_EN(0, 0), pll_en.u64);
- /* 3. Set GSER0_DLM0_RX_DATA_EN[RXn_DATA_EN] = 1 */
- data_en.u64 = csr_rd(CVMX_GSERX_DLMX_RX_DATA_EN(0, 0));
- data_en.s.rx0_data_en = need0;
- data_en.s.rx1_data_en = need1;
- csr_wr(CVMX_GSERX_DLMX_RX_DATA_EN(0, 0), data_en.u64);
- /* 4. Clear GSER0_DLM0_RX_RESET[RXn_DATA_EN] = 0. Now the GMX can be
- * enabled: set GMX(0..1)_INF_MODE[EN] = 1
- */
- rx_reset.u64 = csr_rd(CVMX_GSERX_DLMX_RX_RESET(0, 0));
- rx_reset.s.rx0_reset = !need0;
- rx_reset.s.rx1_reset = !need1;
- csr_wr(CVMX_GSERX_DLMX_RX_RESET(0, 0), rx_reset.u64);
- return 0;
- }
- static int a_clk;
- static int __dlm2_sata_uctl_init_cn70xx(void)
- {
- cvmx_sata_uctl_ctl_t uctl_ctl;
- const int MAX_A_CLK = 333000000; /* Max of 333Mhz */
- int divisor, a_clkdiv;
- /* Wait for all voltages to reach a stable stable. Ensure the
- * reference clock is up and stable.
- */
- /* 2. Wait for IOI reset to deassert. */
- /* 3. Optionally program the GPIO CSRs for SATA features.
- * a. For cold-presence detect:
- * i. Select a GPIO for the input and program GPIO_SATA_CTL[sel]
- * for port0 and port1.
- * ii. Select a GPIO for the output and program
- * GPIO_BIT_CFG*[OUTPUT_SEL] for port0 and port1.
- * b. For mechanical-presence detect, select a GPIO for the input
- * and program GPIO_SATA_CTL[SEL] for port0/port1.
- * c. For LED activity, select a GPIO for the output and program
- * GPIO_BIT_CFG*[OUTPUT_SEL] for port0/port1.
- */
- /* 4. Assert all resets:
- * a. UAHC reset: SATA_UCTL_CTL[UAHC_RST] = 1
- * a. UCTL reset: SATA_UCTL_CTL[UCTL_RST] = 1
- */
- uctl_ctl.u64 = csr_rd(CVMX_SATA_UCTL_CTL);
- uctl_ctl.s.sata_uahc_rst = 1;
- uctl_ctl.s.sata_uctl_rst = 1;
- csr_wr(CVMX_SATA_UCTL_CTL, uctl_ctl.u64);
- /* 5. Configure the ACLK:
- * a. Reset the clock dividers: SATA_UCTL_CTL[A_CLKDIV_RST] = 1.
- * b. Select the ACLK frequency (400 MHz maximum)
- * i. SATA_UCTL_CTL[A_CLKDIV] = desired value,
- * ii. SATA_UCTL_CTL[A_CLKDIV_EN] = 1 to enable the ACLK,
- * c. Deassert the ACLK clock divider reset:
- * SATA_UCTL_CTL[A_CLKDIV_RST] = 0
- */
- uctl_ctl.u64 = csr_rd(CVMX_SATA_UCTL_CTL);
- uctl_ctl.s.a_clkdiv_rst = 1;
- csr_wr(CVMX_SATA_UCTL_CTL, uctl_ctl.u64);
- uctl_ctl.u64 = csr_rd(CVMX_SATA_UCTL_CTL);
- divisor = (gd->bus_clk + MAX_A_CLK - 1) / MAX_A_CLK;
- if (divisor <= 4) {
- a_clkdiv = divisor - 1;
- } else if (divisor <= 6) {
- a_clkdiv = 4;
- divisor = 6;
- } else if (divisor <= 8) {
- a_clkdiv = 5;
- divisor = 8;
- } else if (divisor <= 16) {
- a_clkdiv = 6;
- divisor = 16;
- } else if (divisor <= 24) {
- a_clkdiv = 7;
- divisor = 24;
- } else {
- printf("Unable to determine SATA clock divisor\n");
- return -1;
- }
- /* Calculate the final clock rate */
- a_clk = gd->bus_clk / divisor;
- uctl_ctl.s.a_clkdiv_sel = a_clkdiv;
- uctl_ctl.s.a_clk_en = 1;
- uctl_ctl.s.a_clk_byp_sel = 0;
- csr_wr(CVMX_SATA_UCTL_CTL, uctl_ctl.u64);
- uctl_ctl.u64 = csr_rd(CVMX_SATA_UCTL_CTL);
- uctl_ctl.s.a_clkdiv_rst = 0;
- csr_wr(CVMX_SATA_UCTL_CTL, uctl_ctl.u64);
- udelay(1);
- return 0;
- }
- static int __sata_dlm_init_cn70xx(int qlm, int baud_mhz, int ref_clk_sel, int ref_clk_input)
- {
- cvmx_gserx_sata_cfg_t sata_cfg;
- cvmx_gserx_sata_lane_rst_t sata_lane_rst;
- cvmx_gserx_dlmx_phy_reset_t dlmx_phy_reset;
- cvmx_gserx_dlmx_test_powerdown_t dlmx_test_powerdown;
- cvmx_gserx_sata_ref_ssp_en_t ref_ssp_en;
- cvmx_gserx_dlmx_mpll_multiplier_t mpll_multiplier;
- cvmx_gserx_dlmx_ref_clkdiv2_t ref_clkdiv2;
- cvmx_sata_uctl_shim_cfg_t shim_cfg;
- cvmx_gserx_phyx_ovrd_in_lo_t ovrd_in;
- cvmx_sata_uctl_ctl_t uctl_ctl;
- int sata_ref_clk;
- debug("%s(%d, %d, %d, %d)\n", __func__, qlm, baud_mhz, ref_clk_sel, ref_clk_input);
- switch (ref_clk_sel) {
- case 0:
- sata_ref_clk = 100;
- break;
- case 1:
- sata_ref_clk = 125;
- break;
- case 2:
- sata_ref_clk = 156;
- break;
- default:
- printf("%s: Invalid reference clock select %d for qlm %d\n", __func__,
- ref_clk_sel, qlm);
- return -1;
- }
- /* 5. Set GSERX0_SATA_CFG[SATA_EN] = 1 to configure DLM2 multiplexing.
- */
- sata_cfg.u64 = csr_rd(CVMX_GSERX_SATA_CFG(0));
- sata_cfg.s.sata_en = 1;
- csr_wr(CVMX_GSERX_SATA_CFG(0), sata_cfg.u64);
- /* 1. Write GSER(0)_DLM2_REFCLK_SEL[REFCLK_SEL] if required for
- * reference-clock selection.
- */
- if (ref_clk_input < 2) {
- csr_wr(CVMX_GSERX_DLMX_REFCLK_SEL(qlm, 0), ref_clk_input);
- csr_wr(CVMX_GSERX_DLMX_REF_USE_PAD(qlm, 0), 0);
- } else {
- csr_wr(CVMX_GSERX_DLMX_REF_USE_PAD(qlm, 0), 1);
- }
- ref_ssp_en.u64 = csr_rd(CVMX_GSERX_SATA_REF_SSP_EN(0));
- ref_ssp_en.s.ref_ssp_en = 1;
- csr_wr(CVMX_GSERX_SATA_REF_SSP_EN(0), ref_ssp_en.u64);
- /* Apply workaround for Errata (G-20669) MPLL may not come up. */
- /* Set REF_CLKDIV2 based on the Ref Clock */
- ref_clkdiv2.u64 = csr_rd(CVMX_GSERX_DLMX_REF_CLKDIV2(qlm, 0));
- if (sata_ref_clk == 100)
- ref_clkdiv2.s.ref_clkdiv2 = 0;
- else
- ref_clkdiv2.s.ref_clkdiv2 = 1;
- csr_wr(CVMX_GSERX_DLMX_REF_CLKDIV2(qlm, 0), ref_clkdiv2.u64);
- /* 1. Ensure GSER(0)_DLM(0..2)_PHY_RESET[PHY_RESET] is set. */
- dlmx_phy_reset.u64 = csr_rd(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0));
- dlmx_phy_reset.s.phy_reset = 1;
- csr_wr(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0), dlmx_phy_reset.u64);
- /* 2. If SGMII or QSGMII or RXAUI (i.e. if DLM0) set
- * GSER(0)_DLM(0)_MPLL_EN[MPLL_EN] to one.
- */
- /* 3. Set GSER(0)_DLM(0..2)_MPLL_MULTIPLIER[MPLL_MULTIPLIER]
- * to the value in the preceding table, which is different
- * than the desired setting prescribed by the HRM.
- */
- mpll_multiplier.u64 = csr_rd(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0));
- if (sata_ref_clk == 100)
- mpll_multiplier.s.mpll_multiplier = 35;
- else
- mpll_multiplier.s.mpll_multiplier = 56;
- csr_wr(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0), mpll_multiplier.u64);
- /* 3. Clear GSER0_DLM2_TEST_POWERDOWN[TEST_POWERDOWN] = 0 */
- dlmx_test_powerdown.u64 = csr_rd(CVMX_GSERX_DLMX_TEST_POWERDOWN(qlm, 0));
- dlmx_test_powerdown.s.test_powerdown = 0;
- csr_wr(CVMX_GSERX_DLMX_TEST_POWERDOWN(qlm, 0), dlmx_test_powerdown.u64);
- /* 4. Clear either/both lane0 and lane1 resets:
- * GSER0_SATA_LANE_RST[L0_RST, L1_RST] = 0.
- */
- sata_lane_rst.u64 = csr_rd(CVMX_GSERX_SATA_LANE_RST(0));
- sata_lane_rst.s.l0_rst = 0;
- sata_lane_rst.s.l1_rst = 0;
- csr_wr(CVMX_GSERX_SATA_LANE_RST(0), sata_lane_rst.u64);
- udelay(1);
- /* 5. Clear GSER0_DLM2_PHY_RESET */
- dlmx_phy_reset.u64 = csr_rd(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0));
- dlmx_phy_reset.s.phy_reset = 0;
- csr_wr(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0), dlmx_phy_reset.u64);
- /* 6. If PCIe or SATA (i.e. if DLM1 or DLM2), set both MPLL_EN
- * and MPLL_EN_OVRD to one in GSER(0)_PHY(1..2)_OVRD_IN_LO.
- */
- ovrd_in.u64 = csr_rd(CVMX_GSERX_PHYX_OVRD_IN_LO(qlm, 0));
- ovrd_in.s.mpll_en = 1;
- ovrd_in.s.mpll_en_ovrd = 1;
- csr_wr(CVMX_GSERX_PHYX_OVRD_IN_LO(qlm, 0), ovrd_in.u64);
- /* 7. 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.
- */
- mpll_multiplier.u64 = csr_rd(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0));
- if (sata_ref_clk == 100)
- mpll_multiplier.s.mpll_multiplier = 0x1e;
- else
- mpll_multiplier.s.mpll_multiplier = 0x30;
- csr_wr(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0), mpll_multiplier.u64);
- if (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_DLMX_MPLL_STATUS(qlm, 0),
- cvmx_gserx_dlmx_mpll_status_t, mpll_status, ==, 1, 10000)) {
- printf("ERROR: SATA MPLL failed to set\n");
- return -1;
- }
- if (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_DLMX_RX_STATUS(qlm, 0), cvmx_gserx_dlmx_rx_status_t,
- rx0_status, ==, 1, 10000)) {
- printf("ERROR: SATA RX0_STATUS failed to set\n");
- return -1;
- }
- if (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_DLMX_RX_STATUS(qlm, 0), cvmx_gserx_dlmx_rx_status_t,
- rx1_status, ==, 1, 10000)) {
- printf("ERROR: SATA RX1_STATUS failed to set\n");
- return -1;
- }
- /* 8. Deassert UCTL and UAHC resets:
- * a. SATA_UCTL_CTL[UCTL_RST] = 0
- * b. SATA_UCTL_CTL[UAHC_RST] = 0
- * c. Wait 10 ACLK cycles before accessing any ACLK-only registers.
- */
- uctl_ctl.u64 = csr_rd(CVMX_SATA_UCTL_CTL);
- uctl_ctl.s.sata_uctl_rst = 0;
- uctl_ctl.s.sata_uahc_rst = 0;
- csr_wr(CVMX_SATA_UCTL_CTL, uctl_ctl.u64);
- udelay(1);
- /* 9. Enable conditional SCLK of UCTL by writing
- * SATA_UCTL_CTL[CSCLK_EN] = 1
- */
- uctl_ctl.u64 = csr_rd(CVMX_SATA_UCTL_CTL);
- uctl_ctl.s.csclk_en = 1;
- csr_wr(CVMX_SATA_UCTL_CTL, uctl_ctl.u64);
- /* 10. Initialize UAHC as described in the AHCI Specification (UAHC_*
- * registers
- */
- /* set-up endian mode */
- shim_cfg.u64 = csr_rd(CVMX_SATA_UCTL_SHIM_CFG);
- shim_cfg.s.dma_endian_mode = 1;
- shim_cfg.s.csr_endian_mode = 3;
- csr_wr(CVMX_SATA_UCTL_SHIM_CFG, shim_cfg.u64);
- return 0;
- }
- /**
- * Initializes DLM 4 for SATA
- *
- * @param qlm Must be 4.
- * @param baud_mhz Baud rate for SATA
- * @param ref_clk_sel Selects the speed of the reference clock where:
- * 0 = 100MHz, 1 = 125MHz and 2 = 156.25MHz
- * @param ref_clk_input Reference clock input where 0 = external QLM clock,
- * 1 = qlmc_ref_clk0 and 2 = qlmc_ref_clk1
- */
- static int __sata_dlm_init_cn73xx(int qlm, int baud_mhz, int ref_clk_sel, int ref_clk_input)
- {
- cvmx_sata_uctl_shim_cfg_t shim_cfg;
- cvmx_gserx_refclk_sel_t refclk_sel;
- cvmx_gserx_phy_ctl_t phy_ctl;
- cvmx_gserx_rx_pwr_ctrl_p2_t pwr_ctrl_p2;
- cvmx_gserx_lanex_misc_cfg_0_t misc_cfg_0;
- cvmx_gserx_sata_lane_rst_t lane_rst;
- cvmx_gserx_pll_px_mode_0_t pmode_0;
- cvmx_gserx_pll_px_mode_1_t pmode_1;
- cvmx_gserx_lane_px_mode_0_t lane_pmode_0;
- cvmx_gserx_lane_px_mode_1_t lane_pmode_1;
- cvmx_gserx_cfg_t gserx_cfg;
- cvmx_sata_uctl_ctl_t uctl_ctl;
- int l;
- int i;
- /*
- * 1. Configure the SATA
- */
- /*
- * 2. Configure the QLM Reference clock
- * Set GSERX_REFCLK_SEL.COM_CLK_SEL to source reference clock
- * from the external clock mux.
- * GSERX_REFCLK_SEL.USE_COM1 to select qlmc_refclkn/p_1 or
- * leave clear to select qlmc_refclkn/p_0
- */
- refclk_sel.u64 = 0;
- if (ref_clk_input == 0) { /* External ref clock */
- refclk_sel.s.com_clk_sel = 0;
- refclk_sel.s.use_com1 = 0;
- } else if (ref_clk_input == 1) { /* Common reference clock 0 */
- refclk_sel.s.com_clk_sel = 1;
- refclk_sel.s.use_com1 = 0;
- } else { /* Common reference clock 1 */
- refclk_sel.s.com_clk_sel = 1;
- refclk_sel.s.use_com1 = 1;
- }
- if (ref_clk_sel != 0) {
- printf("Wrong reference clock selected for QLM4\n");
- return -1;
- }
- csr_wr(CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);
- /* Reset the QLM after changing the reference clock */
- phy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(qlm));
- phy_ctl.s.phy_reset = 1;
- csr_wr(CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);
- udelay(1);
- /*
- * 3. Configure the QLM for SATA mode set GSERX_CFG.SATA
- */
- gserx_cfg.u64 = 0;
- gserx_cfg.s.sata = 1;
- csr_wr(CVMX_GSERX_CFG(qlm), gserx_cfg.u64);
- /*
- * 12. Clear the appropriate lane resets
- * clear GSERX_SATA_LANE_RST.LX_RST where X is the lane number 0-1.
- */
- lane_rst.u64 = csr_rd(CVMX_GSERX_SATA_LANE_RST(qlm));
- lane_rst.s.l0_rst = 0;
- lane_rst.s.l1_rst = 0;
- csr_wr(CVMX_GSERX_SATA_LANE_RST(qlm), lane_rst.u64);
- csr_rd(CVMX_GSERX_SATA_LANE_RST(qlm));
- udelay(1);
- /*
- * 4. Take the PHY out of reset
- * Write GSERX_PHY_CTL.PHY_RESET to a zero
- */
- phy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(qlm));
- phy_ctl.s.phy_reset = 0;
- csr_wr(CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);
- /* Wait for reset to complete and the PLL to lock */
- /* PCIe mode doesn't become ready until the PEM block attempts to bring
- * the interface up. Skip this check for PCIe
- */
- if (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_QLM_STAT(qlm), cvmx_gserx_qlm_stat_t,
- rst_rdy, ==, 1, 10000)) {
- printf("QLM%d: Timeout waiting for GSERX_QLM_STAT[rst_rdy]\n", qlm);
- return -1;
- }
- /* Workaround for errata GSER-30310: SATA HDD Not Ready due to
- * PHY SDLL/LDLL lockup at 3GHz
- */
- for (i = 0; i < 2; i++) {
- cvmx_gserx_slicex_pcie1_mode_t pcie1;
- cvmx_gserx_slicex_pcie2_mode_t pcie2;
- cvmx_gserx_slicex_pcie3_mode_t pcie3;
- pcie1.u64 = csr_rd(CVMX_GSERX_SLICEX_PCIE1_MODE(i, qlm));
- pcie1.s.rx_pi_bwsel = 1;
- pcie1.s.rx_ldll_bwsel = 1;
- pcie1.s.rx_sdll_bwsel = 1;
- csr_wr(CVMX_GSERX_SLICEX_PCIE1_MODE(i, qlm), pcie1.u64);
- pcie2.u64 = csr_rd(CVMX_GSERX_SLICEX_PCIE2_MODE(i, qlm));
- pcie2.s.rx_pi_bwsel = 1;
- pcie2.s.rx_ldll_bwsel = 1;
- pcie2.s.rx_sdll_bwsel = 1;
- csr_wr(CVMX_GSERX_SLICEX_PCIE2_MODE(i, qlm), pcie2.u64);
- pcie3.u64 = csr_rd(CVMX_GSERX_SLICEX_PCIE3_MODE(i, qlm));
- pcie3.s.rx_pi_bwsel = 1;
- pcie3.s.rx_ldll_bwsel = 1;
- pcie3.s.rx_sdll_bwsel = 1;
- csr_wr(CVMX_GSERX_SLICEX_PCIE3_MODE(i, qlm), pcie3.u64);
- }
- /*
- * 7. Change P2 termination
- * Clear GSERX_RX_PWR_CTRL_P2.P2_RX_SUBBLK_PD[0] (Termination)
- */
- pwr_ctrl_p2.u64 = csr_rd(CVMX_GSERX_RX_PWR_CTRL_P2(qlm));
- pwr_ctrl_p2.s.p2_rx_subblk_pd &= 0x1e;
- csr_wr(CVMX_GSERX_RX_PWR_CTRL_P2(qlm), pwr_ctrl_p2.u64);
- /*
- * 8. Modify the Electrical IDLE Detect on delay
- * Change GSERX_LANE(0..3)_MISC_CFG_0.EIE_DET_STL_ON_TIME to a 0x4
- */
- for (i = 0; i < 2; i++) {
- misc_cfg_0.u64 = csr_rd(CVMX_GSERX_LANEX_MISC_CFG_0(i, qlm));
- misc_cfg_0.s.eie_det_stl_on_time = 4;
- csr_wr(CVMX_GSERX_LANEX_MISC_CFG_0(i, qlm), misc_cfg_0.u64);
- }
- /*
- * 9. Modify the PLL and Lane Protocol Mode registers to configure
- * the PHY for SATA.
- * (Configure all 3 PLLs, doesn't matter what speed it is configured)
- */
- /* Errata (GSER-26724) SATA never indicates GSER QLM_STAT[RST_RDY]
- * We program PLL_PX_MODE_0 last due to this errata
- */
- for (l = 0; l < 3; l++) {
- pmode_1.u64 = csr_rd(CVMX_GSERX_PLL_PX_MODE_1(l, qlm));
- lane_pmode_0.u64 = csr_rd(CVMX_GSERX_LANE_PX_MODE_0(l, qlm));
- lane_pmode_1.u64 = csr_rd(CVMX_GSERX_LANE_PX_MODE_1(l, qlm));
- pmode_1.s.pll_cpadj = 0x2;
- pmode_1.s.pll_opr = 0x0;
- pmode_1.s.pll_div = 0x1e;
- pmode_1.s.pll_pcie3en = 0x0;
- pmode_1.s.pll_16p5en = 0x0;
- lane_pmode_0.s.ctle = 0x0;
- lane_pmode_0.s.pcie = 0x0;
- lane_pmode_0.s.tx_ldiv = 0x0;
- lane_pmode_0.s.srate = 0;
- lane_pmode_0.s.tx_mode = 0x3;
- lane_pmode_0.s.rx_mode = 0x3;
- lane_pmode_1.s.vma_mm = 1;
- lane_pmode_1.s.vma_fine_cfg_sel = 0;
- lane_pmode_1.s.cdr_fgain = 0xa;
- lane_pmode_1.s.ph_acc_adj = 0x15;
- if (l == R_2_5G_REFCLK100)
- lane_pmode_0.s.rx_ldiv = 0x2;
- else if (l == R_5G_REFCLK100)
- lane_pmode_0.s.rx_ldiv = 0x1;
- else
- lane_pmode_0.s.rx_ldiv = 0x0;
- csr_wr(CVMX_GSERX_PLL_PX_MODE_1(l, qlm), pmode_1.u64);
- csr_wr(CVMX_GSERX_LANE_PX_MODE_0(l, qlm), lane_pmode_0.u64);
- csr_wr(CVMX_GSERX_LANE_PX_MODE_1(l, qlm), lane_pmode_1.u64);
- }
- for (l = 0; l < 3; l++) {
- pmode_0.u64 = csr_rd(CVMX_GSERX_PLL_PX_MODE_0(l, qlm));
- pmode_0.s.pll_icp = 0x1;
- pmode_0.s.pll_rloop = 0x3;
- pmode_0.s.pll_pcs_div = 0x5;
- csr_wr(CVMX_GSERX_PLL_PX_MODE_0(l, qlm), pmode_0.u64);
- }
- for (i = 0; i < 2; i++) {
- cvmx_gserx_slicex_rx_sdll_ctrl_t rx_sdll;
- rx_sdll.u64 = csr_rd(CVMX_GSERX_SLICEX_RX_SDLL_CTRL(i, qlm));
- rx_sdll.s.pcs_sds_oob_clk_ctrl = 2;
- rx_sdll.s.pcs_sds_rx_sdll_tune = 0;
- rx_sdll.s.pcs_sds_rx_sdll_swsel = 0;
- csr_wr(CVMX_GSERX_SLICEX_RX_SDLL_CTRL(i, qlm), rx_sdll.u64);
- }
- for (i = 0; i < 2; i++) {
- cvmx_gserx_lanex_misc_cfg_0_t misc_cfg;
- misc_cfg.u64 = csr_rd(CVMX_GSERX_LANEX_MISC_CFG_0(i, qlm));
- misc_cfg.s.use_pma_polarity = 0;
- misc_cfg.s.cfg_pcs_loopback = 0;
- misc_cfg.s.pcs_tx_mode_ovrrd_en = 0;
- misc_cfg.s.pcs_rx_mode_ovrrd_en = 0;
- misc_cfg.s.cfg_eie_det_cnt = 0;
- misc_cfg.s.eie_det_stl_on_time = 4;
- misc_cfg.s.eie_det_stl_off_time = 0;
- misc_cfg.s.tx_bit_order = 1;
- misc_cfg.s.rx_bit_order = 1;
- csr_wr(CVMX_GSERX_LANEX_MISC_CFG_0(i, qlm), misc_cfg.u64);
- }
- /* Wait for reset to complete and the PLL to lock */
- /* PCIe mode doesn't become ready until the PEM block attempts to bring
- * the interface up. Skip this check for PCIe
- */
- if (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_QLM_STAT(qlm), cvmx_gserx_qlm_stat_t,
- rst_rdy, ==, 1, 10000)) {
- printf("QLM%d: Timeout waiting for GSERX_QLM_STAT[rst_rdy]\n", qlm);
- return -1;
- }
- /* Poll GSERX_SATA_STATUS for P0_RDY = 1 */
- if (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_SATA_STATUS(qlm), cvmx_gserx_sata_status_t,
- p0_rdy, ==, 1, 10000)) {
- printf("QLM4: Timeout waiting for GSERX_SATA_STATUS[p0_rdy]\n");
- return -1;
- }
- /* Poll GSERX_SATA_STATUS for P1_RDY = 1 */
- if (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_SATA_STATUS(qlm), cvmx_gserx_sata_status_t,
- p1_rdy, ==, 1, 10000)) {
- printf("QLM4: Timeout waiting for GSERX_SATA_STATUS[p1_rdy]\n");
- return -1;
- }
- udelay(2000);
- /* 6. Deassert UCTL and UAHC resets:
- * a. SATA_UCTL_CTL[UCTL_RST] = 0
- * b. SATA_UCTL_CTL[UAHC_RST] = 0
- * c. Wait 10 ACLK cycles before accessing any ACLK-only registers.
- */
- uctl_ctl.u64 = csr_rd(CVMX_SATA_UCTL_CTL);
- uctl_ctl.s.sata_uctl_rst = 0;
- uctl_ctl.s.sata_uahc_rst = 0;
- csr_wr(CVMX_SATA_UCTL_CTL, uctl_ctl.u64);
- udelay(1);
- /* 7. Enable conditional SCLK of UCTL by writing
- * SATA_UCTL_CTL[CSCLK_EN] = 1
- */
- uctl_ctl.u64 = csr_rd(CVMX_SATA_UCTL_CTL);
- uctl_ctl.s.csclk_en = 1;
- csr_wr(CVMX_SATA_UCTL_CTL, uctl_ctl.u64);
- /* set-up endian mode */
- shim_cfg.u64 = csr_rd(CVMX_SATA_UCTL_SHIM_CFG);
- shim_cfg.s.dma_endian_mode = 1;
- shim_cfg.s.csr_endian_mode = 3;
- csr_wr(CVMX_SATA_UCTL_SHIM_CFG, shim_cfg.u64);
- return 0;
- }
- static int __dlm2_sata_uahc_init_cn70xx(int baud_mhz)
- {
- cvmx_sata_uahc_gbl_cap_t gbl_cap;
- cvmx_sata_uahc_px_sctl_t sctl;
- cvmx_sata_uahc_gbl_pi_t pi;
- cvmx_sata_uahc_px_cmd_t cmd;
- cvmx_sata_uahc_px_sctl_t sctl0, sctl1;
- cvmx_sata_uahc_px_ssts_t ssts;
- cvmx_sata_uahc_px_tfd_t tfd;
- cvmx_sata_uahc_gbl_timer1ms_t gbl_timer1ms;
- u64 done;
- int result = -1;
- int retry_count = 0;
- int spd;
- /* From the synopsis data book, SATA_UAHC_GBL_TIMER1MS is the
- * AMBA clock in MHz * 1000, which is a_clk(Hz) / 1000
- */
- gbl_timer1ms.u32 = csr_rd32(CVMX_SATA_UAHC_GBL_TIMER1MS);
- gbl_timer1ms.s.timv = a_clk / 1000;
- csr_wr32(CVMX_SATA_UAHC_GBL_TIMER1MS, gbl_timer1ms.u32);
- gbl_timer1ms.u32 = csr_rd32(CVMX_SATA_UAHC_GBL_TIMER1MS);
- /* Set-u global capabilities reg (GBL_CAP) */
- gbl_cap.u32 = csr_rd32(CVMX_SATA_UAHC_GBL_CAP);
- debug("%s: SATA_UAHC_GBL_CAP before: 0x%x\n", __func__, gbl_cap.u32);
- gbl_cap.s.sss = 1;
- gbl_cap.s.smps = 1;
- csr_wr32(CVMX_SATA_UAHC_GBL_CAP, gbl_cap.u32);
- gbl_cap.u32 = csr_rd32(CVMX_SATA_UAHC_GBL_CAP);
- debug("%s: SATA_UAHC_GBL_CAP after: 0x%x\n", __func__, gbl_cap.u32);
- /* Set-up global hba control reg (interrupt enables) */
- /* Set-up port SATA control registers (speed limitation) */
- if (baud_mhz == 1500)
- spd = 1;
- else if (baud_mhz == 3000)
- spd = 2;
- else
- spd = 3;
- sctl.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(0));
- debug("%s: SATA_UAHC_P0_SCTL before: 0x%x\n", __func__, sctl.u32);
- sctl.s.spd = spd;
- csr_wr32(CVMX_SATA_UAHC_PX_SCTL(0), sctl.u32);
- sctl.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(0));
- debug("%s: SATA_UAHC_P0_SCTL after: 0x%x\n", __func__, sctl.u32);
- sctl.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(1));
- debug("%s: SATA_UAHC_P1_SCTL before: 0x%x\n", __func__, sctl.u32);
- sctl.s.spd = spd;
- csr_wr32(CVMX_SATA_UAHC_PX_SCTL(1), sctl.u32);
- sctl.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(1));
- debug("%s: SATA_UAHC_P1_SCTL after: 0x%x\n", __func__, sctl.u32);
- /* Set-up ports implemented reg. */
- pi.u32 = csr_rd32(CVMX_SATA_UAHC_GBL_PI);
- debug("%s: SATA_UAHC_GBL_PI before: 0x%x\n", __func__, pi.u32);
- pi.s.pi = 3;
- csr_wr32(CVMX_SATA_UAHC_GBL_PI, pi.u32);
- pi.u32 = csr_rd32(CVMX_SATA_UAHC_GBL_PI);
- debug("%s: SATA_UAHC_GBL_PI after: 0x%x\n", __func__, pi.u32);
- retry0:
- /* Clear port SERR and IS registers */
- csr_wr32(CVMX_SATA_UAHC_PX_SERR(0), csr_rd32(CVMX_SATA_UAHC_PX_SERR(0)));
- csr_wr32(CVMX_SATA_UAHC_PX_IS(0), csr_rd32(CVMX_SATA_UAHC_PX_IS(0)));
- /* Set spin-up, power on, FIS RX enable, start, active */
- cmd.u32 = csr_rd32(CVMX_SATA_UAHC_PX_CMD(0));
- debug("%s: SATA_UAHC_P0_CMD before: 0x%x\n", __func__, cmd.u32);
- cmd.s.fre = 1;
- cmd.s.sud = 1;
- cmd.s.pod = 1;
- cmd.s.st = 1;
- cmd.s.icc = 1;
- cmd.s.fbscp = 1; /* Enable FIS-based switching */
- csr_wr32(CVMX_SATA_UAHC_PX_CMD(0), cmd.u32);
- cmd.u32 = csr_rd32(CVMX_SATA_UAHC_PX_CMD(0));
- debug("%s: SATA_UAHC_P0_CMD after: 0x%x\n", __func__, cmd.u32);
- sctl0.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(0));
- sctl0.s.det = 1;
- csr_wr32(CVMX_SATA_UAHC_PX_SCTL(0), sctl0.u32);
- /* check status */
- done = get_timer(0);
- while (1) {
- ssts.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SSTS(0));
- if (ssts.s.ipm == 1 && ssts.s.det == 3) {
- result = 0;
- break;
- } else if (get_timer(done) > 100) {
- result = -1;
- break;
- }
- udelay(100);
- }
- if (result != -1) {
- /* Clear the PxSERR Register, by writing '1s' to each
- * implemented bit location
- */
- csr_wr32(CVMX_SATA_UAHC_PX_SERR(0), -1);
- /*
- * Wait for indication that SATA drive is ready. This is
- * determined via an examination of PxTFD.STS. If PxTFD.STS.BSY
- * PxTFD.STS.DRQ, and PxTFD.STS.ERR are all '0', prior to the
- * maximum allowed time as specified in the ATA/ATAPI-7
- * specification, the device is ready.
- */
- /*
- * Wait for the device to be ready. BSY(7), DRQ(3), and ERR(0)
- * must be clear
- */
- done = get_timer(0);
- while (1) {
- tfd.u32 = csr_rd32(CVMX_SATA_UAHC_PX_TFD(0));
- if ((tfd.s.sts & 0x89) == 0) {
- result = 0;
- break;
- } else if (get_timer(done) > 500) {
- if (retry_count < 3) {
- sctl0.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(0));
- sctl0.s.det = 1; /* Perform interface reset */
- csr_wr32(CVMX_SATA_UAHC_PX_SCTL(0), sctl0.u32);
- udelay(1000); /* 1ms dicated by AHCI 1.3 spec */
- sctl0.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(0));
- sctl0.s.det = 0; /* Perform interface reset */
- csr_wr32(CVMX_SATA_UAHC_PX_SCTL(0), sctl0.u32);
- retry_count++;
- goto retry0;
- }
- result = -1;
- break;
- }
- udelay(100);
- }
- }
- if (result == -1)
- printf("SATA0: not available\n");
- else
- printf("SATA0: available\n");
- sctl1.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(1));
- sctl1.s.det = 1;
- csr_wr32(CVMX_SATA_UAHC_PX_SCTL(1), sctl1.u32);
- result = -1;
- retry_count = 0;
- retry1:
- /* Clear port SERR and IS registers */
- csr_wr32(CVMX_SATA_UAHC_PX_SERR(1), csr_rd32(CVMX_SATA_UAHC_PX_SERR(1)));
- csr_wr32(CVMX_SATA_UAHC_PX_IS(1), csr_rd32(CVMX_SATA_UAHC_PX_IS(1)));
- /* Set spin-up, power on, FIS RX enable, start, active */
- cmd.u32 = csr_rd32(CVMX_SATA_UAHC_PX_CMD(1));
- debug("%s: SATA_UAHC_P1_CMD before: 0x%x\n", __func__, cmd.u32);
- cmd.s.fre = 1;
- cmd.s.sud = 1;
- cmd.s.pod = 1;
- cmd.s.st = 1;
- cmd.s.icc = 1;
- cmd.s.fbscp = 1; /* Enable FIS-based switching */
- csr_wr32(CVMX_SATA_UAHC_PX_CMD(1), cmd.u32);
- cmd.u32 = csr_rd32(CVMX_SATA_UAHC_PX_CMD(1));
- debug("%s: SATA_UAHC_P1_CMD after: 0x%x\n", __func__, cmd.u32);
- /* check status */
- done = get_timer(0);
- while (1) {
- ssts.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SSTS(1));
- if (ssts.s.ipm == 1 && ssts.s.det == 3) {
- result = 0;
- break;
- } else if (get_timer(done) > 1000) {
- result = -1;
- break;
- }
- udelay(100);
- }
- if (result != -1) {
- /* Clear the PxSERR Register, by writing '1s' to each
- * implemented bit location
- */
- csr_wr32(CVMX_SATA_UAHC_PX_SERR(1), csr_rd32(CVMX_SATA_UAHC_PX_SERR(1)));
- /*
- * Wait for indication that SATA drive is ready. This is
- * determined via an examination of PxTFD.STS. If PxTFD.STS.BSY
- * PxTFD.STS.DRQ, and PxTFD.STS.ERR are all '0', prior to the
- * maximum allowed time as specified in the ATA/ATAPI-7
- * specification, the device is ready.
- */
- /*
- * Wait for the device to be ready. BSY(7), DRQ(3), and ERR(0)
- * must be clear
- */
- done = get_timer(0);
- while (1) {
- tfd.u32 = csr_rd32(CVMX_SATA_UAHC_PX_TFD(1));
- if ((tfd.s.sts & 0x89) == 0) {
- result = 0;
- break;
- } else if (get_timer(done) > 500) {
- if (retry_count < 3) {
- sctl0.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(1));
- sctl0.s.det = 1; /* Perform interface reset */
- csr_wr32(CVMX_SATA_UAHC_PX_SCTL(1), sctl0.u32);
- udelay(1000); /* 1ms dicated by AHCI 1.3 spec */
- sctl0.u32 = csr_rd32(CVMX_SATA_UAHC_PX_SCTL(1));
- sctl0.s.det = 0; /* Perform interface reset */
- csr_wr32(CVMX_SATA_UAHC_PX_SCTL(1), sctl0.u32);
- retry_count++;
- goto retry1;
- }
- result = -1;
- break;
- }
- udelay(100);
- }
- }
- if (result == -1)
- printf("SATA1: not available\n");
- else
- printf("SATA1: available\n");
- return 0;
- }
- static int __sata_bist_cn70xx(int qlm, int baud_mhz, int ref_clk_sel, int ref_clk_input)
- {
- cvmx_sata_uctl_bist_status_t bist_status;
- cvmx_sata_uctl_ctl_t uctl_ctl;
- cvmx_sata_uctl_shim_cfg_t shim_cfg;
- u64 done;
- int result = -1;
- debug("%s(%d, %d, %d, %d)\n", __func__, qlm, baud_mhz, ref_clk_sel, ref_clk_input);
- bist_status.u64 = csr_rd(CVMX_SATA_UCTL_BIST_STATUS);
- {
- if (__dlm2_sata_uctl_init_cn70xx()) {
- printf("ERROR: Failed to initialize SATA UCTL CSRs\n");
- return -1;
- }
- if (OCTEON_IS_MODEL(OCTEON_CN73XX))
- result = __sata_dlm_init_cn73xx(qlm, baud_mhz, ref_clk_sel, ref_clk_input);
- else
- result = __sata_dlm_init_cn70xx(qlm, baud_mhz, ref_clk_sel, ref_clk_input);
- if (result) {
- printf("ERROR: Failed to initialize SATA GSER CSRs\n");
- return -1;
- }
- uctl_ctl.u64 = csr_rd(CVMX_SATA_UCTL_CTL);
- uctl_ctl.s.start_bist = 1;
- csr_wr(CVMX_SATA_UCTL_CTL, uctl_ctl.u64);
- /* Set-up for a 1 sec timer. */
- done = get_timer(0);
- while (1) {
- bist_status.u64 = csr_rd(CVMX_SATA_UCTL_BIST_STATUS);
- if ((bist_status.s.uctl_xm_r_bist_ndone |
- bist_status.s.uctl_xm_w_bist_ndone |
- bist_status.s.uahc_p0_rxram_bist_ndone |
- bist_status.s.uahc_p1_rxram_bist_ndone |
- bist_status.s.uahc_p0_txram_bist_ndone |
- bist_status.s.uahc_p1_txram_bist_ndone) == 0) {
- result = 0;
- break;
- } else if (get_timer(done) > 1000) {
- result = -1;
- break;
- }
- udelay(100);
- }
- if (result == -1) {
- printf("ERROR: SATA_UCTL_BIST_STATUS = 0x%llx\n",
- (unsigned long long)bist_status.u64);
- return -1;
- }
- debug("%s: Initializing UAHC\n", __func__);
- if (__dlm2_sata_uahc_init_cn70xx(baud_mhz)) {
- printf("ERROR: Failed to initialize SATA UAHC CSRs\n");
- return -1;
- }
- }
- /* Change CSR_ENDIAN_MODE to big endian to use Open Source AHCI SATA
- * driver
- */
- shim_cfg.u64 = csr_rd(CVMX_SATA_UCTL_SHIM_CFG);
- shim_cfg.s.csr_endian_mode = 1;
- csr_wr(CVMX_SATA_UCTL_SHIM_CFG, shim_cfg.u64);
- return 0;
- }
- static int __setup_sata(int qlm, int baud_mhz, int ref_clk_sel, int ref_clk_input)
- {
- debug("%s(%d, %d, %d, %d)\n", __func__, qlm, baud_mhz, ref_clk_sel, ref_clk_input);
- return __sata_bist_cn70xx(qlm, baud_mhz, ref_clk_sel, ref_clk_input);
- }
- static int __dlmx_setup_pcie_cn70xx(int qlm, enum cvmx_qlm_mode mode, int gen2, int rc,
- int ref_clk_sel, int ref_clk_input)
- {
- cvmx_gserx_dlmx_phy_reset_t dlmx_phy_reset;
- cvmx_gserx_dlmx_test_powerdown_t dlmx_test_powerdown;
- cvmx_gserx_dlmx_mpll_multiplier_t mpll_multiplier;
- cvmx_gserx_dlmx_ref_clkdiv2_t ref_clkdiv2;
- static const u8 ref_clk_mult[2] = { 35, 56 }; /* 100 & 125 MHz ref clock supported. */
- debug("%s(%d, %d, %d, %d, %d, %d)\n", __func__, qlm, mode, gen2, rc, ref_clk_sel,
- ref_clk_input);
- if (rc == 0) {
- debug("Skipping initializing PCIe dlm %d in endpoint mode\n", qlm);
- return 0;
- }
- if (qlm > 0 && ref_clk_input > 1) {
- printf("%s: Error: ref_clk_input can only be 0 or 1 for QLM %d\n",
- __func__, qlm);
- return -1;
- }
- if (ref_clk_sel > OCTEON_QLM_REF_CLK_125MHZ) {
- printf("%s: Error: ref_clk_sel can only be 100 or 125 MHZ.\n", __func__);
- return -1;
- }
- /* 1. Write GSER0_DLM(1..2)_REFCLK_SEL[REFCLK_SEL] if required for
- * reference-clock selection
- */
- csr_wr(CVMX_GSERX_DLMX_REFCLK_SEL(qlm, 0), ref_clk_input);
- /* 2. If required, write GSER0_DLM(1..2)_REF_CLKDIV2[REF_CLKDIV2] = 1
- * (must be set if reference clock >= 100 MHz)
- */
- /* 4. Configure the PCIE PIPE:
- * a. Write GSER0_PCIE_PIPE_PORT_SEL[PIPE_PORT_SEL] to configure the
- * PCIE PIPE.
- * 0x0 = disables all pipes
- * 0x1 = enables pipe0 only (PEM0 4-lane)
- * 0x2 = enables pipes 0 and 1 (PEM0 and PEM1 2-lanes each)
- * 0x3 = enables pipes 0, 1, 2, and 3 (PEM0, PEM1, and PEM3 are
- * one-lane each)
- * b. Configure GSER0_PCIE_PIPE_PORT_SEL[CFG_PEM1_DLM2]. If PEM1 is
- * to be configured, this bit must reflect which DLM it is logically
- * tied to. This bit sets multiplexing logic in GSER, and it is used
- * by the RST logic to determine when the MAC can come out of reset.
- * 0 = PEM1 is tied to DLM1 (for 3 x 1 PCIe mode).
- * 1 = PEM1 is tied to DLM2 (for all other PCIe modes).
- */
- if (qlm == 1) {
- cvmx_gserx_pcie_pipe_port_sel_t pipe_port;
- pipe_port.u64 = csr_rd(CVMX_GSERX_PCIE_PIPE_PORT_SEL(0));
- pipe_port.s.cfg_pem1_dlm2 = (mode == CVMX_QLM_MODE_PCIE_1X1) ? 1 : 0;
- pipe_port.s.pipe_port_sel =
- (mode == CVMX_QLM_MODE_PCIE) ? 1 : /* PEM0 only */
- (mode == CVMX_QLM_MODE_PCIE_1X2) ? 2 : /* PEM0-1 */
- (mode == CVMX_QLM_MODE_PCIE_1X1) ? 3 : /* PEM0-2 */
- (mode == CVMX_QLM_MODE_PCIE_2X1) ? 3 : /* PEM0-1 */
- 0; /* PCIe disabled */
- csr_wr(CVMX_GSERX_PCIE_PIPE_PORT_SEL(0), pipe_port.u64);
- }
- /* Apply workaround for Errata (G-20669) MPLL may not come up. */
- /* Set REF_CLKDIV2 based on the Ref Clock */
- ref_clkdiv2.u64 = csr_rd(CVMX_GSERX_DLMX_REF_CLKDIV2(qlm, 0));
- ref_clkdiv2.s.ref_clkdiv2 = ref_clk_sel > 0;
- csr_wr(CVMX_GSERX_DLMX_REF_CLKDIV2(qlm, 0), ref_clkdiv2.u64);
- /* 1. Ensure GSER(0)_DLM(0..2)_PHY_RESET[PHY_RESET] is set. */
- dlmx_phy_reset.u64 = csr_rd(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0));
- dlmx_phy_reset.s.phy_reset = 1;
- csr_wr(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0), dlmx_phy_reset.u64);
- /* 2. If SGMII or QSGMII or RXAUI (i.e. if DLM0) set
- * GSER(0)_DLM(0)_MPLL_EN[MPLL_EN] to one.
- */
- /* 3. Set GSER(0)_DLM(0..2)_MPLL_MULTIPLIER[MPLL_MULTIPLIER]
- * to the value in the preceding table, which is different
- * than the desired setting prescribed by the HRM.
- */
- mpll_multiplier.u64 = csr_rd(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0));
- mpll_multiplier.s.mpll_multiplier = ref_clk_mult[ref_clk_sel];
- debug("%s: Setting MPLL multiplier to %d\n", __func__,
- (int)mpll_multiplier.s.mpll_multiplier);
- csr_wr(CVMX_GSERX_DLMX_MPLL_MULTIPLIER(qlm, 0), mpll_multiplier.u64);
- /* 5. Clear GSER0_DLM(1..2)_TEST_POWERDOWN. Configurations that only
- * use DLM1 need not clear GSER0_DLM2_TEST_POWERDOWN
- */
- dlmx_test_powerdown.u64 = csr_rd(CVMX_GSERX_DLMX_TEST_POWERDOWN(qlm, 0));
- dlmx_test_powerdown.s.test_powerdown = 0;
- csr_wr(CVMX_GSERX_DLMX_TEST_POWERDOWN(qlm, 0), dlmx_test_powerdown.u64);
- /* 6. Clear GSER0_DLM(1..2)_PHY_RESET. Configurations that use only
- * need DLM1 need not clear GSER0_DLM2_PHY_RESET
- */
- dlmx_phy_reset.u64 = csr_rd(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0));
- dlmx_phy_reset.s.phy_reset = 0;
- csr_wr(CVMX_GSERX_DLMX_PHY_RESET(qlm, 0), dlmx_phy_reset.u64);
- /* 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.
- */
- /* This is set when initializing PCIe after soft reset is asserted. */
- /* 7. Write the GSER0_PCIE_PIPE_RST register to take the appropriate
- * PIPE out of reset. There is a PIPEn_RST bit for each PIPE. Clear
- * the appropriate bits based on the configuration (reset is
- * active high).
- */
- if (qlm == 1) {
- cvmx_pemx_cfg_t pemx_cfg;
- cvmx_pemx_on_t pemx_on;
- cvmx_gserx_pcie_pipe_rst_t pipe_rst;
- cvmx_rst_ctlx_t rst_ctl;
- switch (mode) {
- case CVMX_QLM_MODE_PCIE: /* PEM0 on DLM1 & DLM2 */
- case CVMX_QLM_MODE_PCIE_1X2: /* PEM0 on DLM1 */
- case CVMX_QLM_MODE_PCIE_1X1: /* PEM0 on DLM1 using lane 0 */
- pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(0));
- pemx_cfg.cn70xx.hostmd = rc;
- if (mode == CVMX_QLM_MODE_PCIE_1X1) {
- pemx_cfg.cn70xx.md =
- gen2 ? CVMX_PEM_MD_GEN2_1LANE : CVMX_PEM_MD_GEN1_1LANE;
- } else if (mode == CVMX_QLM_MODE_PCIE) {
- pemx_cfg.cn70xx.md =
- gen2 ? CVMX_PEM_MD_GEN2_4LANE : CVMX_PEM_MD_GEN1_4LANE;
- } else {
- pemx_cfg.cn70xx.md =
- gen2 ? CVMX_PEM_MD_GEN2_2LANE : CVMX_PEM_MD_GEN1_2LANE;
- }
- csr_wr(CVMX_PEMX_CFG(0), pemx_cfg.u64);
- rst_ctl.u64 = csr_rd(CVMX_RST_CTLX(0));
- rst_ctl.s.rst_drv = 1;
- csr_wr(CVMX_RST_CTLX(0), rst_ctl.u64);
- /* PEM0 is on DLM1&2 which is pipe0 */
- pipe_rst.u64 = csr_rd(CVMX_GSERX_PCIE_PIPE_RST(0));
- pipe_rst.s.pipe0_rst = 0;
- csr_wr(CVMX_GSERX_PCIE_PIPE_RST(0), pipe_rst.u64);
- pemx_on.u64 = csr_rd(CVMX_PEMX_ON(0));
- pemx_on.s.pemon = 1;
- csr_wr(CVMX_PEMX_ON(0), pemx_on.u64);
- break;
- case CVMX_QLM_MODE_PCIE_2X1: /* PEM0 and PEM1 on DLM1 */
- pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(0));
- pemx_cfg.cn70xx.hostmd = rc;
- pemx_cfg.cn70xx.md = gen2 ? CVMX_PEM_MD_GEN2_1LANE : CVMX_PEM_MD_GEN1_1LANE;
- csr_wr(CVMX_PEMX_CFG(0), pemx_cfg.u64);
- rst_ctl.u64 = csr_rd(CVMX_RST_CTLX(0));
- rst_ctl.s.rst_drv = 1;
- csr_wr(CVMX_RST_CTLX(0), rst_ctl.u64);
- /* PEM0 is on DLM1 which is pipe0 */
- pipe_rst.u64 = csr_rd(CVMX_GSERX_PCIE_PIPE_RST(0));
- pipe_rst.s.pipe0_rst = 0;
- csr_wr(CVMX_GSERX_PCIE_PIPE_RST(0), pipe_rst.u64);
- pemx_on.u64 = csr_rd(CVMX_PEMX_ON(0));
- pemx_on.s.pemon = 1;
- csr_wr(CVMX_PEMX_ON(0), pemx_on.u64);
- pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(1));
- pemx_cfg.cn70xx.hostmd = 1;
- pemx_cfg.cn70xx.md = gen2 ? CVMX_PEM_MD_GEN2_1LANE : CVMX_PEM_MD_GEN1_1LANE;
- csr_wr(CVMX_PEMX_CFG(1), pemx_cfg.u64);
- rst_ctl.u64 = csr_rd(CVMX_RST_CTLX(1));
- rst_ctl.s.rst_drv = 1;
- csr_wr(CVMX_RST_CTLX(1), rst_ctl.u64);
- /* PEM1 is on DLM2 which is pipe1 */
- pipe_rst.u64 = csr_rd(CVMX_GSERX_PCIE_PIPE_RST(0));
- pipe_rst.s.pipe1_rst = 0;
- csr_wr(CVMX_GSERX_PCIE_PIPE_RST(0), pipe_rst.u64);
- pemx_on.u64 = csr_rd(CVMX_PEMX_ON(1));
- pemx_on.s.pemon = 1;
- csr_wr(CVMX_PEMX_ON(1), pemx_on.u64);
- break;
- default:
- break;
- }
- } else {
- cvmx_pemx_cfg_t pemx_cfg;
- cvmx_pemx_on_t pemx_on;
- cvmx_gserx_pcie_pipe_rst_t pipe_rst;
- cvmx_rst_ctlx_t rst_ctl;
- switch (mode) {
- case CVMX_QLM_MODE_PCIE_1X2: /* PEM1 on DLM2 */
- pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(1));
- pemx_cfg.cn70xx.hostmd = 1;
- pemx_cfg.cn70xx.md = gen2 ? CVMX_PEM_MD_GEN2_2LANE : CVMX_PEM_MD_GEN1_2LANE;
- csr_wr(CVMX_PEMX_CFG(1), pemx_cfg.u64);
- rst_ctl.u64 = csr_rd(CVMX_RST_CTLX(1));
- rst_ctl.s.rst_drv = 1;
- csr_wr(CVMX_RST_CTLX(1), rst_ctl.u64);
- /* PEM1 is on DLM1 lane 0, which is pipe1 */
- pipe_rst.u64 = csr_rd(CVMX_GSERX_PCIE_PIPE_RST(0));
- pipe_rst.s.pipe1_rst = 0;
- csr_wr(CVMX_GSERX_PCIE_PIPE_RST(0), pipe_rst.u64);
- pemx_on.u64 = csr_rd(CVMX_PEMX_ON(1));
- pemx_on.s.pemon = 1;
- csr_wr(CVMX_PEMX_ON(1), pemx_on.u64);
- break;
- case CVMX_QLM_MODE_PCIE_2X1: /* PEM1 and PEM2 on DLM2 */
- pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(1));
- pemx_cfg.cn70xx.hostmd = 1;
- pemx_cfg.cn70xx.md = gen2 ? CVMX_PEM_MD_GEN2_1LANE : CVMX_PEM_MD_GEN1_1LANE;
- csr_wr(CVMX_PEMX_CFG(1), pemx_cfg.u64);
- rst_ctl.u64 = csr_rd(CVMX_RST_CTLX(1));
- rst_ctl.s.rst_drv = 1;
- csr_wr(CVMX_RST_CTLX(1), rst_ctl.u64);
- /* PEM1 is on DLM2 lane 0, which is pipe2 */
- pipe_rst.u64 = csr_rd(CVMX_GSERX_PCIE_PIPE_RST(0));
- pipe_rst.s.pipe2_rst = 0;
- csr_wr(CVMX_GSERX_PCIE_PIPE_RST(0), pipe_rst.u64);
- pemx_on.u64 = csr_rd(CVMX_PEMX_ON(1));
- pemx_on.s.pemon = 1;
- csr_wr(CVMX_PEMX_ON(1), pemx_on.u64);
- pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(2));
- pemx_cfg.cn70xx.hostmd = 1;
- pemx_cfg.cn70xx.md = gen2 ? CVMX_PEM_MD_GEN2_1LANE : CVMX_PEM_MD_GEN1_1LANE;
- csr_wr(CVMX_PEMX_CFG(2), pemx_cfg.u64);
- rst_ctl.u64 = csr_rd(CVMX_RST_CTLX(2));
- rst_ctl.s.rst_drv = 1;
- csr_wr(CVMX_RST_CTLX(2), rst_ctl.u64);
- /* PEM2 is on DLM2 lane 1, which is pipe3 */
- pipe_rst.u64 = csr_rd(CVMX_GSERX_PCIE_PIPE_RST(0));
- pipe_rst.s.pipe3_rst = 0;
- csr_wr(CVMX_GSERX_PCIE_PIPE_RST(0), pipe_rst.u64);
- pemx_on.u64 = csr_rd(CVMX_PEMX_ON(2));
- pemx_on.s.pemon = 1;
- csr_wr(CVMX_PEMX_ON(2), pemx_on.u64);
- break;
- default:
- break;
- }
- }
- return 0;
- }
- /**
- * Configure dlm speed and mode for cn70xx.
- *
- * @param qlm The DLM to configure
- * @param speed The speed the DLM needs to be configured in Mhz.
- * @param mode The DLM to be configured as SGMII/XAUI/PCIe.
- * DLM 0: has 2 interfaces which can be configured as
- * SGMII/QSGMII/RXAUI. Need to configure both at the
- * same time. These are valid option
- * CVMX_QLM_MODE_QSGMII,
- * CVMX_QLM_MODE_SGMII_SGMII,
- * CVMX_QLM_MODE_SGMII_DISABLED,
- * CVMX_QLM_MODE_DISABLED_SGMII,
- * CVMX_QLM_MODE_SGMII_QSGMII,
- * CVMX_QLM_MODE_QSGMII_QSGMII,
- * CVMX_QLM_MODE_QSGMII_DISABLED,
- * CVMX_QLM_MODE_DISABLED_QSGMII,
- * CVMX_QLM_MODE_QSGMII_SGMII,
- * CVMX_QLM_MODE_RXAUI_1X2
- *
- * DLM 1: PEM0/1 in PCIE_1x4/PCIE_2x1/PCIE_1X1
- * DLM 2: PEM0/1/2 in PCIE_1x4/PCIE_1x2/PCIE_2x1/PCIE_1x1
- * @param rc Only used for PCIe, rc = 1 for root complex mode, 0 for EP mode.
- * @param gen2 Only used for PCIe, gen2 = 1, in GEN2 mode else in GEN1 mode.
- *
- * @param ref_clk_input The reference-clock input to use to configure QLM
- * @param ref_clk_sel The reference-clock selection to use to configure QLM
- *
- * Return: Return 0 on success or -1.
- */
- static int octeon_configure_qlm_cn70xx(int qlm, int speed, int mode, int rc, int gen2,
- int ref_clk_sel, int ref_clk_input)
- {
- debug("%s(%d, %d, %d, %d, %d, %d, %d)\n", __func__, qlm, speed, mode, rc, gen2, ref_clk_sel,
- ref_clk_input);
- switch (qlm) {
- case 0: {
- int is_sff7000_rxaui = 0;
- cvmx_gmxx_inf_mode_t inf_mode0, inf_mode1;
- inf_mode0.u64 = csr_rd(CVMX_GMXX_INF_MODE(0));
- inf_mode1.u64 = csr_rd(CVMX_GMXX_INF_MODE(1));
- if (inf_mode0.s.en || inf_mode1.s.en) {
- debug("DLM0 already configured\n");
- return -1;
- }
- switch (mode) {
- case CVMX_QLM_MODE_SGMII_SGMII:
- debug(" Mode SGMII SGMII\n");
- inf_mode0.s.mode = CVMX_GMX_INF_MODE_SGMII;
- inf_mode1.s.mode = CVMX_GMX_INF_MODE_SGMII;
- break;
- case CVMX_QLM_MODE_SGMII_QSGMII:
- debug(" Mode SGMII QSGMII\n");
- inf_mode0.s.mode = CVMX_GMX_INF_MODE_SGMII;
- inf_mode1.s.mode = CVMX_GMX_INF_MODE_QSGMII;
- break;
- case CVMX_QLM_MODE_SGMII_DISABLED:
- debug(" Mode SGMII Disabled\n");
- inf_mode0.s.mode = CVMX_GMX_INF_MODE_SGMII;
- inf_mode1.s.mode = CVMX_GMX_INF_MODE_DISABLED;
- break;
- case CVMX_QLM_MODE_DISABLED_SGMII:
- debug("Mode Disabled SGMII\n");
- inf_mode0.s.mode = CVMX_GMX_INF_MODE_DISABLED;
- inf_mode1.s.mode = CVMX_GMX_INF_MODE_SGMII;
- break;
- case CVMX_QLM_MODE_QSGMII_SGMII:
- debug(" Mode QSGMII SGMII\n");
- inf_mode0.s.mode = CVMX_GMX_INF_MODE_QSGMII;
- inf_mode1.s.mode = CVMX_GMX_INF_MODE_SGMII;
- break;
- case CVMX_QLM_MODE_QSGMII_QSGMII:
- debug(" Mode QSGMII QSGMII\n");
- inf_mode0.s.mode = CVMX_GMX_INF_MODE_QSGMII;
- inf_mode1.s.mode = CVMX_GMX_INF_MODE_QSGMII;
- break;
- case CVMX_QLM_MODE_QSGMII_DISABLED:
- debug(" Mode QSGMII Disabled\n");
- inf_mode0.s.mode = CVMX_GMX_INF_MODE_QSGMII;
- inf_mode1.s.mode = CVMX_GMX_INF_MODE_DISABLED;
- break;
- case CVMX_QLM_MODE_DISABLED_QSGMII:
- debug("Mode Disabled QSGMII\n");
- inf_mode0.s.mode = CVMX_GMX_INF_MODE_DISABLED;
- inf_mode1.s.mode = CVMX_GMX_INF_MODE_QSGMII;
- break;
- case CVMX_QLM_MODE_RXAUI:
- debug(" Mode RXAUI\n");
- inf_mode0.s.mode = CVMX_GMX_INF_MODE_RXAUI;
- inf_mode1.s.mode = CVMX_GMX_INF_MODE_DISABLED;
- break;
- default:
- debug(" Mode Disabled Disabled\n");
- inf_mode0.s.mode = CVMX_GMX_INF_MODE_DISABLED;
- inf_mode1.s.mode = CVMX_GMX_INF_MODE_DISABLED;
- break;
- }
- csr_wr(CVMX_GMXX_INF_MODE(0), inf_mode0.u64);
- csr_wr(CVMX_GMXX_INF_MODE(1), inf_mode1.u64);
- /* Bringup the PLL */
- if (__dlm_setup_pll_cn70xx(qlm, speed, ref_clk_sel, ref_clk_input,
- is_sff7000_rxaui))
- return -1;
- /* TX Lanes */
- if (__dlm0_setup_tx_cn70xx(speed, ref_clk_sel))
- return -1;
- /* RX Lanes */
- if (__dlm0_setup_rx_cn70xx(speed, ref_clk_sel))
- return -1;
- /* Enable the interface */
- inf_mode0.u64 = csr_rd(CVMX_GMXX_INF_MODE(0));
- if (inf_mode0.s.mode != CVMX_GMX_INF_MODE_DISABLED)
- inf_mode0.s.en = 1;
- csr_wr(CVMX_GMXX_INF_MODE(0), inf_mode0.u64);
- inf_mode1.u64 = csr_rd(CVMX_GMXX_INF_MODE(1));
- if (inf_mode1.s.mode != CVMX_GMX_INF_MODE_DISABLED)
- inf_mode1.s.en = 1;
- csr_wr(CVMX_GMXX_INF_MODE(1), inf_mode1.u64);
- break;
- }
- case 1:
- switch (mode) {
- case CVMX_QLM_MODE_PCIE: /* PEM0 on DLM1 & DLM2 */
- debug(" Mode PCIe\n");
- if (__dlmx_setup_pcie_cn70xx(1, mode, gen2, rc, ref_clk_sel, ref_clk_input))
- return -1;
- if (__dlmx_setup_pcie_cn70xx(2, mode, gen2, rc, ref_clk_sel, ref_clk_input))
- return -1;
- break;
- case CVMX_QLM_MODE_PCIE_1X2: /* PEM0 on DLM1 */
- case CVMX_QLM_MODE_PCIE_2X1: /* PEM0 & PEM1 on DLM1 */
- case CVMX_QLM_MODE_PCIE_1X1: /* PEM0 on DLM1, only 1 lane */
- debug(" Mode PCIe 1x2, 2x1 or 1x1\n");
- if (__dlmx_setup_pcie_cn70xx(qlm, mode, gen2, rc, ref_clk_sel,
- ref_clk_input))
- return -1;
- break;
- case CVMX_QLM_MODE_DISABLED:
- debug(" Mode disabled\n");
- break;
- default:
- debug("DLM1 illegal mode specified\n");
- return -1;
- }
- break;
- case 2:
- switch (mode) {
- case CVMX_QLM_MODE_SATA_2X1:
- debug("%s: qlm 2, mode is SATA 2x1\n", __func__);
- /* DLM2 is SATA, PCIE2 is disabled */
- if (__setup_sata(qlm, speed, ref_clk_sel, ref_clk_input))
- return -1;
- break;
- case CVMX_QLM_MODE_PCIE:
- debug(" Mode PCIe\n");
- /* DLM2 is PCIE0, PCIE1-2 are disabled. */
- /* Do nothing, its initialized in DLM1 */
- break;
- case CVMX_QLM_MODE_PCIE_1X2: /* PEM1 on DLM2 */
- case CVMX_QLM_MODE_PCIE_2X1: /* PEM1 & PEM2 on DLM2 */
- debug(" Mode PCIe 1x2 or 2x1\n");
- if (__dlmx_setup_pcie_cn70xx(qlm, mode, gen2, rc, ref_clk_sel,
- ref_clk_input))
- return -1;
- break;
- case CVMX_QLM_MODE_DISABLED:
- debug(" Mode Disabled\n");
- break;
- default:
- debug("DLM2 illegal mode specified\n");
- return -1;
- }
- default:
- return -1;
- }
- return 0;
- }
- /**
- * Disables DFE for the specified QLM lane(s).
- * This function should only be called for low-loss channels.
- *
- * @param node Node to configure
- * @param qlm QLM to configure
- * @param lane Lane to configure, or -1 all lanes
- * @param baud_mhz The speed the QLM needs to be configured in Mhz.
- * @param mode The QLM to be configured as SGMII/XAUI/PCIe.
- */
- void octeon_qlm_dfe_disable(int node, int qlm, int lane, int baud_mhz, int mode)
- {
- int num_lanes = cvmx_qlm_get_lanes(qlm);
- int l;
- cvmx_gserx_lanex_rx_loop_ctrl_t loop_ctrl;
- cvmx_gserx_lanex_rx_valbbd_ctrl_0_t ctrl_0;
- cvmx_gserx_lanex_rx_valbbd_ctrl_1_t ctrl_1;
- cvmx_gserx_lanex_rx_valbbd_ctrl_2_t ctrl_2;
- cvmx_gserx_lane_vma_fine_ctrl_2_t lane_vma_fine_ctrl_2;
- /* Interfaces below 5Gbaud are already manually tuned. */
- if (baud_mhz < 5000)
- return;
- /* Don't run on PCIe links, SATA or KR. These interfaces use training */
- switch (mode) {
- case CVMX_QLM_MODE_10G_KR_1X2:
- case CVMX_QLM_MODE_10G_KR:
- case CVMX_QLM_MODE_40G_KR4:
- return;
- case CVMX_QLM_MODE_PCIE_1X1:
- case CVMX_QLM_MODE_PCIE_2X1:
- case CVMX_QLM_MODE_PCIE_1X2:
- case CVMX_QLM_MODE_PCIE:
- case CVMX_QLM_MODE_PCIE_1X8:
- return;
- case CVMX_QLM_MODE_SATA_2X1:
- return;
- default:
- break;
- }
- /* Updating pre_ctle minimum to 0. This works best for short channels */
- lane_vma_fine_ctrl_2.u64 = csr_rd_node(node, CVMX_GSERX_LANE_VMA_FINE_CTRL_2(qlm));
- lane_vma_fine_ctrl_2.s.rx_prectle_gain_min_fine = 0;
- csr_wr_node(node, CVMX_GSERX_LANE_VMA_FINE_CTRL_2(qlm), lane_vma_fine_ctrl_2.u64);
- for (l = 0; l < num_lanes; l++) {
- if (lane != -1 && lane != l)
- continue;
- /* 1. Write GSERX_LANEx_RX_LOOP_CTRL = 0x0270
- * (var "loop_ctrl" with bits 8 & 1 cleared).
- * bit<1> dfe_en_byp = 1'b0
- */
- loop_ctrl.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_LOOP_CTRL(l, qlm));
- loop_ctrl.s.cfg_rx_lctrl = loop_ctrl.s.cfg_rx_lctrl & 0x3fd;
- csr_wr_node(node, CVMX_GSERX_LANEX_RX_LOOP_CTRL(l, qlm), loop_ctrl.u64);
- /* 2. Write GSERX_LANEx_RX_VALBBD_CTRL_1 = 0x0000
- * (var "ctrl1" with all bits cleared)
- * bits<14:11> CFG_RX_DFE_C3_MVAL = 4'b0000
- * bit<10> CFG_RX_DFE_C3_MSGN = 1'b0
- * bits<9:6> CFG_RX_DFE_C2_MVAL = 4'b0000
- * bit<5> CFG_RX_DFE_C2_MSGN = 1'b0
- * bits<4:0> CFG_RX_DFE_C1_MVAL = 5'b00000
- */
- ctrl_1.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_1(l, qlm));
- ctrl_1.s.dfe_c3_mval = 0;
- ctrl_1.s.dfe_c3_msgn = 0;
- ctrl_1.s.dfe_c2_mval = 0;
- ctrl_1.s.dfe_c2_msgn = 0;
- ctrl_1.s.dfe_c2_mval = 0;
- ctrl_1.s.dfe_c1_mval = 0;
- ctrl_1.s.dfe_c1_msgn = 0;
- csr_wr_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_1(l, qlm), ctrl_1.u64);
- /* 3. Write GSERX_LANEx_RX_VALBBD_CTRL_0 = 0x2400
- * (var "ctrl0" with following bits set/cleared)
- * bits<11:10> CFG_RX_DFE_GAIN = 0x1
- * bits<9:6> CFG_RX_DFE_C5_MVAL = 4'b0000
- * bit<5> CFG_RX_DFE_C5_MSGN = 1'b0
- * bits<4:1> CFG_RX_DFE_C4_MVAL = 4'b0000
- * bit<0> CFG_RX_DFE_C4_MSGN = 1'b0
- */
- ctrl_0.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_0(l, qlm));
- ctrl_0.s.dfe_gain = 0x1;
- ctrl_0.s.dfe_c5_mval = 0;
- ctrl_0.s.dfe_c5_msgn = 0;
- ctrl_0.s.dfe_c4_mval = 0;
- ctrl_0.s.dfe_c4_msgn = 0;
- csr_wr_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_0(l, qlm), ctrl_0.u64);
- /* 4. Write GSER(0..13)_LANE(0..3)_RX_VALBBD_CTRL_2 = 0x003F
- * //enable DFE tap overrides
- * bit<5> dfe_ovrd_en = 1
- * bit<4> dfe_c5_ovrd_val = 1
- * bit<3> dfe_c4_ovrd_val = 1
- * bit<2> dfe_c3_ovrd_val = 1
- * bit<1> dfe_c2_ovrd_val = 1
- * bit<0> dfe_c1_ovrd_val = 1
- */
- ctrl_2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_2(l, qlm));
- ctrl_2.s.dfe_ovrd_en = 0x1;
- ctrl_2.s.dfe_c5_ovrd_val = 0x1;
- ctrl_2.s.dfe_c4_ovrd_val = 0x1;
- ctrl_2.s.dfe_c3_ovrd_val = 0x1;
- ctrl_2.s.dfe_c2_ovrd_val = 0x1;
- ctrl_2.s.dfe_c1_ovrd_val = 0x1;
- csr_wr_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_2(l, qlm), ctrl_2.u64);
- }
- }
- /**
- * Disables DFE, uses fixed CTLE Peak value and AGC settings
- * for the specified QLM lane(s).
- * This function should only be called for low-loss channels.
- * This function prevents Rx equalization from happening on all lanes in a QLM
- * This function should be called for all lanes being used in the QLM.
- *
- * @param node Node to configure
- * @param qlm QLM to configure
- * @param lane Lane to configure, or -1 all lanes
- * @param baud_mhz The speed the QLM needs to be configured in Mhz.
- * @param mode The QLM to be configured as SGMII/XAUI/PCIe.
- * @param ctle_zero Equalizer Peaking control
- * @param agc_pre_ctle Pre-CTLE gain
- * @param agc_post_ctle Post-CTLE gain
- * Return: Zero on success, negative on failure
- */
- int octeon_qlm_dfe_disable_ctle_agc(int node, int qlm, int lane, int baud_mhz, int mode,
- int ctle_zero, int agc_pre_ctle, int agc_post_ctle)
- {
- int num_lanes = cvmx_qlm_get_lanes(qlm);
- int l;
- cvmx_gserx_lanex_rx_loop_ctrl_t loop_ctrl;
- cvmx_gserx_lanex_rx_valbbd_ctrl_0_t ctrl_0;
- cvmx_gserx_lanex_pwr_ctrl_t lanex_pwr_ctrl;
- cvmx_gserx_lane_mode_t lmode;
- cvmx_gserx_lane_px_mode_1_t px_mode_1;
- cvmx_gserx_lanex_rx_cfg_5_t rx_cfg_5;
- cvmx_gserx_lanex_rx_cfg_2_t rx_cfg_2;
- cvmx_gserx_lanex_rx_ctle_ctrl_t ctle_ctrl;
- /* Check tuning constraints */
- if (ctle_zero < 0 || ctle_zero > 15) {
- printf("Error: N%d.QLM%d: Invalid CTLE_ZERO(%d). Must be between -1 and 15.\n",
- node, qlm, ctle_zero);
- return -1;
- }
- if (agc_pre_ctle < 0 || agc_pre_ctle > 15) {
- printf("Error: N%d.QLM%d: Invalid AGC_Pre_CTLE(%d)\n",
- node, qlm, agc_pre_ctle);
- return -1;
- }
- if (agc_post_ctle < 0 || agc_post_ctle > 15) {
- printf("Error: N%d.QLM%d: Invalid AGC_Post_CTLE(%d)\n",
- node, qlm, agc_post_ctle);
- return -1;
- }
- /* Interfaces below 5Gbaud are already manually tuned. */
- if (baud_mhz < 5000)
- return 0;
- /* Don't run on PCIe links, SATA or KR. These interfaces use training */
- switch (mode) {
- case CVMX_QLM_MODE_10G_KR_1X2:
- case CVMX_QLM_MODE_10G_KR:
- case CVMX_QLM_MODE_40G_KR4:
- return 0;
- case CVMX_QLM_MODE_PCIE_1X1:
- case CVMX_QLM_MODE_PCIE_2X1:
- case CVMX_QLM_MODE_PCIE_1X2:
- case CVMX_QLM_MODE_PCIE:
- case CVMX_QLM_MODE_PCIE_1X8:
- return 0;
- case CVMX_QLM_MODE_SATA_2X1:
- return 0;
- default:
- break;
- }
- lmode.u64 = csr_rd_node(node, CVMX_GSERX_LANE_MODE(qlm));
- /* 1. Enable VMA manual mode for the QLM's lane mode */
- px_mode_1.u64 = csr_rd_node(node, CVMX_GSERX_LANE_PX_MODE_1(lmode.s.lmode, qlm));
- px_mode_1.s.vma_mm = 1;
- csr_wr_node(node, CVMX_GSERX_LANE_PX_MODE_1(lmode.s.lmode, qlm), px_mode_1.u64);
- /* 2. Disable DFE */
- octeon_qlm_dfe_disable(node, qlm, lane, baud_mhz, mode);
- for (l = 0; l < num_lanes; l++) {
- if (lane != -1 && lane != l)
- continue;
- /* 3. Write GSERX_LANEx_RX_VALBBD_CTRL_0.CFG_RX_AGC_GAIN = 0x2 */
- ctrl_0.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_0(l, qlm));
- ctrl_0.s.agc_gain = 0x2;
- csr_wr_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_0(l, qlm), ctrl_0.u64);
- /* 4. Write GSERX_LANEx_RX_LOOP_CTRL
- * bit<8> lctrl_men = 1'b1
- * bit<0> cdr_en_byp = 1'b1
- */
- loop_ctrl.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_LOOP_CTRL(l, qlm));
- loop_ctrl.s.cfg_rx_lctrl = loop_ctrl.s.cfg_rx_lctrl | 0x101;
- csr_wr_node(node, CVMX_GSERX_LANEX_RX_LOOP_CTRL(l, qlm), loop_ctrl.u64);
- /* 5. Write GSERX_LANEx_PWR_CTRL = 0x0040 (var "lanex_pwr_ctrl" with
- * following bits set)
- * bit<6> RX_LCTRL_OVRRD_EN = 1'b1
- * all other bits cleared.
- */
- lanex_pwr_ctrl.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PWR_CTRL(l, qlm));
- lanex_pwr_ctrl.s.rx_lctrl_ovrrd_en = 1;
- csr_wr_node(node, CVMX_GSERX_LANEX_PWR_CTRL(l, qlm), lanex_pwr_ctrl.u64);
- /* --Setting AGC in manual mode and configuring CTLE-- */
- rx_cfg_5.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_CFG_5(l, qlm));
- rx_cfg_5.s.rx_agc_men_ovrrd_val = 1;
- rx_cfg_5.s.rx_agc_men_ovrrd_en = 1;
- csr_wr_node(node, CVMX_GSERX_LANEX_RX_CFG_5(l, qlm), rx_cfg_5.u64);
- ctle_ctrl.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_CTLE_CTRL(l, qlm));
- ctle_ctrl.s.pcs_sds_rx_ctle_zero = ctle_zero;
- csr_wr_node(node, CVMX_GSERX_LANEX_RX_CTLE_CTRL(l, qlm), ctle_ctrl.u64);
- rx_cfg_2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_CFG_2(l, qlm));
- rx_cfg_2.s.rx_sds_rx_agc_mval = (agc_pre_ctle << 4) | agc_post_ctle;
- csr_wr_node(node, CVMX_GSERX_LANEX_RX_CFG_2(l, qlm), rx_cfg_2.u64);
- }
- return 0;
- }
- /**
- * Some QLM speeds need to override the default tuning parameters
- *
- * @param node Node to configure
- * @param qlm QLM to configure
- * @param baud_mhz Desired speed in MHz
- * @param lane Lane the apply the tuning parameters
- * @param tx_swing Voltage swing. The higher the value the lower the voltage,
- * the default value is 7.
- * @param tx_pre pre-cursor pre-emphasis
- * @param tx_post post-cursor pre-emphasis.
- * @param tx_gain Transmit gain. Range 0-7
- * @param tx_vboost Transmit voltage boost. Range 0-1
- */
- void octeon_qlm_tune_per_lane_v3(int node, int qlm, int baud_mhz, int lane, int tx_swing,
- int tx_pre, int tx_post, int tx_gain, int tx_vboost)
- {
- cvmx_gserx_cfg_t gserx_cfg;
- cvmx_gserx_lanex_tx_cfg_0_t tx_cfg0;
- cvmx_gserx_lanex_tx_pre_emphasis_t pre_emphasis;
- cvmx_gserx_lanex_tx_cfg_1_t tx_cfg1;
- cvmx_gserx_lanex_tx_cfg_3_t tx_cfg3;
- cvmx_bgxx_spux_br_pmd_control_t pmd_control;
- cvmx_gserx_lanex_pcs_ctlifc_0_t pcs_ctlifc_0;
- cvmx_gserx_lanex_pcs_ctlifc_2_t pcs_ctlifc_2;
- int bgx, lmac;
- /* Do not apply QLM tuning to PCIe and KR interfaces. */
- gserx_cfg.u64 = csr_rd_node(node, CVMX_GSERX_CFG(qlm));
- if (gserx_cfg.s.pcie)
- return;
- /* Apply the QLM tuning only to cn73xx and cn78xx models only */
- if (OCTEON_IS_MODEL(OCTEON_CN78XX))
- bgx = (qlm < 2) ? qlm : (qlm - 2);
- else if (OCTEON_IS_MODEL(OCTEON_CN73XX))
- bgx = (qlm < 4) ? (qlm - 2) : 2;
- else if (OCTEON_IS_MODEL(OCTEON_CNF75XX))
- bgx = 0;
- else
- return;
- if ((OCTEON_IS_MODEL(OCTEON_CN73XX) && qlm == 6) ||
- (OCTEON_IS_MODEL(OCTEON_CNF75XX) && qlm == 5))
- lmac = 2;
- else
- lmac = lane;
- /* No need to tune 10G-KR and 40G-KR interfaces */
- pmd_control.u64 = csr_rd_node(node, CVMX_BGXX_SPUX_BR_PMD_CONTROL(lmac, bgx));
- if (pmd_control.s.train_en)
- return;
- if (tx_pre != -1 && tx_post == -1)
- tx_post = 0;
- if (tx_post != -1 && tx_pre == -1)
- tx_pre = 0;
- /* Check tuning constraints */
- if (tx_swing < -1 || tx_swing > 25) {
- printf("ERROR: N%d:QLM%d: Lane %d: Invalid TX_SWING(%d). TX_SWING must be <= 25.\n",
- node, qlm, lane, tx_swing);
- return;
- }
- if (tx_pre < -1 || tx_pre > 10) {
- printf("ERROR: N%d:QLM%d: Lane %d: Invalid TX_PRE(%d). TX_PRE must be <= 10.\n",
- node, qlm, lane, tx_swing);
- return;
- }
- if (tx_post < -1 || tx_post > 31) {
- printf("ERROR: N%d:QLM%d: Lane %d: Invalid TX_POST(%d). TX_POST must be <= 15.\n",
- node, qlm, lane, tx_swing);
- return;
- }
- if (tx_pre >= 0 && tx_post >= 0 && tx_swing >= 0 &&
- tx_pre + tx_post - tx_swing > 2) {
- printf("ERROR: N%d.QLM%d: Lane %d: TX_PRE(%d) + TX_POST(%d) - TX_SWING(%d) must be <= 2\n",
- node, qlm, lane, tx_pre, tx_post, tx_swing);
- return;
- }
- if (tx_pre >= 0 && tx_post >= 0 && tx_swing >= 0 &&
- tx_pre + tx_post + tx_swing > 35) {
- printf("ERROR: N%d.QLM%d: Lane %d: TX_PRE(%d) + TX_POST(%d) + TX_SWING(%d) must be <= 35\n",
- node, qlm, lane, tx_pre, tx_post, tx_swing);
- return;
- }
- if (tx_gain < -1 || tx_gain > 7) {
- printf("ERROR: N%d.QLM%d: Lane %d: Invalid TX_GAIN(%d). TX_GAIN must be between 0 and 7\n",
- node, qlm, lane, tx_gain);
- return;
- }
- if (tx_vboost < -1 || tx_vboost > 1) {
- printf("ERROR: N%d.QLM%d: Lane %d: Invalid TX_VBOOST(%d). TX_VBOOST must be 0 or 1.\n",
- node, qlm, lane, tx_vboost);
- return;
- }
- debug("N%d.QLM%d: Lane %d: TX_SWING=%d, TX_PRE=%d, TX_POST=%d, TX_GAIN=%d, TX_VBOOST=%d\n",
- node, qlm, lane, tx_swing, tx_pre, tx_post, tx_gain, tx_vboost);
- /* Complete the Tx swing and Tx equilization programming */
- /* 1) Enable Tx swing and Tx emphasis overrides */
- tx_cfg1.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_TX_CFG_1(lane, qlm));
- tx_cfg1.s.tx_swing_ovrrd_en = (tx_swing != -1);
- tx_cfg1.s.tx_premptap_ovrrd_val = (tx_pre != -1) && (tx_post != -1);
- tx_cfg1.s.tx_vboost_en_ovrrd_en = (tx_vboost != -1); /* Vboost override */
- ;
- csr_wr_node(node, CVMX_GSERX_LANEX_TX_CFG_1(lane, qlm), tx_cfg1.u64);
- /* 2) Program the Tx swing and Tx emphasis Pre-cursor and Post-cursor values */
- /* CFG_TX_PREMPTAP[8:4] = Lane X's TX post-cursor value (C+1) */
- /* CFG_TX_PREMPTAP[3:0] = Lane X's TX pre-cursor value (C-1) */
- if (tx_swing != -1) {
- tx_cfg0.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_TX_CFG_0(lane, qlm));
- tx_cfg0.s.cfg_tx_swing = tx_swing;
- csr_wr_node(node, CVMX_GSERX_LANEX_TX_CFG_0(lane, qlm), tx_cfg0.u64);
- }
- if ((tx_pre != -1) && (tx_post != -1)) {
- pre_emphasis.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_TX_PRE_EMPHASIS(lane, qlm));
- pre_emphasis.s.cfg_tx_premptap = (tx_post << 4) | tx_pre;
- csr_wr_node(node, CVMX_GSERX_LANEX_TX_PRE_EMPHASIS(lane, qlm), pre_emphasis.u64);
- }
- /* Apply TX gain settings */
- if (tx_gain != -1) {
- tx_cfg3.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_TX_CFG_3(lane, qlm));
- tx_cfg3.s.pcs_sds_tx_gain = tx_gain;
- csr_wr_node(node, CVMX_GSERX_LANEX_TX_CFG_3(lane, qlm), tx_cfg3.u64);
- }
- /* Apply TX vboot settings */
- if (tx_vboost != -1) {
- tx_cfg3.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_TX_CFG_3(lane, qlm));
- tx_cfg3.s.cfg_tx_vboost_en = tx_vboost;
- csr_wr_node(node, CVMX_GSERX_LANEX_TX_CFG_3(lane, qlm), tx_cfg3.u64);
- }
- /* 3) Program override for the Tx coefficient request */
- pcs_ctlifc_0.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_0(lane, qlm));
- if (((tx_pre != -1) && (tx_post != -1)) || (tx_swing != -1))
- pcs_ctlifc_0.s.cfg_tx_coeff_req_ovrrd_val = 0x1;
- if (tx_vboost != -1)
- pcs_ctlifc_0.s.cfg_tx_vboost_en_ovrrd_val = 1;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_0(lane, qlm), pcs_ctlifc_0.u64);
- /* 4) Enable the Tx coefficient request override enable */
- pcs_ctlifc_2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));
- if (((tx_pre != -1) && (tx_post != -1)) || (tx_swing != -1))
- pcs_ctlifc_2.s.cfg_tx_coeff_req_ovrrd_en = 0x1;
- if (tx_vboost != -1)
- pcs_ctlifc_2.s.cfg_tx_vboost_en_ovrrd_en = 1;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), pcs_ctlifc_2.u64);
- /* 5) Issue a Control Interface Configuration Override request to start the Tx equalizer */
- pcs_ctlifc_2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));
- pcs_ctlifc_2.s.ctlifc_ovrrd_req = 0x1;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), pcs_ctlifc_2.u64);
- /* 6) Wait 1 ms for the request to complete */
- udelay(1000);
- /* Steps 7 & 8 required for subsequent Tx swing and Tx equilization adjustment */
- /* 7) Disable the Tx coefficient request override enable */
- pcs_ctlifc_2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));
- pcs_ctlifc_2.s.cfg_tx_coeff_req_ovrrd_en = 0;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), pcs_ctlifc_2.u64);
- /* 8) Issue a Control Interface Configuration Override request */
- pcs_ctlifc_2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));
- pcs_ctlifc_2.s.ctlifc_ovrrd_req = 0x1;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), pcs_ctlifc_2.u64);
- }
- /**
- * Some QLM speeds need to override the default tuning parameters
- *
- * @param node Node to configure
- * @param qlm QLM to configure
- * @param baud_mhz Desired speed in MHz
- * @param tx_swing Voltage swing. The higher the value the lower the voltage,
- * the default value is 7.
- * @param tx_premptap bits [0:3] pre-cursor pre-emphasis, bits[4:8] post-cursor
- * pre-emphasis.
- * @param tx_gain Transmit gain. Range 0-7
- * @param tx_vboost Transmit voltage boost. Range 0-1
- *
- */
- void octeon_qlm_tune_v3(int node, int qlm, int baud_mhz, int tx_swing, int tx_premptap, int tx_gain,
- int tx_vboost)
- {
- int lane;
- int num_lanes = cvmx_qlm_get_lanes(qlm);
- for (lane = 0; lane < num_lanes; lane++) {
- int tx_pre = (tx_premptap == -1) ? -1 : tx_premptap & 0xf;
- int tx_post = (tx_premptap == -1) ? -1 : (tx_premptap >> 4) & 0x1f;
- octeon_qlm_tune_per_lane_v3(node, qlm, baud_mhz, lane, tx_swing, tx_pre, tx_post,
- tx_gain, tx_vboost);
- }
- }
- /**
- * Some QLMs need to override the default pre-ctle for low loss channels.
- *
- * @param node Node to configure
- * @param qlm QLM to configure
- * @param pre_ctle pre-ctle settings for low loss channels
- */
- void octeon_qlm_set_channel_v3(int node, int qlm, int pre_ctle)
- {
- cvmx_gserx_lane_vma_fine_ctrl_2_t lane_vma_fine_ctrl_2;
- lane_vma_fine_ctrl_2.u64 = csr_rd_node(node, CVMX_GSERX_LANE_VMA_FINE_CTRL_2(qlm));
- lane_vma_fine_ctrl_2.s.rx_prectle_gain_min_fine = pre_ctle;
- csr_wr_node(node, CVMX_GSERX_LANE_VMA_FINE_CTRL_2(qlm), lane_vma_fine_ctrl_2.u64);
- }
- static void __qlm_init_errata_20844(int node, int qlm)
- {
- int lane;
- /* Only applies to CN78XX pass 1.x */
- if (!OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0))
- return;
- /* Errata GSER-20844: Electrical Idle logic can coast
- * 1) After the link first comes up write the following
- * register on each lane to prevent the application logic
- * from stomping on the Coast inputs. This is a one time write,
- * or if you prefer you could put it in the link up loop and
- * write it every time the link comes up.
- * 1a) Then write GSER(0..13)_LANE(0..3)_PCS_CTLIFC_2
- * Set CTLIFC_OVRRD_REQ (later)
- * Set CFG_RX_CDR_COAST_REQ_OVRRD_EN
- * Its not clear if #1 and #1a can be combined, lets try it
- * this way first.
- */
- for (lane = 0; lane < 4; lane++) {
- cvmx_gserx_lanex_rx_misc_ovrrd_t misc_ovrrd;
- cvmx_gserx_lanex_pcs_ctlifc_2_t ctlifc_2;
- ctlifc_2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));
- ctlifc_2.s.cfg_rx_cdr_coast_req_ovrrd_en = 1;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), ctlifc_2.u64);
- misc_ovrrd.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_MISC_OVRRD(lane, qlm));
- misc_ovrrd.s.cfg_rx_eie_det_ovrrd_en = 1;
- misc_ovrrd.s.cfg_rx_eie_det_ovrrd_val = 0;
- csr_wr_node(node, CVMX_GSERX_LANEX_RX_MISC_OVRRD(lane, qlm), misc_ovrrd.u64);
- udelay(1);
- misc_ovrrd.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_MISC_OVRRD(lane, qlm));
- misc_ovrrd.s.cfg_rx_eie_det_ovrrd_en = 1;
- misc_ovrrd.s.cfg_rx_eie_det_ovrrd_val = 1;
- csr_wr_node(node, CVMX_GSERX_LANEX_RX_MISC_OVRRD(lane, qlm), misc_ovrrd.u64);
- ctlifc_2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm));
- ctlifc_2.s.ctlifc_ovrrd_req = 1;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(lane, qlm), ctlifc_2.u64);
- }
- }
- /** CN78xx reference clock register settings */
- struct refclk_settings_cn78xx {
- bool valid; /** Reference clock speed supported */
- union cvmx_gserx_pll_px_mode_0 mode_0;
- union cvmx_gserx_pll_px_mode_1 mode_1;
- union cvmx_gserx_lane_px_mode_0 pmode_0;
- union cvmx_gserx_lane_px_mode_1 pmode_1;
- };
- /** Default reference clock for various modes */
- static const u8 def_ref_clk_cn78xx[R_NUM_LANE_MODES] = { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 };
- /**
- * This data structure stores the reference clock for each mode for each QLM.
- *
- * It is indexed first by the node number, then the QLM number and then the
- * lane mode. It is initialized to the default values.
- */
- static u8 ref_clk_cn78xx[CVMX_MAX_NODES][8][R_NUM_LANE_MODES] = {
- { { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 } },
- { { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 } },
- { { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 } },
- { { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
- { 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1 } }
- };
- /**
- * This data structure contains the register values for the cn78xx PLLs
- * It is indexed first by the reference clock and second by the mode.
- * Note that not all combinations are supported.
- */
- static const struct refclk_settings_cn78xx refclk_settings_cn78xx[R_NUM_LANE_MODES][4] = {
- { /* 0 R_2_5G_REFCLK100 */
- { /* 100MHz reference clock */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x4, .pll_rloop = 0x3, .pll_pcs_div = 0x5 },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x19 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x1,
- .tx_ldiv = 0x1,
- .rx_ldiv = 0x1,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x1,
- .cdr_fgain = 0xa,
- .ph_acc_adj = 0x14 } },
- { /* 125MHz reference clock */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0x5 },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x1,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x14 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x1,
- .tx_ldiv = 0x1,
- .rx_ldiv = 0x1,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x1,
- .cdr_fgain = 0xa,
- .ph_acc_adj = 0x14 } },
- { /* 156.25MHz reference clock */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0x5 },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x10 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x1,
- .tx_ldiv = 0x1,
- .rx_ldiv = 0x1,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x1,
- .cdr_fgain = 0xa,
- .ph_acc_adj = 0x14 } },
- {
- /* 161.1328125MHz reference clock */
- .valid = false,
- } },
- {
- /* 1 R_5G_REFCLK100 */
- { /* 100MHz reference clock */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x4, .pll_rloop = 0x3, .pll_pcs_div = 0xa },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x19 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x1,
- .tx_ldiv = 0x0,
- .rx_ldiv = 0x0,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x0,
- .cdr_fgain = 0xa,
- .ph_acc_adj = 0x14 } },
- { /* 125MHz reference clock */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0xa },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x1,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x14 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x1,
- .tx_ldiv = 0x0,
- .rx_ldiv = 0x0,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x0,
- .cdr_fgain = 0xa,
- .ph_acc_adj = 0x14 } },
- { /* 156.25MHz reference clock */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0xa },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x10 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x1,
- .tx_ldiv = 0x0,
- .rx_ldiv = 0x0,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x0,
- .cdr_fgain = 0xa,
- .ph_acc_adj = 0x14 } },
- {
- /* 161.1328125MHz reference clock */
- .valid = false,
- },
- },
- { /* 2 R_8G_REFCLK100 */
- { /* 100MHz reference clock */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x5, .pll_pcs_div = 0xa },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x1,
- .pll_opr = 0x1,
- .pll_div = 0x28 },
- .pmode_0.s = { .ctle = 0x3,
- .pcie = 0x0,
- .tx_ldiv = 0x0,
- .rx_ldiv = 0x0,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x0,
- .cdr_fgain = 0xb,
- .ph_acc_adj = 0x23 } },
- { /* 125MHz reference clock */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x2, .pll_rloop = 0x5, .pll_pcs_div = 0xa },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x1,
- .pll_pcie3en = 0x1,
- .pll_opr = 0x1,
- .pll_div = 0x20 },
- .pmode_0.s = { .ctle = 0x3,
- .pcie = 0x0,
- .tx_ldiv = 0x0,
- .rx_ldiv = 0x0,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x0,
- .cdr_fgain = 0xb,
- .ph_acc_adj = 0x23 } },
- { /* 156.25MHz reference clock not supported */
- .valid = false } },
- {
- /* 3 R_125G_REFCLK15625_KX */
- { /* 100MHz reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0x28 },
- .mode_1.s = { .pll_16p5en = 0x1,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x19 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x0,
- .tx_ldiv = 0x2,
- .rx_ldiv = 0x2,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x1,
- .cdr_fgain = 0xc,
- .ph_acc_adj = 0x1e } },
- { /* 125MHz reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0x28 },
- .mode_1.s = { .pll_16p5en = 0x1,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x14 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x0,
- .tx_ldiv = 0x2,
- .rx_ldiv = 0x2,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x1,
- .cdr_fgain = 0xc,
- .ph_acc_adj = 0x1e } },
- { /* 156.25MHz reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0x28 },
- .mode_1.s = { .pll_16p5en = 0x1,
- .pll_cpadj = 0x3,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x10 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x0,
- .tx_ldiv = 0x2,
- .rx_ldiv = 0x2,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x1,
- .cdr_fgain = 0xc,
- .ph_acc_adj = 0x1e } },
- {
- /* 161.1328125MHz reference clock */
- .valid = false,
- },
- },
- { /* 4 R_3125G_REFCLK15625_XAUI */
- { /* 100MHz reference */
- .valid = false },
- { /* 125MHz reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0x14 },
- .mode_1.s = { .pll_16p5en = 0x1,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x19 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x0,
- .tx_ldiv = 0x1,
- .rx_ldiv = 0x1,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x1,
- .cdr_fgain = 0xc,
- .ph_acc_adj = 0x1e } },
- { /* 156.25MHz reference, default */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0x14 },
- .mode_1.s = { .pll_16p5en = 0x1,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x14 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x0,
- .tx_ldiv = 0x1,
- .rx_ldiv = 0x1,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x1,
- .cdr_fgain = 0xc,
- .ph_acc_adj = 0x1e } },
- {
- /* 161.1328125MHz reference clock */
- .valid = false,
- } },
- { /* 5 R_103125G_REFCLK15625_KR */
- { /* 100MHz reference */
- .valid = false },
- { /* 125MHz reference */
- .valid = false },
- { /* 156.25MHz reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x5, .pll_pcs_div = 0xa },
- .mode_1.s = { .pll_16p5en = 0x1,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x1,
- .pll_div = 0x21 },
- .pmode_0.s = { .ctle = 0x3,
- .pcie = 0x0,
- .tx_ldiv = 0x0,
- .rx_ldiv = 0x0,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x1,
- .vma_mm = 0x0,
- .cdr_fgain = 0xa,
- .ph_acc_adj = 0xf } },
- { /* 161.1328125 reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x5, .pll_pcs_div = 0xa },
- .mode_1.s = { .pll_16p5en = 0x1,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x1,
- .pll_div = 0x20 },
- .pmode_0.s = { .ctle = 0x3,
- .pcie = 0x0,
- .tx_ldiv = 0x0,
- .rx_ldiv = 0x0,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x1,
- .vma_mm = 0x0,
- .cdr_fgain = 0xa,
- .ph_acc_adj = 0xf } } },
- { /* 6 R_125G_REFCLK15625_SGMII */
- { /* 100MHz reference clock */
- .valid = 1,
- .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0x28 },
- .mode_1.s = { .pll_16p5en = 0x1,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x19 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x0,
- .tx_ldiv = 0x2,
- .rx_ldiv = 0x2,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x1,
- .cdr_fgain = 0xc,
- .ph_acc_adj = 0x1e } },
- { /* 125MHz reference clock */
- .valid = 1,
- .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0x28 },
- .mode_1.s = { .pll_16p5en = 0x1,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x14 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x0,
- .tx_ldiv = 0x2,
- .rx_ldiv = 0x2,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x0,
- .cdr_fgain = 0xc,
- .ph_acc_adj = 0x1e } },
- { /* 156.25MHz reference clock */
- .valid = 1,
- .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0x28 },
- .mode_1.s = { .pll_16p5en = 0x1,
- .pll_cpadj = 0x3,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x10 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x0,
- .tx_ldiv = 0x2,
- .rx_ldiv = 0x2,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x1,
- .cdr_fgain = 0xc,
- .ph_acc_adj = 0x1e } } },
- { /* 7 R_5G_REFCLK15625_QSGMII */
- { /* 100MHz reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x4, .pll_rloop = 0x3, .pll_pcs_div = 0xa },
- .mode_1.s = { .pll_16p5en = 0x0, .pll_cpadj = 0x2, .pll_pcie3en = 0x0,
- .pll_div = 0x19 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x0,
- .tx_ldiv = 0x0,
- .rx_ldiv = 0x0,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x1,
- .cdr_fgain = 0xc,
- .ph_acc_adj = 0x1e } },
- { /* 125MHz reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0xa },
- .mode_1.s = { .pll_16p5en = 0x0, .pll_cpadj = 0x1, .pll_pcie3en = 0x0,
- .pll_div = 0x14 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x0,
- .tx_ldiv = 0x0,
- .rx_ldiv = 0x0,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x1,
- .cdr_fgain = 0xc,
- .ph_acc_adj = 0x1e } },
- { /* 156.25MHz reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0xa },
- .mode_1.s = { .pll_16p5en = 0x0, .pll_cpadj = 0x2, .pll_pcie3en = 0x0,
- .pll_div = 0x10 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x0,
- .tx_ldiv = 0x0,
- .rx_ldiv = 0x0,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x1,
- .cdr_fgain = 0xc,
- .ph_acc_adj = 0x1e } },
- {
- /* 161.1328125MHz reference clock */
- .valid = false,
- } },
- { /* 8 R_625G_REFCLK15625_RXAUI */
- { /* 100MHz reference */
- .valid = false },
- { /* 125MHz reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0xa },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x19 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x0,
- .tx_ldiv = 0x0,
- .rx_ldiv = 0x0,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x0,
- .cdr_fgain = 0xa,
- .ph_acc_adj = 0x14 } },
- { /* 156.25MHz reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0xa },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x14 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x0,
- .tx_ldiv = 0x0,
- .rx_ldiv = 0x0,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x0,
- .cdr_fgain = 0xa,
- .ph_acc_adj = 0x14 } },
- { /* 161.1328125 reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x1, .pll_rloop = 0x3, .pll_pcs_div = 0xa },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x14 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x0,
- .tx_ldiv = 0x0,
- .rx_ldiv = 0x0,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x0,
- .cdr_fgain = 0xa,
- .ph_acc_adj = 0x14 } } },
- { /* 9 R_2_5G_REFCLK125 */
- { /* 100MHz reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x4, .pll_rloop = 0x3, .pll_pcs_div = 0x5 },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x19 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x1,
- .tx_ldiv = 0x1,
- .rx_ldiv = 0x1,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x1,
- .cdr_fgain = 0xa,
- .ph_acc_adj = 0x14 } },
- { /* 125MHz reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0x5 },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x1,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x14 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x1,
- .tx_ldiv = 0x1,
- .rx_ldiv = 0x1,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x1,
- .cdr_fgain = 0xa,
- .ph_acc_adj = 0x14 } },
- { /* 156,25MHz reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0x5 },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x10 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x1,
- .tx_ldiv = 0x1,
- .rx_ldiv = 0x1,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x1,
- .cdr_fgain = 0xa,
- .ph_acc_adj = 0x14 } },
- {
- /* 161.1328125MHz reference clock */
- .valid = false,
- } },
- { /* 0xa R_5G_REFCLK125 */
- { /* 100MHz reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x4, .pll_rloop = 0x3, .pll_pcs_div = 0xa },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x19 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x1,
- .tx_ldiv = 0x0,
- .rx_ldiv = 0x0,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x0,
- .cdr_fgain = 0xa,
- .ph_acc_adj = 0x14 } },
- { /* 125MHz reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0xa },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x1,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x14 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x1,
- .tx_ldiv = 0x0,
- .rx_ldiv = 0x0,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x0,
- .cdr_fgain = 0xa,
- .ph_acc_adj = 0x14 } },
- { /* 156.25MHz reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x3, .pll_pcs_div = 0xa },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x0,
- .pll_opr = 0x0,
- .pll_div = 0x10 },
- .pmode_0.s = { .ctle = 0x0,
- .pcie = 0x1,
- .tx_ldiv = 0x0,
- .rx_ldiv = 0x0,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x0,
- .cdr_fgain = 0xa,
- .ph_acc_adj = 0x14 } },
- {
- /* 161.1328125MHz reference clock */
- .valid = false,
- } },
- { /* 0xb R_8G_REFCLK125 */
- { /* 100MHz reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x3, .pll_rloop = 0x5, .pll_pcs_div = 0xa },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x2,
- .pll_pcie3en = 0x1,
- .pll_opr = 0x1,
- .pll_div = 0x28 },
- .pmode_0.s = { .ctle = 0x3,
- .pcie = 0x0,
- .tx_ldiv = 0x0,
- .rx_ldiv = 0x0,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x0,
- .cdr_fgain = 0xb,
- .ph_acc_adj = 0x23 } },
- { /* 125MHz reference */
- .valid = true,
- .mode_0.s = { .pll_icp = 0x2, .pll_rloop = 0x5, .pll_pcs_div = 0xa },
- .mode_1.s = { .pll_16p5en = 0x0,
- .pll_cpadj = 0x1,
- .pll_pcie3en = 0x1,
- .pll_opr = 0x1,
- .pll_div = 0x20 },
- .pmode_0.s = { .ctle = 0x3,
- .pcie = 0x0,
- .tx_ldiv = 0x0,
- .rx_ldiv = 0x0,
- .srate = 0x0,
- .tx_mode = 0x3,
- .rx_mode = 0x3 },
- .pmode_1.s = { .vma_fine_cfg_sel = 0x0,
- .vma_mm = 0x0,
- .cdr_fgain = 0xb,
- .ph_acc_adj = 0x23 } },
- { /* 156.25MHz reference */
- .valid = false },
- {
- /* 161.1328125MHz reference clock */
- .valid = false,
- } }
- };
- /**
- * Set a non-standard reference clock for a node, qlm and lane mode.
- *
- * @INTERNAL
- *
- * @param node node number the reference clock is used with
- * @param qlm qlm number the reference clock is hooked up to
- * @param lane_mode current lane mode selected for the QLM
- * @param ref_clk_sel 0 = 100MHz, 1 = 125MHz, 2 = 156.25MHz,
- * 3 = 161.1328125MHz
- *
- * Return: 0 for success or -1 if the reference clock selector is not supported
- *
- * NOTE: This must be called before __qlm_setup_pll_cn78xx.
- */
- static int __set_qlm_ref_clk_cn78xx(int node, int qlm, int lane_mode, int ref_clk_sel)
- {
- if (ref_clk_sel > 3 || ref_clk_sel < 0 ||
- !refclk_settings_cn78xx[lane_mode][ref_clk_sel].valid) {
- debug("%s: Invalid reference clock %d for lane mode %d for node %d, QLM %d\n",
- __func__, ref_clk_sel, lane_mode, node, qlm);
- return -1;
- }
- debug("%s(%d, %d, 0x%x, %d)\n", __func__, node, qlm, lane_mode, ref_clk_sel);
- ref_clk_cn78xx[node][qlm][lane_mode] = ref_clk_sel;
- return 0;
- }
- /**
- * KR - Inverted Tx Coefficient Direction Change. Changing Pre & Post Tap inc/dec direction
- *
- *
- * @INTERNAL
- *
- * @param node Node number to configure
- * @param qlm QLM number to configure
- */
- static void __qlm_kr_inc_dec_gser26636(int node, int qlm)
- {
- cvmx_gserx_rx_txdir_ctrl_1_t rx_txdir_ctrl;
- /* Apply workaround for Errata GSER-26636,
- * KR training coefficient update inverted
- */
- rx_txdir_ctrl.u64 = csr_rd_node(node, CVMX_GSERX_RX_TXDIR_CTRL_1(qlm));
- rx_txdir_ctrl.s.rx_precorr_chg_dir = 1;
- rx_txdir_ctrl.s.rx_tap1_chg_dir = 1;
- csr_wr_node(node, CVMX_GSERX_RX_TXDIR_CTRL_1(qlm), rx_txdir_ctrl.u64);
- }
- /**
- * Updating the RX EQ settings to support wider temperature range
- * @INTERNAL
- *
- * @param node Node number to configure
- * @param qlm QLM number to configure
- */
- static void __qlm_rx_eq_temp_gser27140(int node, int qlm)
- {
- int lane;
- int num_lanes = cvmx_qlm_get_lanes(qlm);
- cvmx_gserx_lanex_rx_valbbd_ctrl_0_t rx_valbbd_ctrl_0;
- cvmx_gserx_lane_vma_fine_ctrl_2_t lane_vma_fine_ctrl_2;
- cvmx_gserx_lane_vma_fine_ctrl_0_t lane_vma_fine_ctrl_0;
- cvmx_gserx_rx_txdir_ctrl_1_t rx_txdir_ctrl_1;
- cvmx_gserx_eq_wait_time_t eq_wait_time;
- cvmx_gserx_rx_txdir_ctrl_2_t rx_txdir_ctrl_2;
- cvmx_gserx_rx_txdir_ctrl_0_t rx_txdir_ctrl_0;
- for (lane = 0; lane < num_lanes; lane++) {
- rx_valbbd_ctrl_0.u64 =
- csr_rd_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_0(lane, qlm));
- rx_valbbd_ctrl_0.s.agc_gain = 3;
- rx_valbbd_ctrl_0.s.dfe_gain = 2;
- csr_wr_node(node, CVMX_GSERX_LANEX_RX_VALBBD_CTRL_0(lane, qlm),
- rx_valbbd_ctrl_0.u64);
- }
- /* do_pre_ctle_limits_work_around: */
- lane_vma_fine_ctrl_2.u64 = csr_rd_node(node, CVMX_GSERX_LANE_VMA_FINE_CTRL_2(qlm));
- //lane_vma_fine_ctrl_2.s.rx_prectle_peak_max_fine = 11;
- lane_vma_fine_ctrl_2.s.rx_prectle_gain_max_fine = 11;
- //lane_vma_fine_ctrl_2.s.rx_prectle_peak_min_fine = 6;
- lane_vma_fine_ctrl_2.s.rx_prectle_gain_min_fine = 6;
- csr_wr_node(node, CVMX_GSERX_LANE_VMA_FINE_CTRL_2(qlm), lane_vma_fine_ctrl_2.u64);
- /* do_inc_dec_thres_work_around: */
- rx_txdir_ctrl_0.u64 = csr_rd_node(node, CVMX_GSERX_RX_TXDIR_CTRL_0(qlm));
- rx_txdir_ctrl_0.s.rx_boost_hi_thrs = 11;
- rx_txdir_ctrl_0.s.rx_boost_lo_thrs = 4;
- rx_txdir_ctrl_0.s.rx_boost_hi_val = 15;
- csr_wr_node(node, CVMX_GSERX_RX_TXDIR_CTRL_0(qlm), rx_txdir_ctrl_0.u64);
- /* do_sdll_iq_work_around: */
- lane_vma_fine_ctrl_0.u64 = csr_rd_node(node, CVMX_GSERX_LANE_VMA_FINE_CTRL_0(qlm));
- lane_vma_fine_ctrl_0.s.rx_sdll_iq_max_fine = 14;
- lane_vma_fine_ctrl_0.s.rx_sdll_iq_min_fine = 8;
- lane_vma_fine_ctrl_0.s.rx_sdll_iq_step_fine = 2;
- /* do_vma_window_work_around_2: */
- lane_vma_fine_ctrl_0.s.vma_window_wait_fine = 5;
- lane_vma_fine_ctrl_0.s.lms_wait_time_fine = 5;
- csr_wr_node(node, CVMX_GSERX_LANE_VMA_FINE_CTRL_0(qlm), lane_vma_fine_ctrl_0.u64);
- /* Set dfe_tap_1_lo_thres_val: */
- rx_txdir_ctrl_1.u64 = csr_rd_node(node, CVMX_GSERX_RX_TXDIR_CTRL_1(qlm));
- rx_txdir_ctrl_1.s.rx_tap1_lo_thrs = 8;
- rx_txdir_ctrl_1.s.rx_tap1_hi_thrs = 0x17;
- csr_wr_node(node, CVMX_GSERX_RX_TXDIR_CTRL_1(qlm), rx_txdir_ctrl_1.u64);
- /* do_rxeq_wait_cnt_work_around: */
- eq_wait_time.u64 = csr_rd_node(node, CVMX_GSERX_EQ_WAIT_TIME(qlm));
- eq_wait_time.s.rxeq_wait_cnt = 6;
- csr_wr_node(node, CVMX_GSERX_EQ_WAIT_TIME(qlm), eq_wait_time.u64);
- /* do_write_rx_txdir_precorr_thresholds: */
- rx_txdir_ctrl_2.u64 = csr_rd_node(node, CVMX_GSERX_RX_TXDIR_CTRL_2(qlm));
- rx_txdir_ctrl_2.s.rx_precorr_hi_thrs = 0xc0;
- rx_txdir_ctrl_2.s.rx_precorr_lo_thrs = 0x40;
- csr_wr_node(node, CVMX_GSERX_RX_TXDIR_CTRL_2(qlm), rx_txdir_ctrl_2.u64);
- }
- /* Errata GSER-26150: 10G PHY PLL Temperature Failure
- * This workaround must be completed after the final deassertion of
- * GSERx_PHY_CTL[PHY_RESET]
- */
- static int __qlm_errata_gser_26150(int node, int qlm, int is_pcie)
- {
- int num_lanes = 4;
- int i;
- cvmx_gserx_glbl_pll_cfg_3_t pll_cfg_3;
- cvmx_gserx_glbl_misc_config_1_t misc_config_1;
- /* PCIe only requires the LC-VCO parameters to be updated */
- if (is_pcie) {
- /* Update PLL parameters */
- /* Step 1: Set GSER()_GLBL_PLL_CFG_3[PLL_VCTRL_SEL_LCVCO_VAL] = 0x2, and
- * GSER()_GLBL_PLL_CFG_3[PCS_SDS_PLL_VCO_AMP] = 0
- */
- pll_cfg_3.u64 = csr_rd_node(node, CVMX_GSERX_GLBL_PLL_CFG_3(qlm));
- pll_cfg_3.s.pcs_sds_pll_vco_amp = 0;
- pll_cfg_3.s.pll_vctrl_sel_lcvco_val = 2;
- csr_wr_node(node, CVMX_GSERX_GLBL_PLL_CFG_3(qlm), pll_cfg_3.u64);
- /* Step 2: Set GSER()_GLBL_MISC_CONFIG_1[PCS_SDS_TRIM_CHP_REG] = 0x2. */
- misc_config_1.u64 = csr_rd_node(node, CVMX_GSERX_GLBL_MISC_CONFIG_1(qlm));
- misc_config_1.s.pcs_sds_trim_chp_reg = 2;
- csr_wr_node(node, CVMX_GSERX_GLBL_MISC_CONFIG_1(qlm), misc_config_1.u64);
- return 0;
- }
- /* Applying this errata twice causes problems */
- pll_cfg_3.u64 = csr_rd_node(node, CVMX_GSERX_GLBL_PLL_CFG_3(qlm));
- if (pll_cfg_3.s.pll_vctrl_sel_lcvco_val == 0x2)
- return 0;
- /* (GSER-26150) 10 Gb temperature excursions can cause lock failure */
- /* Change the calibration point of the VCO at start up to shift some
- * available range of the VCO from -deltaT direction to the +deltaT
- * ramp direction allowing a greater range of VCO temperatures before
- * experiencing the failure.
- */
- /* Check for DLMs on CN73XX and CNF75XX */
- if (OCTEON_IS_MODEL(OCTEON_CN73XX) && (qlm == 5 || qlm == 6))
- num_lanes = 2;
- /* Put PHY in P2 Power-down state Need to Power down all lanes in a
- * QLM/DLM to force PHY to P2 state
- */
- for (i = 0; i < num_lanes; i++) {
- cvmx_gserx_lanex_pcs_ctlifc_0_t ctlifc0;
- cvmx_gserx_lanex_pcs_ctlifc_1_t ctlifc1;
- cvmx_gserx_lanex_pcs_ctlifc_2_t ctlifc2;
- /* Step 1: Set Set GSER()_LANE(lane_n)_PCS_CTLIFC_0[CFG_TX_PSTATE_REQ_OVERRD_VAL]
- * = 0x3
- * Select P2 power state for Tx lane
- */
- ctlifc0.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_0(i, qlm));
- ctlifc0.s.cfg_tx_pstate_req_ovrrd_val = 0x3;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_0(i, qlm), ctlifc0.u64);
- /* Step 2: Set GSER()_LANE(lane_n)_PCS_CTLIFC_1[CFG_RX_PSTATE_REQ_OVERRD_VAL]
- * = 0x3
- * Select P2 power state for Rx lane
- */
- ctlifc1.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_1(i, qlm));
- ctlifc1.s.cfg_rx_pstate_req_ovrrd_val = 0x3;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_1(i, qlm), ctlifc1.u64);
- /* Step 3: Set GSER()_LANE(lane_n)_PCS_CTLIFC_2[CFG_TX_PSTATE_REQ_OVRRD_EN] = 1
- * Enable Tx power state override and Set
- * GSER()_LANE(lane_n)_PCS_CTLIFC_2[CFG_RX_PSTATE_REQ_OVRRD_EN] = 1
- * Enable Rx power state override
- */
- ctlifc2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm));
- ctlifc2.s.cfg_tx_pstate_req_ovrrd_en = 0x1;
- ctlifc2.s.cfg_rx_pstate_req_ovrrd_en = 0x1;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm), ctlifc2.u64);
- /* Step 4: Set GSER()_LANE(lane_n)_PCS_CTLIFC_2[CTLIFC_OVRRD_REQ] = 1
- * Start the CTLIFC override state machine
- */
- ctlifc2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm));
- ctlifc2.s.ctlifc_ovrrd_req = 0x1;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm), ctlifc2.u64);
- }
- /* Update PLL parameters */
- /* Step 5: Set GSER()_GLBL_PLL_CFG_3[PLL_VCTRL_SEL_LCVCO_VAL] = 0x2, and
- * GSER()_GLBL_PLL_CFG_3[PCS_SDS_PLL_VCO_AMP] = 0
- */
- pll_cfg_3.u64 = csr_rd_node(node, CVMX_GSERX_GLBL_PLL_CFG_3(qlm));
- pll_cfg_3.s.pcs_sds_pll_vco_amp = 0;
- pll_cfg_3.s.pll_vctrl_sel_lcvco_val = 2;
- csr_wr_node(node, CVMX_GSERX_GLBL_PLL_CFG_3(qlm), pll_cfg_3.u64);
- /* Step 6: Set GSER()_GLBL_MISC_CONFIG_1[PCS_SDS_TRIM_CHP_REG] = 0x2. */
- misc_config_1.u64 = csr_rd_node(node, CVMX_GSERX_GLBL_MISC_CONFIG_1(qlm));
- misc_config_1.s.pcs_sds_trim_chp_reg = 2;
- csr_wr_node(node, CVMX_GSERX_GLBL_MISC_CONFIG_1(qlm), misc_config_1.u64);
- /* Wake up PHY and transition to P0 Power-up state to bring-up the lanes,
- * need to wake up all PHY lanes
- */
- for (i = 0; i < num_lanes; i++) {
- cvmx_gserx_lanex_pcs_ctlifc_0_t ctlifc0;
- cvmx_gserx_lanex_pcs_ctlifc_1_t ctlifc1;
- cvmx_gserx_lanex_pcs_ctlifc_2_t ctlifc2;
- /* Step 7: Set GSER()_LANE(lane_n)_PCS_CTLIFC_0[CFG_TX_PSTATE_REQ_OVERRD_VAL] = 0x0
- * Select P0 power state for Tx lane
- */
- ctlifc0.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_0(i, qlm));
- ctlifc0.s.cfg_tx_pstate_req_ovrrd_val = 0x0;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_0(i, qlm), ctlifc0.u64);
- /* Step 8: Set GSER()_LANE(lane_n)_PCS_CTLIFC_1[CFG_RX_PSTATE_REQ_OVERRD_VAL] = 0x0
- * Select P0 power state for Rx lane
- */
- ctlifc1.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_1(i, qlm));
- ctlifc1.s.cfg_rx_pstate_req_ovrrd_val = 0x0;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_1(i, qlm), ctlifc1.u64);
- /* Step 9: Set GSER()_LANE(lane_n)_PCS_CTLIFC_2[CFG_TX_PSTATE_REQ_OVRRD_EN] = 1
- * Enable Tx power state override and Set
- * GSER()_LANE(lane_n)_PCS_CTLIFC_2[CFG_RX_PSTATE_REQ_OVRRD_EN] = 1
- * Enable Rx power state override
- */
- ctlifc2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm));
- ctlifc2.s.cfg_tx_pstate_req_ovrrd_en = 0x1;
- ctlifc2.s.cfg_rx_pstate_req_ovrrd_en = 0x1;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm), ctlifc2.u64);
- /* Step 10: Set GSER()_LANE(lane_n)_PCS_CTLIFC_2[CTLIFC_OVRRD_REQ] = 1
- * Start the CTLIFC override state machine
- */
- ctlifc2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm));
- ctlifc2.s.ctlifc_ovrrd_req = 0x1;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm), ctlifc2.u64);
- }
- /* Step 11: Wait 10 msec */
- mdelay(10);
- /* Release Lane Tx/Rx Power state override enables. */
- for (i = 0; i < num_lanes; i++) {
- cvmx_gserx_lanex_pcs_ctlifc_2_t ctlifc2;
- ctlifc2.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm));
- ctlifc2.s.cfg_tx_pstate_req_ovrrd_en = 0x0;
- ctlifc2.s.cfg_rx_pstate_req_ovrrd_en = 0x0;
- csr_wr_node(node, CVMX_GSERX_LANEX_PCS_CTLIFC_2(i, qlm), ctlifc2.u64);
- }
- /* Step 12: Poll GSER()_PLL_STAT.[PLL_LOCK] = 1
- * Poll and check that PLL is locked
- */
- if (CVMX_WAIT_FOR_FIELD64_NODE(node, CVMX_GSERX_PLL_STAT(qlm), cvmx_gserx_pll_stat_t,
- pll_lock, ==, 1, 10000)) {
- printf("%d:QLM%d: Timeout waiting for GSERX_PLL_STAT[pll_lock]\n", node, qlm);
- return -1;
- }
- /* Step 13: Poll GSER()_QLM_STAT.[RST_RDY] = 1
- * Poll and check that QLM/DLM is Ready
- */
- if (is_pcie == 0 &&
- CVMX_WAIT_FOR_FIELD64_NODE(node, CVMX_GSERX_QLM_STAT(qlm), cvmx_gserx_qlm_stat_t,
- rst_rdy, ==, 1, 10000)) {
- printf("%d:QLM%d: Timeout waiting for GSERX_QLM_STAT[rst_rdy]\n", node, qlm);
- return -1;
- }
- return 0;
- }
- /**
- * Configure all of the PLLs for a particular node and qlm
- * @INTERNAL
- *
- * @param node Node number to configure
- * @param qlm QLM number to configure
- */
- static void __qlm_setup_pll_cn78xx(int node, int qlm)
- {
- cvmx_gserx_pll_px_mode_0_t mode_0;
- cvmx_gserx_pll_px_mode_1_t mode_1;
- cvmx_gserx_lane_px_mode_0_t pmode_0;
- cvmx_gserx_lane_px_mode_1_t pmode_1;
- int lane_mode;
- int ref_clk;
- const struct refclk_settings_cn78xx *clk_settings;
- for (lane_mode = 0; lane_mode < R_NUM_LANE_MODES; lane_mode++) {
- mode_0.u64 = csr_rd_node(node, CVMX_GSERX_PLL_PX_MODE_0(lane_mode, qlm));
- mode_1.u64 = csr_rd_node(node, CVMX_GSERX_PLL_PX_MODE_1(lane_mode, qlm));
- pmode_0.u64 = 0;
- pmode_1.u64 = 0;
- ref_clk = ref_clk_cn78xx[node][qlm][lane_mode];
- clk_settings = &refclk_settings_cn78xx[lane_mode][ref_clk];
- debug("%s(%d, %d): lane_mode: 0x%x, ref_clk: %d\n", __func__, node, qlm, lane_mode,
- ref_clk);
- if (!clk_settings->valid) {
- printf("%s: Error: reference clock %d is not supported for lane mode %d on qlm %d\n",
- __func__, ref_clk, lane_mode, qlm);
- continue;
- }
- mode_0.s.pll_icp = clk_settings->mode_0.s.pll_icp;
- mode_0.s.pll_rloop = clk_settings->mode_0.s.pll_rloop;
- mode_0.s.pll_pcs_div = clk_settings->mode_0.s.pll_pcs_div;
- mode_1.s.pll_16p5en = clk_settings->mode_1.s.pll_16p5en;
- mode_1.s.pll_cpadj = clk_settings->mode_1.s.pll_cpadj;
- mode_1.s.pll_pcie3en = clk_settings->mode_1.s.pll_pcie3en;
- mode_1.s.pll_opr = clk_settings->mode_1.s.pll_opr;
- mode_1.s.pll_div = clk_settings->mode_1.s.pll_div;
- pmode_0.u64 = clk_settings->pmode_0.u64;
- pmode_1.u64 = clk_settings->pmode_1.u64;
- csr_wr_node(node, CVMX_GSERX_PLL_PX_MODE_1(lane_mode, qlm), mode_1.u64);
- csr_wr_node(node, CVMX_GSERX_LANE_PX_MODE_0(lane_mode, qlm), pmode_0.u64);
- csr_wr_node(node, CVMX_GSERX_LANE_PX_MODE_1(lane_mode, qlm), pmode_1.u64);
- csr_wr_node(node, CVMX_GSERX_PLL_PX_MODE_0(lane_mode, qlm), mode_0.u64);
- }
- }
- /**
- * Get the lane mode for the specified node and QLM.
- *
- * @param ref_clk_sel The reference-clock selection to use to configure QLM
- * 0 = REF_100MHZ
- * 1 = REF_125MHZ
- * 2 = REF_156MHZ
- * @param baud_mhz The speed the QLM needs to be configured in Mhz.
- * @param[out] alt_pll_settings If non-NULL this will be set if non-default PLL
- * settings are required for the mode.
- *
- * Return: lane mode to use or -1 on error
- *
- * NOTE: In some modes
- */
- static int __get_lane_mode_for_speed_and_ref_clk(int ref_clk_sel, int baud_mhz,
- bool *alt_pll_settings)
- {
- if (alt_pll_settings)
- *alt_pll_settings = false;
- switch (baud_mhz) {
- case 98304:
- case 49152:
- case 24576:
- case 12288:
- if (ref_clk_sel != 3) {
- printf("Error: Invalid ref clock\n");
- return -1;
- }
- return 0x5;
- case 6144:
- case 3072:
- if (ref_clk_sel != 3) {
- printf("Error: Invalid ref clock\n");
- return -1;
- }
- return 0x8;
- case 1250:
- if (alt_pll_settings)
- *alt_pll_settings = (ref_clk_sel != 2);
- return R_125G_REFCLK15625_SGMII;
- case 2500:
- if (ref_clk_sel == 0)
- return R_2_5G_REFCLK100;
- if (alt_pll_settings)
- *alt_pll_settings = (ref_clk_sel != 1);
- return R_2_5G_REFCLK125;
- case 3125:
- if (ref_clk_sel == 2) {
- return R_3125G_REFCLK15625_XAUI;
- } else if (ref_clk_sel == 1) {
- if (alt_pll_settings)
- *alt_pll_settings = true;
- return R_3125G_REFCLK15625_XAUI;
- }
- printf("Error: Invalid speed\n");
- return -1;
- case 5000:
- if (ref_clk_sel == 0) {
- return R_5G_REFCLK100;
- } else if (ref_clk_sel == 1) {
- if (alt_pll_settings)
- *alt_pll_settings = (ref_clk_sel != 1);
- return R_5G_REFCLK125;
- } else {
- return R_5G_REFCLK15625_QSGMII;
- }
- case 6250:
- if (ref_clk_sel != 0) {
- if (alt_pll_settings)
- *alt_pll_settings = (ref_clk_sel != 2);
- return R_625G_REFCLK15625_RXAUI;
- }
- printf("Error: Invalid speed\n");
- return -1;
- case 6316:
- if (ref_clk_sel != 3) {
- printf("Error: Invalid speed\n");
- } else {
- *alt_pll_settings = true;
- return R_625G_REFCLK15625_RXAUI;
- }
- case 8000:
- if (ref_clk_sel == 0)
- return R_8G_REFCLK100;
- else if (ref_clk_sel == 1)
- return R_8G_REFCLK125;
- printf("Error: Invalid speed\n");
- return -1;
- case 103125:
- if (ref_clk_sel == 3 && alt_pll_settings)
- *alt_pll_settings = true;
- if (ref_clk_sel == 2 || ref_clk_sel == 3)
- return R_103125G_REFCLK15625_KR;
- default:
- printf("Error: Invalid speed\n");
- return -1;
- }
- return -1;
- }
- /*
- * Errata PEM-31375 PEM RSL accesses to PCLK registers can timeout
- * during speed change. Change SLI_WINDOW_CTL[time] to 525us
- */
- static void __set_sli_window_ctl_errata_31375(int node)
- {
- if (OCTEON_IS_MODEL(OCTEON_CN78XX) || OCTEON_IS_MODEL(OCTEON_CN73XX) ||
- OCTEON_IS_MODEL(OCTEON_CNF75XX)) {
- cvmx_sli_window_ctl_t window_ctl;
- window_ctl.u64 = csr_rd_node(node, CVMX_PEXP_SLI_WINDOW_CTL);
- /* Configure SLI_WINDOW_CTL only once */
- if (window_ctl.s.time != 8191)
- return;
- window_ctl.s.time = gd->bus_clk * 525ull / 1000000;
- csr_wr_node(node, CVMX_PEXP_SLI_WINDOW_CTL, window_ctl.u64);
- }
- }
- static void __cvmx_qlm_pcie_errata_ep_cn78xx(int node, int pem)
- {
- cvmx_pciercx_cfg031_t cfg031;
- cvmx_pciercx_cfg032_t cfg032;
- cvmx_pciercx_cfg040_t cfg040;
- cvmx_pemx_cfg_t pemx_cfg;
- cvmx_pemx_on_t pemx_on;
- int low_qlm, high_qlm;
- int qlm, lane;
- u64 start_cycle;
- pemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(pem));
- /* Errata (GSER-21178) PCIe gen3 doesn't work, continued */
- /* Wait for the link to come up as Gen1 */
- printf("PCIe%d: Waiting for EP out of reset\n", pem);
- while (pemx_on.s.pemoor == 0) {
- udelay(1000);
- pemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(pem));
- }
- /* Enable gen3 speed selection */
- printf("PCIe%d: Enabling Gen3 for EP\n", pem);
- /* Force Gen1 for initial link bringup. We'll fix it later */
- pemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(pem));
- pemx_cfg.s.md = 2;
- csr_wr_node(node, CVMX_PEMX_CFG(pem), pemx_cfg.u64);
- cfg031.u32 = cvmx_pcie_cfgx_read_node(node, pem, CVMX_PCIERCX_CFG031(pem));
- cfg031.s.mls = 2;
- cvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG031(pem), cfg031.u32);
- cfg040.u32 = cvmx_pcie_cfgx_read_node(node, pem, CVMX_PCIERCX_CFG040(pem));
- cfg040.s.tls = 3;
- cvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG040(pem), cfg040.u32);
- /* Wait up to 10ms for the link speed change to complete */
- start_cycle = get_timer(0);
- do {
- if (get_timer(start_cycle) > 10)
- return;
- mdelay(1);
- cfg032.u32 = cvmx_pcie_cfgx_read_node(node, pem, CVMX_PCIERCX_CFG032(pem));
- } while (cfg032.s.ls != 3);
- pemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(pem));
- low_qlm = pem; /* FIXME */
- high_qlm = (pemx_cfg.cn78xx.lanes8) ? low_qlm + 1 : low_qlm;
- /* Toggle cfg_rx_dll_locken_ovrrd_en and rx_resetn_ovrrd_en across
- * all QM lanes in use
- */
- for (qlm = low_qlm; qlm <= high_qlm; qlm++) {
- for (lane = 0; lane < 4; lane++) {
- cvmx_gserx_lanex_rx_misc_ovrrd_t misc_ovrrd;
- cvmx_gserx_lanex_pwr_ctrl_t pwr_ctrl;
- misc_ovrrd.u64 =
- csr_rd_node(node, CVMX_GSERX_LANEX_RX_MISC_OVRRD(lane, pem));
- misc_ovrrd.s.cfg_rx_dll_locken_ovrrd_en = 1;
- csr_wr_node(node, CVMX_GSERX_LANEX_RX_MISC_OVRRD(lane, pem),
- misc_ovrrd.u64);
- pwr_ctrl.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PWR_CTRL(lane, pem));
- pwr_ctrl.s.rx_resetn_ovrrd_en = 1;
- csr_wr_node(node, CVMX_GSERX_LANEX_PWR_CTRL(lane, pem), pwr_ctrl.u64);
- }
- }
- for (qlm = low_qlm; qlm <= high_qlm; qlm++) {
- for (lane = 0; lane < 4; lane++) {
- cvmx_gserx_lanex_rx_misc_ovrrd_t misc_ovrrd;
- cvmx_gserx_lanex_pwr_ctrl_t pwr_ctrl;
- misc_ovrrd.u64 =
- csr_rd_node(node, CVMX_GSERX_LANEX_RX_MISC_OVRRD(lane, pem));
- misc_ovrrd.s.cfg_rx_dll_locken_ovrrd_en = 0;
- csr_wr_node(node, CVMX_GSERX_LANEX_RX_MISC_OVRRD(lane, pem),
- misc_ovrrd.u64);
- pwr_ctrl.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PWR_CTRL(lane, pem));
- pwr_ctrl.s.rx_resetn_ovrrd_en = 0;
- csr_wr_node(node, CVMX_GSERX_LANEX_PWR_CTRL(lane, pem), pwr_ctrl.u64);
- }
- }
- //printf("PCIe%d: Waiting for EP link up at Gen3\n", pem);
- if (CVMX_WAIT_FOR_FIELD64_NODE(node, CVMX_PEMX_ON(pem), cvmx_pemx_on_t, pemoor, ==, 1,
- 1000000)) {
- printf("PCIe%d: Timeout waiting for EP link up at Gen3\n", pem);
- return;
- }
- }
- static void __cvmx_qlm_pcie_errata_cn78xx(int node, int qlm)
- {
- int pem, i, q;
- int is_8lanes;
- int is_high_lanes;
- int low_qlm, high_qlm, is_host;
- int need_ep_monitor;
- cvmx_pemx_cfg_t pem_cfg, pem3_cfg;
- cvmx_gserx_slice_cfg_t slice_cfg;
- cvmx_gserx_rx_pwr_ctrl_p1_t pwr_ctrl_p1;
- cvmx_rst_soft_prstx_t soft_prst;
- /* Only applies to CN78XX pass 1.x */
- if (!OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X))
- return;
- /* Determine the PEM for this QLM, whether we're in 8 lane mode,
- * and whether these are the top lanes of the 8
- */
- switch (qlm) {
- case 0: /* First 4 lanes of PEM0 */
- pem_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(0));
- pem = 0;
- is_8lanes = pem_cfg.cn78xx.lanes8;
- is_high_lanes = 0;
- break;
- case 1: /* Either last 4 lanes of PEM0, or PEM1 */
- pem_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(0));
- pem = (pem_cfg.cn78xx.lanes8) ? 0 : 1;
- is_8lanes = pem_cfg.cn78xx.lanes8;
- is_high_lanes = is_8lanes;
- break;
- case 2: /* First 4 lanes of PEM2 */
- pem_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(2));
- pem = 2;
- is_8lanes = pem_cfg.cn78xx.lanes8;
- is_high_lanes = 0;
- break;
- case 3: /* Either last 4 lanes of PEM2, or PEM3 */
- pem_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(2));
- pem3_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(3));
- pem = (pem_cfg.cn78xx.lanes8) ? 2 : 3;
- is_8lanes = (pem == 2) ? pem_cfg.cn78xx.lanes8 : pem3_cfg.cn78xx.lanes8;
- is_high_lanes = (pem == 2) && is_8lanes;
- break;
- case 4: /* Last 4 lanes of PEM3 */
- pem = 3;
- is_8lanes = 1;
- is_high_lanes = 1;
- break;
- default:
- return;
- }
- /* These workaround must be applied once per PEM. Since we're called per
- * QLM, wait for the 2nd half of 8 lane setups before doing the workaround
- */
- if (is_8lanes && !is_high_lanes)
- return;
- pem_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(pem));
- is_host = pem_cfg.cn78xx.hostmd;
- low_qlm = (is_8lanes) ? qlm - 1 : qlm;
- high_qlm = qlm;
- qlm = -1;
- if (!is_host) {
- /* Read the current slice config value. If its at the value we will
- * program then skip doing the workaround. We're probably doing a
- * hot reset and the workaround is already applied
- */
- slice_cfg.u64 = csr_rd_node(node, CVMX_GSERX_SLICE_CFG(low_qlm));
- if (slice_cfg.s.tx_rx_detect_lvl_enc == 7 && OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0))
- return;
- }
- if (is_host && OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0)) {
- /* (GSER-XXXX) GSER PHY needs to be reset at initialization */
- cvmx_gserx_phy_ctl_t phy_ctl;
- for (q = low_qlm; q <= high_qlm; q++) {
- phy_ctl.u64 = csr_rd_node(node, CVMX_GSERX_PHY_CTL(q));
- phy_ctl.s.phy_reset = 1;
- csr_wr_node(node, CVMX_GSERX_PHY_CTL(q), phy_ctl.u64);
- }
- udelay(5);
- for (q = low_qlm; q <= high_qlm; q++) {
- phy_ctl.u64 = csr_rd_node(node, CVMX_GSERX_PHY_CTL(q));
- phy_ctl.s.phy_reset = 0;
- csr_wr_node(node, CVMX_GSERX_PHY_CTL(q), phy_ctl.u64);
- }
- udelay(5);
- }
- if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0)) {
- /* (GSER-20936) GSER has wrong PCIe RX detect reset value */
- for (q = low_qlm; q <= high_qlm; q++) {
- slice_cfg.u64 = csr_rd_node(node, CVMX_GSERX_SLICE_CFG(q));
- slice_cfg.s.tx_rx_detect_lvl_enc = 7;
- csr_wr_node(node, CVMX_GSERX_SLICE_CFG(q), slice_cfg.u64);
- }
- /* Clear the bit in GSERX_RX_PWR_CTRL_P1[p1_rx_subblk_pd]
- * that coresponds to "Lane DLL"
- */
- for (q = low_qlm; q <= high_qlm; q++) {
- pwr_ctrl_p1.u64 = csr_rd_node(node, CVMX_GSERX_RX_PWR_CTRL_P1(q));
- pwr_ctrl_p1.s.p1_rx_subblk_pd &= ~4;
- csr_wr_node(node, CVMX_GSERX_RX_PWR_CTRL_P1(q), pwr_ctrl_p1.u64);
- }
- /* Errata (GSER-20888) GSER incorrect synchronizers hurts PCIe
- * Override TX Power State machine TX reset control signal
- */
- for (q = low_qlm; q <= high_qlm; q++) {
- for (i = 0; i < 4; i++) {
- cvmx_gserx_lanex_tx_cfg_0_t tx_cfg;
- cvmx_gserx_lanex_pwr_ctrl_t pwr_ctrl;
- tx_cfg.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_TX_CFG_0(i, q));
- tx_cfg.s.tx_resetn_ovrrd_val = 1;
- csr_wr_node(node, CVMX_GSERX_LANEX_TX_CFG_0(i, q), tx_cfg.u64);
- pwr_ctrl.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_PWR_CTRL(i, q));
- pwr_ctrl.s.tx_p2s_resetn_ovrrd_en = 1;
- csr_wr_node(node, CVMX_GSERX_LANEX_PWR_CTRL(i, q), pwr_ctrl.u64);
- }
- }
- }
- if (!is_host) {
- cvmx_pciercx_cfg089_t cfg089;
- cvmx_pciercx_cfg090_t cfg090;
- cvmx_pciercx_cfg091_t cfg091;
- cvmx_pciercx_cfg092_t cfg092;
- cvmx_pciercx_cfg548_t cfg548;
- cvmx_pciercx_cfg554_t cfg554;
- if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0)) {
- /* Errata (GSER-21178) PCIe gen3 doesn't work */
- /* The starting equalization hints are incorrect on CN78XX pass 1.x. Fix
- * them for the 8 possible lanes. It doesn't hurt to program them even
- * for lanes not in use
- */
- cfg089.u32 = cvmx_pcie_cfgx_read_node(node, pem, CVMX_PCIERCX_CFG089(pem));
- cfg089.s.l1urph = 2;
- cfg089.s.l1utp = 7;
- cfg089.s.l0urph = 2;
- cfg089.s.l0utp = 7;
- cvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG089(pem), cfg089.u32);
- cfg090.u32 = cvmx_pcie_cfgx_read_node(node, pem, CVMX_PCIERCX_CFG090(pem));
- cfg090.s.l3urph = 2;
- cfg090.s.l3utp = 7;
- cfg090.s.l2urph = 2;
- cfg090.s.l2utp = 7;
- cvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG090(pem), cfg090.u32);
- cfg091.u32 = cvmx_pcie_cfgx_read_node(node, pem, CVMX_PCIERCX_CFG091(pem));
- cfg091.s.l5urph = 2;
- cfg091.s.l5utp = 7;
- cfg091.s.l4urph = 2;
- cfg091.s.l4utp = 7;
- cvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG091(pem), cfg091.u32);
- cfg092.u32 = cvmx_pcie_cfgx_read_node(node, pem, CVMX_PCIERCX_CFG092(pem));
- cfg092.s.l7urph = 2;
- cfg092.s.l7utp = 7;
- cfg092.s.l6urph = 2;
- cfg092.s.l6utp = 7;
- cvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG092(pem), cfg092.u32);
- /* FIXME: Disable phase 2 and phase 3 equalization */
- cfg548.u32 = cvmx_pcie_cfgx_read_node(node, pem, CVMX_PCIERCX_CFG548(pem));
- cfg548.s.ep2p3d = 1;
- cvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG548(pem), cfg548.u32);
- }
- /* Errata (GSER-21331) GEN3 Equalization may fail */
- /* Disable preset #10 and disable the 2ms timeout */
- cfg554.u32 = cvmx_pcie_cfgx_read_node(node, pem, CVMX_PCIERCX_CFG554(pem));
- if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0))
- cfg554.s.p23td = 1;
- cfg554.s.prv = 0x3ff;
- cvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG554(pem), cfg554.u32);
- if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0)) {
- need_ep_monitor = (pem_cfg.s.md == 2);
- if (need_ep_monitor) {
- cvmx_pciercx_cfg031_t cfg031;
- cvmx_pciercx_cfg040_t cfg040;
- /* Force Gen1 for initial link bringup. We'll
- * fix it later
- */
- pem_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(pem));
- pem_cfg.s.md = 0;
- csr_wr_node(node, CVMX_PEMX_CFG(pem), pem_cfg.u64);
- cfg031.u32 = cvmx_pcie_cfgx_read_node(node, pem,
- CVMX_PCIERCX_CFG031(pem));
- cfg031.s.mls = 0;
- cvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG031(pem),
- cfg031.u32);
- cfg040.u32 = cvmx_pcie_cfgx_read_node(node, pem,
- CVMX_PCIERCX_CFG040(pem));
- cfg040.s.tls = 1;
- cvmx_pcie_cfgx_write_node(node, pem, CVMX_PCIERCX_CFG040(pem),
- cfg040.u32);
- __cvmx_qlm_pcie_errata_ep_cn78xx(node, pem);
- }
- return;
- }
- }
- if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_0)) {
- /* De-assert the SOFT_RST bit for this QLM (PEM), causing the PCIe
- * workarounds code above to take effect.
- */
- soft_prst.u64 = csr_rd_node(node, CVMX_RST_SOFT_PRSTX(pem));
- soft_prst.s.soft_prst = 0;
- csr_wr_node(node, CVMX_RST_SOFT_PRSTX(pem), soft_prst.u64);
- udelay(1);
- /* Assert the SOFT_RST bit for this QLM (PEM), putting the PCIe back into
- * reset state with disturbing the workarounds.
- */
- soft_prst.u64 = csr_rd_node(node, CVMX_RST_SOFT_PRSTX(pem));
- soft_prst.s.soft_prst = 1;
- csr_wr_node(node, CVMX_RST_SOFT_PRSTX(pem), soft_prst.u64);
- }
- udelay(1);
- }
- /**
- * Setup the PEM to either driver or receive reset from PRST based on RC or EP
- *
- * @param node Node to use in a Numa setup
- * @param pem Which PEM to setuo
- * @param is_endpoint
- * Non zero if PEM is a EP
- */
- static void __setup_pem_reset(int node, int pem, int is_endpoint)
- {
- cvmx_rst_ctlx_t rst_ctl;
- /* Make sure is_endpoint is either 0 or 1 */
- is_endpoint = (is_endpoint != 0);
- rst_ctl.u64 = csr_rd_node(node, CVMX_RST_CTLX(pem));
- rst_ctl.s.prst_link = 0; /* Link down causes soft reset */
- rst_ctl.s.rst_link = is_endpoint; /* EP PERST causes a soft reset */
- rst_ctl.s.rst_drv = !is_endpoint; /* Drive if RC */
- rst_ctl.s.rst_rcv = is_endpoint; /* Only read PERST in EP mode */
- rst_ctl.s.rst_chip = 0; /* PERST doesn't pull CHIP_RESET */
- csr_wr_node(node, CVMX_RST_CTLX(pem), rst_ctl.u64);
- }
- /**
- * Configure QLM speed and mode for cn78xx.
- *
- * @param node Node to configure the QLM
- * @param qlm The QLM to configure
- * @param baud_mhz The speed the QLM needs to be configured in Mhz.
- * @param mode The QLM to be configured as SGMII/XAUI/PCIe.
- * @param rc Only used for PCIe, rc = 1 for root complex mode, 0 for EP mode.
- * @param gen3 Only used for PCIe
- * gen3 = 2 GEN3 mode
- * gen3 = 1 GEN2 mode
- * gen3 = 0 GEN1 mode
- *
- * @param ref_clk_sel The reference-clock selection to use to configure QLM
- * 0 = REF_100MHZ
- * 1 = REF_125MHZ
- * 2 = REF_156MHZ
- * 3 = REF_161MHZ
- * @param ref_clk_input The reference-clock input to use to configure QLM
- *
- * Return: Return 0 on success or -1.
- */
- int octeon_configure_qlm_cn78xx(int node, int qlm, int baud_mhz, int mode, int rc, int gen3,
- int ref_clk_sel, int ref_clk_input)
- {
- cvmx_gserx_phy_ctl_t phy_ctl;
- cvmx_gserx_lane_mode_t lmode;
- cvmx_gserx_cfg_t cfg;
- cvmx_gserx_refclk_sel_t refclk_sel;
- int is_pcie = 0;
- int is_ilk = 0;
- int is_bgx = 0;
- int lane_mode = 0;
- int lmac_type = 0;
- bool alt_pll = false;
- int num_ports = 0;
- int lane_to_sds = 0;
- debug("%s(node: %d, qlm: %d, baud_mhz: %d, mode: %d, rc: %d, gen3: %d, ref_clk_sel: %d, ref_clk_input: %d\n",
- __func__, node, qlm, baud_mhz, mode, rc, gen3, ref_clk_sel, ref_clk_input);
- if (OCTEON_IS_MODEL(OCTEON_CN76XX) && qlm > 4) {
- debug("%s: qlm %d not present on CN76XX\n", __func__, qlm);
- return -1;
- }
- /* Errata PEM-31375 PEM RSL accesses to PCLK registers can timeout
- * during speed change. Change SLI_WINDOW_CTL[time] to 525us
- */
- __set_sli_window_ctl_errata_31375(node);
- cfg.u64 = csr_rd_node(node, CVMX_GSERX_CFG(qlm));
- /* If PEM is in EP, no need to do anything */
- if (cfg.s.pcie && rc == 0) {
- debug("%s: node %d, qlm %d is in PCIe endpoint mode, returning\n",
- __func__, node, qlm);
- return 0;
- }
- /* Set the reference clock to use */
- refclk_sel.u64 = 0;
- if (ref_clk_input == 0) { /* External ref clock */
- refclk_sel.s.com_clk_sel = 0;
- refclk_sel.s.use_com1 = 0;
- } else if (ref_clk_input == 1) {
- refclk_sel.s.com_clk_sel = 1;
- refclk_sel.s.use_com1 = 0;
- } else {
- refclk_sel.s.com_clk_sel = 1;
- refclk_sel.s.use_com1 = 1;
- }
- csr_wr_node(node, CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);
- /* Reset the QLM after changing the reference clock */
- phy_ctl.u64 = csr_rd_node(node, CVMX_GSERX_PHY_CTL(qlm));
- phy_ctl.s.phy_reset = 1;
- phy_ctl.s.phy_pd = 1;
- csr_wr_node(node, CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);
- udelay(1000);
- /* Always restore the reference clocks for a QLM */
- memcpy(ref_clk_cn78xx[node][qlm], def_ref_clk_cn78xx, sizeof(def_ref_clk_cn78xx));
- switch (mode) {
- case CVMX_QLM_MODE_PCIE:
- case CVMX_QLM_MODE_PCIE_1X8: {
- cvmx_pemx_cfg_t pemx_cfg;
- cvmx_pemx_on_t pemx_on;
- is_pcie = 1;
- if (ref_clk_sel == 0) {
- refclk_sel.u64 = csr_rd_node(node, CVMX_GSERX_REFCLK_SEL(qlm));
- refclk_sel.s.pcie_refclk125 = 0;
- csr_wr_node(node, CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);
- if (gen3 == 0) /* Gen1 mode */
- lane_mode = R_2_5G_REFCLK100;
- else if (gen3 == 1) /* Gen2 mode */
- lane_mode = R_5G_REFCLK100;
- else
- lane_mode = R_8G_REFCLK100;
- } else if (ref_clk_sel == 1) {
- refclk_sel.u64 = csr_rd_node(node, CVMX_GSERX_REFCLK_SEL(qlm));
- refclk_sel.s.pcie_refclk125 = 1;
- csr_wr_node(node, CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);
- if (gen3 == 0) /* Gen1 mode */
- lane_mode = R_2_5G_REFCLK125;
- else if (gen3 == 1) /* Gen2 mode */
- lane_mode = R_5G_REFCLK125;
- else
- lane_mode = R_8G_REFCLK125;
- } else {
- printf("Invalid reference clock for PCIe on QLM%d\n", qlm);
- return -1;
- }
- switch (qlm) {
- case 0: /* Either x4 or x8 based on PEM0 */
- {
- cvmx_rst_soft_prstx_t rst_prst;
- rst_prst.u64 = csr_rd_node(node, CVMX_RST_SOFT_PRSTX(0));
- rst_prst.s.soft_prst = rc;
- csr_wr_node(node, CVMX_RST_SOFT_PRSTX(0), rst_prst.u64);
- __setup_pem_reset(node, 0, !rc);
- pemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(0));
- pemx_cfg.cn78xx.lanes8 = (mode == CVMX_QLM_MODE_PCIE_1X8);
- pemx_cfg.cn78xx.hostmd = rc;
- pemx_cfg.cn78xx.md = gen3;
- csr_wr_node(node, CVMX_PEMX_CFG(0), pemx_cfg.u64);
- /* x8 mode waits for QLM1 setup before turning on the PEM */
- if (mode == CVMX_QLM_MODE_PCIE) {
- pemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(0));
- pemx_on.s.pemon = 1;
- csr_wr_node(node, CVMX_PEMX_ON(0), pemx_on.u64);
- }
- break;
- }
- case 1: /* Either PEM0 x8 or PEM1 x4 */
- {
- if (mode == CVMX_QLM_MODE_PCIE) {
- cvmx_rst_soft_prstx_t rst_prst;
- cvmx_pemx_cfg_t pemx_cfg;
- rst_prst.u64 = csr_rd_node(node, CVMX_RST_SOFT_PRSTX(1));
- rst_prst.s.soft_prst = rc;
- csr_wr_node(node, CVMX_RST_SOFT_PRSTX(1), rst_prst.u64);
- __setup_pem_reset(node, 1, !rc);
- pemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(1));
- pemx_cfg.cn78xx.lanes8 = 0;
- pemx_cfg.cn78xx.hostmd = rc;
- pemx_cfg.cn78xx.md = gen3;
- csr_wr_node(node, CVMX_PEMX_CFG(1), pemx_cfg.u64);
- pemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(1));
- pemx_on.s.pemon = 1;
- csr_wr_node(node, CVMX_PEMX_ON(1), pemx_on.u64);
- } else {
- pemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(0));
- pemx_on.s.pemon = 1;
- csr_wr_node(node, CVMX_PEMX_ON(0), pemx_on.u64);
- }
- break;
- }
- case 2: /* Either PEM2 x4 or PEM2 x8 */
- {
- cvmx_rst_soft_prstx_t rst_prst;
- rst_prst.u64 = csr_rd_node(node, CVMX_RST_SOFT_PRSTX(2));
- rst_prst.s.soft_prst = rc;
- csr_wr_node(node, CVMX_RST_SOFT_PRSTX(2), rst_prst.u64);
- __setup_pem_reset(node, 2, !rc);
- pemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(2));
- pemx_cfg.cn78xx.lanes8 = (mode == CVMX_QLM_MODE_PCIE_1X8);
- pemx_cfg.cn78xx.hostmd = rc;
- pemx_cfg.cn78xx.md = gen3;
- csr_wr_node(node, CVMX_PEMX_CFG(2), pemx_cfg.u64);
- /* x8 mode waits for QLM3 setup before turning on the PEM */
- if (mode == CVMX_QLM_MODE_PCIE) {
- pemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(2));
- pemx_on.s.pemon = 1;
- csr_wr_node(node, CVMX_PEMX_ON(2), pemx_on.u64);
- }
- break;
- }
- case 3: /* Either PEM2 x8 or PEM3 x4 */
- {
- pemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(2));
- if (pemx_cfg.cn78xx.lanes8) {
- /* Last 4 lanes of PEM2 */
- /* PEMX_CFG already setup */
- pemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(2));
- pemx_on.s.pemon = 1;
- csr_wr_node(node, CVMX_PEMX_ON(2), pemx_on.u64);
- }
- /* Check if PEM3 uses QLM3 and in x4 lane mode */
- if (mode == CVMX_QLM_MODE_PCIE) {
- cvmx_rst_soft_prstx_t rst_prst;
- rst_prst.u64 = csr_rd_node(node, CVMX_RST_SOFT_PRSTX(3));
- rst_prst.s.soft_prst = rc;
- csr_wr_node(node, CVMX_RST_SOFT_PRSTX(3), rst_prst.u64);
- __setup_pem_reset(node, 3, !rc);
- pemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(3));
- pemx_cfg.cn78xx.lanes8 = 0;
- pemx_cfg.cn78xx.hostmd = rc;
- pemx_cfg.cn78xx.md = gen3;
- csr_wr_node(node, CVMX_PEMX_CFG(3), pemx_cfg.u64);
- pemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(3));
- pemx_on.s.pemon = 1;
- csr_wr_node(node, CVMX_PEMX_ON(3), pemx_on.u64);
- }
- break;
- }
- case 4: /* Either PEM3 x4 or PEM3 x8 */
- {
- if (mode == CVMX_QLM_MODE_PCIE_1X8) {
- /* Last 4 lanes of PEM3 */
- /* PEMX_CFG already setup */
- pemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(3));
- pemx_on.s.pemon = 1;
- csr_wr_node(node, CVMX_PEMX_ON(3), pemx_on.u64);
- } else {
- /* 4 lanes of PEM3 */
- cvmx_pemx_qlm_t pemx_qlm;
- cvmx_rst_soft_prstx_t rst_prst;
- rst_prst.u64 = csr_rd_node(node, CVMX_RST_SOFT_PRSTX(3));
- rst_prst.s.soft_prst = rc;
- csr_wr_node(node, CVMX_RST_SOFT_PRSTX(3), rst_prst.u64);
- __setup_pem_reset(node, 3, !rc);
- pemx_cfg.u64 = csr_rd_node(node, CVMX_PEMX_CFG(3));
- pemx_cfg.cn78xx.lanes8 = 0;
- pemx_cfg.cn78xx.hostmd = rc;
- pemx_cfg.cn78xx.md = gen3;
- csr_wr_node(node, CVMX_PEMX_CFG(3), pemx_cfg.u64);
- /* PEM3 is on QLM4 */
- pemx_qlm.u64 = csr_rd_node(node, CVMX_PEMX_QLM(3));
- pemx_qlm.cn78xx.pem3qlm = 1;
- csr_wr_node(node, CVMX_PEMX_QLM(3), pemx_qlm.u64);
- pemx_on.u64 = csr_rd_node(node, CVMX_PEMX_ON(3));
- pemx_on.s.pemon = 1;
- csr_wr_node(node, CVMX_PEMX_ON(3), pemx_on.u64);
- }
- break;
- }
- default:
- break;
- }
- break;
- }
- case CVMX_QLM_MODE_ILK:
- is_ilk = 1;
- lane_mode = __get_lane_mode_for_speed_and_ref_clk(ref_clk_sel, baud_mhz, &alt_pll);
- if (lane_mode == -1)
- return -1;
- /* FIXME: Set lane_mode for other speeds */
- break;
- case CVMX_QLM_MODE_SGMII:
- is_bgx = 1;
- lmac_type = 0;
- lane_to_sds = 1;
- num_ports = 4;
- lane_mode = __get_lane_mode_for_speed_and_ref_clk(ref_clk_sel, baud_mhz, &alt_pll);
- debug("%s: SGMII lane mode: %d, alternate PLL: %s\n", __func__, lane_mode,
- alt_pll ? "true" : "false");
- if (lane_mode == -1)
- return -1;
- break;
- case CVMX_QLM_MODE_XAUI:
- is_bgx = 5;
- lmac_type = 1;
- lane_to_sds = 0xe4;
- num_ports = 1;
- lane_mode = __get_lane_mode_for_speed_and_ref_clk(ref_clk_sel, baud_mhz, &alt_pll);
- debug("%s: XAUI lane mode: %d\n", __func__, lane_mode);
- if (lane_mode == -1)
- return -1;
- break;
- case CVMX_QLM_MODE_RXAUI:
- is_bgx = 3;
- lmac_type = 2;
- lane_to_sds = 0;
- num_ports = 2;
- debug("%s: RXAUI lane mode: %d\n", __func__, lane_mode);
- lane_mode = __get_lane_mode_for_speed_and_ref_clk(ref_clk_sel, baud_mhz, &alt_pll);
- if (lane_mode == -1)
- return -1;
- break;
- case CVMX_QLM_MODE_XFI: /* 10GR_4X1 */
- case CVMX_QLM_MODE_10G_KR:
- is_bgx = 1;
- lmac_type = 3;
- lane_to_sds = 1;
- num_ports = 4;
- lane_mode = __get_lane_mode_for_speed_and_ref_clk(ref_clk_sel, baud_mhz, &alt_pll);
- debug("%s: XFI/10G_KR lane mode: %d\n", __func__, lane_mode);
- if (lane_mode == -1)
- return -1;
- break;
- case CVMX_QLM_MODE_XLAUI: /* 40GR4_1X4 */
- case CVMX_QLM_MODE_40G_KR4:
- is_bgx = 5;
- lmac_type = 4;
- lane_to_sds = 0xe4;
- num_ports = 1;
- lane_mode = __get_lane_mode_for_speed_and_ref_clk(ref_clk_sel, baud_mhz, &alt_pll);
- debug("%s: XLAUI/40G_KR4 lane mode: %d\n", __func__, lane_mode);
- if (lane_mode == -1)
- return -1;
- break;
- case CVMX_QLM_MODE_DISABLED:
- /* Power down the QLM */
- phy_ctl.u64 = csr_rd_node(node, CVMX_GSERX_PHY_CTL(qlm));
- phy_ctl.s.phy_pd = 1;
- phy_ctl.s.phy_reset = 1;
- csr_wr_node(node, CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);
- /* Disable all modes */
- csr_wr_node(node, CVMX_GSERX_CFG(qlm), 0);
- /* Do nothing */
- return 0;
- default:
- break;
- }
- if (alt_pll) {
- debug("%s: alternate PLL settings used for node %d, qlm %d, lane mode %d, reference clock %d\n",
- __func__, node, qlm, lane_mode, ref_clk_sel);
- if (__set_qlm_ref_clk_cn78xx(node, qlm, lane_mode, ref_clk_sel)) {
- printf("%s: Error: reference clock %d is not supported for node %d, qlm %d\n",
- __func__, ref_clk_sel, node, qlm);
- return -1;
- }
- }
- /* Power up PHY, but keep it in reset */
- phy_ctl.u64 = csr_rd_node(node, CVMX_GSERX_PHY_CTL(qlm));
- phy_ctl.s.phy_pd = 0;
- phy_ctl.s.phy_reset = 1;
- csr_wr_node(node, CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);
- /* Errata GSER-20788: GSER(0..13)_CFG[BGX_QUAD]=1 is broken. Force the
- * BGX_QUAD bit to be clear for CN78XX pass 1.x
- */
- if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X))
- is_bgx &= 3;
- /* Set GSER for the interface mode */
- cfg.u64 = csr_rd_node(node, CVMX_GSERX_CFG(qlm));
- cfg.s.ila = is_ilk;
- cfg.s.bgx = is_bgx & 1;
- cfg.s.bgx_quad = (is_bgx >> 2) & 1;
- cfg.s.bgx_dual = (is_bgx >> 1) & 1;
- cfg.s.pcie = is_pcie;
- csr_wr_node(node, CVMX_GSERX_CFG(qlm), cfg.u64);
- /* Lane mode */
- lmode.u64 = csr_rd_node(node, CVMX_GSERX_LANE_MODE(qlm));
- lmode.s.lmode = lane_mode;
- csr_wr_node(node, CVMX_GSERX_LANE_MODE(qlm), lmode.u64);
- /* BGX0-1 can connect to QLM0-1 or QLM 2-3. Program the select bit if we're
- * one of these QLMs and we're using BGX
- */
- if (qlm < 4 && is_bgx) {
- int bgx = qlm & 1;
- int use_upper = (qlm >> 1) & 1;
- cvmx_bgxx_cmr_global_config_t global_cfg;
- global_cfg.u64 = csr_rd_node(node, CVMX_BGXX_CMR_GLOBAL_CONFIG(bgx));
- global_cfg.s.pmux_sds_sel = use_upper;
- csr_wr_node(node, CVMX_BGXX_CMR_GLOBAL_CONFIG(bgx), global_cfg.u64);
- }
- /* Bring phy out of reset */
- phy_ctl.u64 = csr_rd_node(node, CVMX_GSERX_PHY_CTL(qlm));
- phy_ctl.s.phy_reset = 0;
- csr_wr_node(node, CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);
- csr_rd_node(node, CVMX_GSERX_PHY_CTL(qlm));
- /*
- * Wait 250 ns until the management interface is ready to accept
- * read/write commands.
- */
- udelay(1);
- if (is_bgx) {
- int bgx = (qlm < 2) ? qlm : qlm - 2;
- cvmx_bgxx_cmrx_config_t cmr_config;
- int index;
- for (index = 0; index < num_ports; index++) {
- cmr_config.u64 = csr_rd_node(node, CVMX_BGXX_CMRX_CONFIG(index, bgx));
- cmr_config.s.enable = 0;
- cmr_config.s.data_pkt_tx_en = 0;
- cmr_config.s.data_pkt_rx_en = 0;
- cmr_config.s.lmac_type = lmac_type;
- cmr_config.s.lane_to_sds = ((lane_to_sds == 1) ?
- index : ((lane_to_sds == 0) ?
- (index ? 0xe : 4) :
- lane_to_sds));
- csr_wr_node(node, CVMX_BGXX_CMRX_CONFIG(index, bgx), cmr_config.u64);
- }
- csr_wr_node(node, CVMX_BGXX_CMR_TX_LMACS(bgx), num_ports);
- csr_wr_node(node, CVMX_BGXX_CMR_RX_LMACS(bgx), num_ports);
- /* Enable/disable training for 10G_KR/40G_KR4/XFI/XLAUI modes */
- for (index = 0; index < num_ports; index++) {
- cvmx_bgxx_spux_br_pmd_control_t spu_pmd_control;
- spu_pmd_control.u64 =
- csr_rd_node(node, CVMX_BGXX_SPUX_BR_PMD_CONTROL(index, bgx));
- if (mode == CVMX_QLM_MODE_10G_KR || mode == CVMX_QLM_MODE_40G_KR4)
- spu_pmd_control.s.train_en = 1;
- else if (mode == CVMX_QLM_MODE_XFI || mode == CVMX_QLM_MODE_XLAUI)
- spu_pmd_control.s.train_en = 0;
- csr_wr_node(node, CVMX_BGXX_SPUX_BR_PMD_CONTROL(index, bgx),
- spu_pmd_control.u64);
- }
- }
- /* Configure the gser pll */
- if (!is_pcie)
- __qlm_setup_pll_cn78xx(node, qlm);
- /* Wait for reset to complete and the PLL to lock */
- if (CVMX_WAIT_FOR_FIELD64_NODE(node, CVMX_GSERX_PLL_STAT(qlm),
- cvmx_gserx_pll_stat_t,
- pll_lock, ==, 1, 10000)) {
- printf("%d:QLM%d: Timeout waiting for GSERX_PLL_STAT[pll_lock]\n",
- node, qlm);
- return -1;
- }
- /* Perform PCIe errata workaround */
- if (is_pcie)
- __cvmx_qlm_pcie_errata_cn78xx(node, qlm);
- else
- __qlm_init_errata_20844(node, qlm);
- /* Wait for reset to complete and the PLL to lock */
- /* PCIe mode doesn't become ready until the PEM block attempts to bring
- * the interface up. Skip this check for PCIe
- */
- if (!is_pcie && CVMX_WAIT_FOR_FIELD64_NODE(node, CVMX_GSERX_QLM_STAT(qlm),
- cvmx_gserx_qlm_stat_t, rst_rdy,
- ==, 1, 10000)) {
- printf("%d:QLM%d: Timeout waiting for GSERX_QLM_STAT[rst_rdy]\n",
- node, qlm);
- return -1;
- }
- /* Errata GSER-26150: 10G PHY PLL Temperature Failure */
- /* This workaround must be completed after the final deassertion of
- * GSERx_PHY_CTL[PHY_RESET].
- * Apply the workaround to 10.3125Gbps and 8Gbps only.
- */
- if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X) &&
- (baud_mhz == 103125 || (is_pcie && gen3 == 2)))
- __qlm_errata_gser_26150(0, qlm, is_pcie);
- /* Errata GSER-26636: 10G-KR/40G-KR - Inverted Tx Coefficient Direction
- * Change. Applied to all 10G standards (required for KR) but also
- * applied to other standards in case software training is used
- */
- if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X) && baud_mhz == 103125)
- __qlm_kr_inc_dec_gser26636(node, qlm);
- /* Errata GSER-25992: RX EQ Default Settings Update (CTLE Bias) */
- /* This workaround will only be applied to Pass 1.x */
- /* It will also only be applied if the SERDES data-rate is 10G */
- /* or if PCIe Gen3 (gen3=2 is PCIe Gen3) */
- if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X) &&
- (baud_mhz == 103125 || (is_pcie && gen3 == 2)))
- cvmx_qlm_gser_errata_25992(node, qlm);
- /* Errata GSER-27140: Updating the RX EQ settings due to temperature
- * drift sensitivities
- */
- /* This workaround will also only be applied if the SERDES data-rate is 10G */
- if (baud_mhz == 103125)
- __qlm_rx_eq_temp_gser27140(node, qlm);
- /* Reduce the voltage amplitude coming from Marvell PHY and also change
- * DFE threshold settings for RXAUI interface
- */
- if (is_bgx && mode == CVMX_QLM_MODE_RXAUI) {
- int l;
- for (l = 0; l < 4; l++) {
- cvmx_gserx_lanex_rx_cfg_4_t cfg4;
- cvmx_gserx_lanex_tx_cfg_0_t cfg0;
- /* Change the Q/QB error sampler 0 threshold from 0xD to 0xF */
- cfg4.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_RX_CFG_4(l, qlm));
- cfg4.s.cfg_rx_errdet_ctrl = 0xcf6f;
- csr_wr_node(node, CVMX_GSERX_LANEX_RX_CFG_4(l, qlm), cfg4.u64);
- /* Reduce the voltage swing to roughly 460mV */
- cfg0.u64 = csr_rd_node(node, CVMX_GSERX_LANEX_TX_CFG_0(l, qlm));
- cfg0.s.cfg_tx_swing = 0x12;
- csr_wr_node(node, CVMX_GSERX_LANEX_TX_CFG_0(l, qlm), cfg0.u64);
- }
- }
- return 0;
- }
- static int __is_qlm_valid_bgx_cn73xx(int qlm)
- {
- if (qlm == 2 || qlm == 3 || qlm == 5 || qlm == 6)
- return 0;
- return 1;
- }
- /**
- * Configure QLM/DLM speed and mode for cn73xx.
- *
- * @param qlm The QLM to configure
- * @param baud_mhz The speed the QLM needs to be configured in Mhz.
- * @param mode The QLM to be configured as SGMII/XAUI/PCIe.
- * @param rc Only used for PCIe, rc = 1 for root complex mode, 0 for EP mode.
- * @param gen3 Only used for PCIe
- * gen3 = 2 GEN3 mode
- * gen3 = 1 GEN2 mode
- * gen3 = 0 GEN1 mode
- *
- * @param ref_clk_sel The reference-clock selection to use to configure QLM
- * 0 = REF_100MHZ
- * 1 = REF_125MHZ
- * 2 = REF_156MHZ
- * 3 = REF_161MHZ
- *
- * @param ref_clk_input The reference-clock input to use to configure QLM
- * 0 = QLM/DLM reference clock input
- * 1 = common reference clock input 0
- * 2 = common reference clock input 1
- *
- * Return: Return 0 on success or -1.
- */
- static int octeon_configure_qlm_cn73xx(int qlm, int baud_mhz, int mode, int rc, int gen3,
- int ref_clk_sel, int ref_clk_input)
- {
- cvmx_gserx_phy_ctl_t phy_ctl;
- cvmx_gserx_lane_mode_t lmode;
- cvmx_gserx_cfg_t cfg;
- cvmx_gserx_refclk_sel_t refclk_sel;
- int is_pcie = 0;
- int is_bgx = 0;
- int lane_mode = 0;
- short lmac_type[4] = { 0 };
- short sds_lane[4] = { 0 };
- bool alt_pll = false;
- int enable_training = 0;
- int additional_lmacs = 0;
- debug("%s(qlm: %d, baud_mhz: %d, mode: %d, rc: %d, gen3: %d, ref_clk_sel: %d, ref_clk_input: %d\n",
- __func__, qlm, baud_mhz, mode, rc, gen3, ref_clk_sel, ref_clk_input);
- /* Don't configure QLM4 if it is not in SATA mode */
- if (qlm == 4) {
- if (mode == CVMX_QLM_MODE_SATA_2X1)
- return __setup_sata(qlm, baud_mhz, ref_clk_sel, ref_clk_input);
- printf("Invalid mode for QLM4\n");
- return 0;
- }
- cfg.u64 = csr_rd(CVMX_GSERX_CFG(qlm));
- /* Errata PEM-31375 PEM RSL accesses to PCLK registers can timeout
- * during speed change. Change SLI_WINDOW_CTL[time] to 525us
- */
- __set_sli_window_ctl_errata_31375(0);
- /* If PEM is in EP, no need to do anything */
- if (cfg.s.pcie && rc == 0 &&
- (mode == CVMX_QLM_MODE_PCIE || mode == CVMX_QLM_MODE_PCIE_1X8 ||
- mode == CVMX_QLM_MODE_PCIE_1X2)) {
- debug("%s: qlm %d is in PCIe endpoint mode, returning\n", __func__, qlm);
- return 0;
- }
- /* Set the reference clock to use */
- refclk_sel.u64 = 0;
- if (ref_clk_input == 0) { /* External ref clock */
- refclk_sel.s.com_clk_sel = 0;
- refclk_sel.s.use_com1 = 0;
- } else if (ref_clk_input == 1) {
- refclk_sel.s.com_clk_sel = 1;
- refclk_sel.s.use_com1 = 0;
- } else {
- refclk_sel.s.com_clk_sel = 1;
- refclk_sel.s.use_com1 = 1;
- }
- csr_wr(CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);
- /* Reset the QLM after changing the reference clock */
- phy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(qlm));
- phy_ctl.s.phy_reset = 1;
- phy_ctl.s.phy_pd = 1;
- csr_wr(CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);
- udelay(1000);
- /* Check if QLM is a valid BGX interface */
- if (mode != CVMX_QLM_MODE_PCIE && mode != CVMX_QLM_MODE_PCIE_1X2 &&
- mode != CVMX_QLM_MODE_PCIE_1X8) {
- if (__is_qlm_valid_bgx_cn73xx(qlm))
- return -1;
- }
- switch (mode) {
- case CVMX_QLM_MODE_PCIE:
- case CVMX_QLM_MODE_PCIE_1X2:
- case CVMX_QLM_MODE_PCIE_1X8: {
- cvmx_pemx_cfg_t pemx_cfg;
- cvmx_pemx_on_t pemx_on;
- cvmx_pemx_qlm_t pemx_qlm;
- cvmx_rst_soft_prstx_t rst_prst;
- int port = 0;
- is_pcie = 1;
- if (qlm < 5 && mode == CVMX_QLM_MODE_PCIE_1X2) {
- printf("Invalid PCIe mode(%d) for QLM%d\n", mode, qlm);
- return -1;
- }
- if (ref_clk_sel == 0) {
- refclk_sel.u64 = csr_rd(CVMX_GSERX_REFCLK_SEL(qlm));
- refclk_sel.s.pcie_refclk125 = 0;
- csr_wr(CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);
- if (gen3 == 0) /* Gen1 mode */
- lane_mode = R_2_5G_REFCLK100;
- else if (gen3 == 1) /* Gen2 mode */
- lane_mode = R_5G_REFCLK100;
- else
- lane_mode = R_8G_REFCLK100;
- } else if (ref_clk_sel == 1) {
- refclk_sel.u64 = csr_rd(CVMX_GSERX_REFCLK_SEL(qlm));
- refclk_sel.s.pcie_refclk125 = 1;
- csr_wr(CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);
- if (gen3 == 0) /* Gen1 mode */
- lane_mode = R_2_5G_REFCLK125;
- else if (gen3 == 1) /* Gen2 mode */
- lane_mode = R_5G_REFCLK125;
- else
- lane_mode = R_8G_REFCLK125;
- } else {
- printf("Invalid reference clock for PCIe on QLM%d\n", qlm);
- return -1;
- }
- switch (qlm) {
- case 0: /* Either x4 or x8 based on PEM0 */
- rst_prst.u64 = csr_rd(CVMX_RST_SOFT_PRSTX(0));
- rst_prst.s.soft_prst = rc;
- csr_wr(CVMX_RST_SOFT_PRSTX(0), rst_prst.u64);
- __setup_pem_reset(0, 0, !rc);
- pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(0));
- pemx_cfg.cn78xx.lanes8 = (mode == CVMX_QLM_MODE_PCIE_1X8);
- pemx_cfg.cn78xx.hostmd = rc;
- pemx_cfg.cn78xx.md = gen3;
- csr_wr(CVMX_PEMX_CFG(0), pemx_cfg.u64);
- /* x8 mode waits for QLM1 setup before turning on the PEM */
- if (mode == CVMX_QLM_MODE_PCIE) {
- pemx_on.u64 = csr_rd(CVMX_PEMX_ON(0));
- pemx_on.s.pemon = 1;
- csr_wr(CVMX_PEMX_ON(0), pemx_on.u64);
- }
- break;
- case 1: /* Either PEM0 x8 or PEM1 x4 */
- if (mode == CVMX_QLM_MODE_PCIE) {
- rst_prst.u64 = csr_rd(CVMX_RST_SOFT_PRSTX(1));
- rst_prst.s.soft_prst = rc;
- csr_wr(CVMX_RST_SOFT_PRSTX(1), rst_prst.u64);
- __setup_pem_reset(0, 1, !rc);
- pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(1));
- pemx_cfg.cn78xx.lanes8 = 0;
- pemx_cfg.cn78xx.hostmd = rc;
- pemx_cfg.cn78xx.md = gen3;
- csr_wr(CVMX_PEMX_CFG(1), pemx_cfg.u64);
- pemx_on.u64 = csr_rd(CVMX_PEMX_ON(1));
- pemx_on.s.pemon = 1;
- csr_wr(CVMX_PEMX_ON(1), pemx_on.u64);
- } else { /* x8 mode */
- pemx_on.u64 = csr_rd(CVMX_PEMX_ON(0));
- pemx_on.s.pemon = 1;
- csr_wr(CVMX_PEMX_ON(0), pemx_on.u64);
- }
- break;
- case 2: /* Either PEM2 x4 or PEM2 x8 or BGX0 */
- {
- pemx_qlm.u64 = csr_rd(CVMX_PEMX_QLM(2));
- pemx_qlm.cn73xx.pemdlmsel = 0;
- csr_wr(CVMX_PEMX_QLM(2), pemx_qlm.u64);
- rst_prst.u64 = csr_rd(CVMX_RST_SOFT_PRSTX(2));
- rst_prst.s.soft_prst = rc;
- csr_wr(CVMX_RST_SOFT_PRSTX(2), rst_prst.u64);
- __setup_pem_reset(0, 2, !rc);
- pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(2));
- pemx_cfg.cn78xx.lanes8 = (mode == CVMX_QLM_MODE_PCIE_1X8);
- pemx_cfg.cn78xx.hostmd = rc;
- pemx_cfg.cn78xx.md = gen3;
- csr_wr(CVMX_PEMX_CFG(2), pemx_cfg.u64);
- /* x8 mode waits for QLM3 setup before turning on the PEM */
- if (mode == CVMX_QLM_MODE_PCIE) {
- pemx_on.u64 = csr_rd(CVMX_PEMX_ON(2));
- pemx_on.s.pemon = 1;
- csr_wr(CVMX_PEMX_ON(2), pemx_on.u64);
- }
- break;
- }
- case 3: /* Either PEM2 x8 or PEM3 x4 or BGX1 */
- /* PEM2/PEM3 are configured to use QLM2/3 */
- pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(2));
- if (pemx_cfg.cn78xx.lanes8) {
- /* Last 4 lanes of PEM2 */
- /* PEMX_CFG already setup */
- pemx_on.u64 = csr_rd(CVMX_PEMX_ON(2));
- pemx_on.s.pemon = 1;
- csr_wr(CVMX_PEMX_ON(2), pemx_on.u64);
- }
- /* Check if PEM3 uses QLM3 and in x4 lane mode */
- if (mode == CVMX_QLM_MODE_PCIE) {
- pemx_qlm.u64 = csr_rd(CVMX_PEMX_QLM(3));
- pemx_qlm.cn73xx.pemdlmsel = 0;
- csr_wr(CVMX_PEMX_QLM(3), pemx_qlm.u64);
- rst_prst.u64 = csr_rd(CVMX_RST_SOFT_PRSTX(3));
- rst_prst.s.soft_prst = rc;
- csr_wr(CVMX_RST_SOFT_PRSTX(3), rst_prst.u64);
- __setup_pem_reset(0, 3, !rc);
- pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(3));
- pemx_cfg.cn78xx.lanes8 = 0;
- pemx_cfg.cn78xx.hostmd = rc;
- pemx_cfg.cn78xx.md = gen3;
- csr_wr(CVMX_PEMX_CFG(3), pemx_cfg.u64);
- pemx_on.u64 = csr_rd(CVMX_PEMX_ON(3));
- pemx_on.s.pemon = 1;
- csr_wr(CVMX_PEMX_ON(3), pemx_on.u64);
- }
- break;
- case 5: /* PEM2/PEM3 x2 or BGX2 */
- case 6:
- port = (qlm == 5) ? 2 : 3;
- if (mode == CVMX_QLM_MODE_PCIE_1X2) {
- /* PEM2/PEM3 are configured to use DLM5/6 */
- pemx_qlm.u64 = csr_rd(CVMX_PEMX_QLM(port));
- pemx_qlm.cn73xx.pemdlmsel = 1;
- csr_wr(CVMX_PEMX_QLM(port), pemx_qlm.u64);
- /* 2 lanes of PEM3 */
- rst_prst.u64 = csr_rd(CVMX_RST_SOFT_PRSTX(port));
- rst_prst.s.soft_prst = rc;
- csr_wr(CVMX_RST_SOFT_PRSTX(port), rst_prst.u64);
- __setup_pem_reset(0, port, !rc);
- pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(port));
- pemx_cfg.cn78xx.lanes8 = 0;
- pemx_cfg.cn78xx.hostmd = rc;
- pemx_cfg.cn78xx.md = gen3;
- csr_wr(CVMX_PEMX_CFG(port), pemx_cfg.u64);
- pemx_on.u64 = csr_rd(CVMX_PEMX_ON(port));
- pemx_on.s.pemon = 1;
- csr_wr(CVMX_PEMX_ON(port), pemx_on.u64);
- }
- break;
- default:
- break;
- }
- break;
- }
- case CVMX_QLM_MODE_SGMII:
- is_bgx = 1;
- lmac_type[0] = 0;
- lmac_type[1] = 0;
- lmac_type[2] = 0;
- lmac_type[3] = 0;
- sds_lane[0] = 0;
- sds_lane[1] = 1;
- sds_lane[2] = 2;
- sds_lane[3] = 3;
- break;
- case CVMX_QLM_MODE_SGMII_2X1:
- if (qlm == 5) {
- is_bgx = 1;
- lmac_type[0] = 0;
- lmac_type[1] = 0;
- lmac_type[2] = -1;
- lmac_type[3] = -1;
- sds_lane[0] = 0;
- sds_lane[1] = 1;
- } else if (qlm == 6) {
- is_bgx = 1;
- lmac_type[0] = -1;
- lmac_type[1] = -1;
- lmac_type[2] = 0;
- lmac_type[3] = 0;
- sds_lane[2] = 2;
- sds_lane[3] = 3;
- additional_lmacs = 2;
- }
- break;
- case CVMX_QLM_MODE_XAUI:
- is_bgx = 5;
- lmac_type[0] = 1;
- lmac_type[1] = -1;
- lmac_type[2] = -1;
- lmac_type[3] = -1;
- sds_lane[0] = 0xe4;
- break;
- case CVMX_QLM_MODE_RXAUI:
- is_bgx = 3;
- lmac_type[0] = 2;
- lmac_type[1] = 2;
- lmac_type[2] = -1;
- lmac_type[3] = -1;
- sds_lane[0] = 0x4;
- sds_lane[1] = 0xe;
- break;
- case CVMX_QLM_MODE_RXAUI_1X2:
- if (qlm == 5) {
- is_bgx = 3;
- lmac_type[0] = 2;
- lmac_type[1] = -1;
- lmac_type[2] = -1;
- lmac_type[3] = -1;
- sds_lane[0] = 0x4;
- }
- if (qlm == 6) {
- is_bgx = 3;
- lmac_type[0] = -1;
- lmac_type[1] = -1;
- lmac_type[2] = 2;
- lmac_type[3] = -1;
- sds_lane[2] = 0xe;
- additional_lmacs = 2;
- }
- break;
- case CVMX_QLM_MODE_10G_KR:
- enable_training = 1;
- case CVMX_QLM_MODE_XFI: /* 10GR_4X1 */
- is_bgx = 1;
- lmac_type[0] = 3;
- lmac_type[1] = 3;
- lmac_type[2] = 3;
- lmac_type[3] = 3;
- sds_lane[0] = 0;
- sds_lane[1] = 1;
- sds_lane[2] = 2;
- sds_lane[3] = 3;
- break;
- case CVMX_QLM_MODE_10G_KR_1X2:
- enable_training = 1;
- case CVMX_QLM_MODE_XFI_1X2:
- if (qlm == 5) {
- is_bgx = 1;
- lmac_type[0] = 3;
- lmac_type[1] = 3;
- lmac_type[2] = -1;
- lmac_type[3] = -1;
- sds_lane[0] = 0;
- sds_lane[1] = 1;
- } else if (qlm == 6) {
- is_bgx = 1;
- lmac_type[0] = -1;
- lmac_type[1] = -1;
- lmac_type[2] = 3;
- lmac_type[3] = 3;
- sds_lane[2] = 2;
- sds_lane[3] = 3;
- additional_lmacs = 2;
- }
- break;
- case CVMX_QLM_MODE_40G_KR4:
- enable_training = 1;
- case CVMX_QLM_MODE_XLAUI: /* 40GR4_1X4 */
- is_bgx = 5;
- lmac_type[0] = 4;
- lmac_type[1] = -1;
- lmac_type[2] = -1;
- lmac_type[3] = -1;
- sds_lane[0] = 0xe4;
- break;
- case CVMX_QLM_MODE_RGMII_SGMII:
- is_bgx = 1;
- lmac_type[0] = 5;
- lmac_type[1] = 0;
- lmac_type[2] = 0;
- lmac_type[3] = 0;
- sds_lane[0] = 0;
- sds_lane[1] = 1;
- sds_lane[2] = 2;
- sds_lane[3] = 3;
- break;
- case CVMX_QLM_MODE_RGMII_SGMII_1X1:
- if (qlm == 5) {
- is_bgx = 1;
- lmac_type[0] = 5;
- lmac_type[1] = 0;
- lmac_type[2] = -1;
- lmac_type[3] = -1;
- sds_lane[0] = 0;
- sds_lane[1] = 1;
- }
- break;
- case CVMX_QLM_MODE_RGMII_SGMII_2X1:
- if (qlm == 6) {
- is_bgx = 1;
- lmac_type[0] = 5;
- lmac_type[1] = -1;
- lmac_type[2] = 0;
- lmac_type[3] = 0;
- sds_lane[0] = 0;
- sds_lane[2] = 0;
- sds_lane[3] = 1;
- }
- break;
- case CVMX_QLM_MODE_RGMII_10G_KR:
- enable_training = 1;
- case CVMX_QLM_MODE_RGMII_XFI:
- is_bgx = 1;
- lmac_type[0] = 5;
- lmac_type[1] = 3;
- lmac_type[2] = 3;
- lmac_type[3] = 3;
- sds_lane[0] = 0;
- sds_lane[1] = 1;
- sds_lane[2] = 2;
- sds_lane[3] = 3;
- break;
- case CVMX_QLM_MODE_RGMII_10G_KR_1X1:
- enable_training = 1;
- case CVMX_QLM_MODE_RGMII_XFI_1X1:
- if (qlm == 5) {
- is_bgx = 3;
- lmac_type[0] = 5;
- lmac_type[1] = 3;
- lmac_type[2] = -1;
- lmac_type[3] = -1;
- sds_lane[0] = 0;
- sds_lane[1] = 1;
- }
- break;
- case CVMX_QLM_MODE_RGMII_40G_KR4:
- enable_training = 1;
- case CVMX_QLM_MODE_RGMII_XLAUI:
- is_bgx = 5;
- lmac_type[0] = 5;
- lmac_type[1] = 4;
- lmac_type[2] = -1;
- lmac_type[3] = -1;
- sds_lane[0] = 0x0;
- sds_lane[1] = 0xe4;
- break;
- case CVMX_QLM_MODE_RGMII_RXAUI:
- is_bgx = 3;
- lmac_type[0] = 5;
- lmac_type[1] = 2;
- lmac_type[2] = 2;
- lmac_type[3] = -1;
- sds_lane[0] = 0x0;
- sds_lane[1] = 0x4;
- sds_lane[2] = 0xe;
- break;
- case CVMX_QLM_MODE_RGMII_XAUI:
- is_bgx = 5;
- lmac_type[0] = 5;
- lmac_type[1] = 1;
- lmac_type[2] = -1;
- lmac_type[3] = -1;
- sds_lane[0] = 0;
- sds_lane[1] = 0xe4;
- break;
- default:
- break;
- }
- if (is_pcie == 0)
- lane_mode = __get_lane_mode_for_speed_and_ref_clk(ref_clk_sel, baud_mhz, &alt_pll);
- debug("%s: %d lane mode: %d, alternate PLL: %s\n", __func__, mode, lane_mode,
- alt_pll ? "true" : "false");
- if (lane_mode == -1)
- return -1;
- if (alt_pll) {
- debug("%s: alternate PLL settings used for qlm %d, lane mode %d, reference clock %d\n",
- __func__, qlm, lane_mode, ref_clk_sel);
- if (__set_qlm_ref_clk_cn78xx(0, qlm, lane_mode, ref_clk_sel)) {
- printf("%s: Error: reference clock %d is not supported for qlm %d, lane mode: 0x%x\n",
- __func__, ref_clk_sel, qlm, lane_mode);
- return -1;
- }
- }
- /* Power up PHY, but keep it in reset */
- phy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(qlm));
- phy_ctl.s.phy_pd = 0;
- phy_ctl.s.phy_reset = 1;
- csr_wr(CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);
- /* Set GSER for the interface mode */
- cfg.u64 = csr_rd(CVMX_GSERX_CFG(qlm));
- cfg.s.bgx = is_bgx & 1;
- cfg.s.bgx_quad = (is_bgx >> 2) & 1;
- cfg.s.bgx_dual = (is_bgx >> 1) & 1;
- cfg.s.pcie = is_pcie;
- csr_wr(CVMX_GSERX_CFG(qlm), cfg.u64);
- /* Lane mode */
- lmode.u64 = csr_rd(CVMX_GSERX_LANE_MODE(qlm));
- lmode.s.lmode = lane_mode;
- csr_wr(CVMX_GSERX_LANE_MODE(qlm), lmode.u64);
- /* Program lmac_type to figure out the type of BGX interface configured */
- if (is_bgx) {
- int bgx = (qlm < 4) ? qlm - 2 : 2;
- cvmx_bgxx_cmrx_config_t cmr_config;
- cvmx_bgxx_cmr_rx_lmacs_t rx_lmacs;
- cvmx_bgxx_spux_br_pmd_control_t spu_pmd_control;
- int index, total_lmacs = 0;
- for (index = 0; index < 4; index++) {
- cmr_config.u64 = csr_rd(CVMX_BGXX_CMRX_CONFIG(index, bgx));
- cmr_config.s.enable = 0;
- cmr_config.s.data_pkt_rx_en = 0;
- cmr_config.s.data_pkt_tx_en = 0;
- if (lmac_type[index] != -1) {
- cmr_config.s.lmac_type = lmac_type[index];
- cmr_config.s.lane_to_sds = sds_lane[index];
- total_lmacs++;
- /* RXAUI takes up 2 lmacs */
- if (lmac_type[index] == 2)
- total_lmacs += 1;
- }
- csr_wr(CVMX_BGXX_CMRX_CONFIG(index, bgx), cmr_config.u64);
- /* Errata (TBD) RGMII doesn't turn on clock if its by
- * itself. Force them on
- */
- if (lmac_type[index] == 5) {
- cvmx_bgxx_cmr_global_config_t global_config;
- global_config.u64 = csr_rd(CVMX_BGXX_CMR_GLOBAL_CONFIG(bgx));
- global_config.s.bgx_clk_enable = 1;
- csr_wr(CVMX_BGXX_CMR_GLOBAL_CONFIG(bgx), global_config.u64);
- }
- /* Enable training for 10G_KR/40G_KR4 modes */
- if (enable_training == 1 &&
- (lmac_type[index] == 3 || lmac_type[index] == 4)) {
- spu_pmd_control.u64 =
- csr_rd(CVMX_BGXX_SPUX_BR_PMD_CONTROL(index, bgx));
- spu_pmd_control.s.train_en = 1;
- csr_wr(CVMX_BGXX_SPUX_BR_PMD_CONTROL(index, bgx),
- spu_pmd_control.u64);
- }
- }
- /* Update the total number of lmacs */
- rx_lmacs.u64 = csr_rd(CVMX_BGXX_CMR_RX_LMACS(bgx));
- rx_lmacs.s.lmacs = total_lmacs + additional_lmacs;
- csr_wr(CVMX_BGXX_CMR_RX_LMACS(bgx), rx_lmacs.u64);
- csr_wr(CVMX_BGXX_CMR_TX_LMACS(bgx), rx_lmacs.u64);
- }
- /* Bring phy out of reset */
- phy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(qlm));
- phy_ctl.s.phy_reset = 0;
- csr_wr(CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);
- /*
- * Wait 1us until the management interface is ready to accept
- * read/write commands.
- */
- udelay(1);
- /* Wait for reset to complete and the PLL to lock */
- /* PCIe mode doesn't become ready until the PEM block attempts to bring
- * the interface up. Skip this check for PCIe
- */
- if (!is_pcie && CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_QLM_STAT(qlm),
- cvmx_gserx_qlm_stat_t,
- rst_rdy, ==, 1, 10000)) {
- printf("QLM%d: Timeout waiting for GSERX_QLM_STAT[rst_rdy]\n", qlm);
- return -1;
- }
- /* Configure the gser pll */
- if (!is_pcie)
- __qlm_setup_pll_cn78xx(0, qlm);
- /* Wait for reset to complete and the PLL to lock */
- if (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_PLL_STAT(qlm), cvmx_gserx_pll_stat_t,
- pll_lock, ==, 1, 10000)) {
- printf("QLM%d: Timeout waiting for GSERX_PLL_STAT[pll_lock]\n", qlm);
- return -1;
- }
- /* Errata GSER-26150: 10G PHY PLL Temperature Failure */
- /* This workaround must be completed after the final deassertion of
- * GSERx_PHY_CTL[PHY_RESET].
- * Apply the workaround to 10.3125Gbps and 8Gbps only.
- */
- if (OCTEON_IS_MODEL(OCTEON_CN73XX_PASS1_0) &&
- (baud_mhz == 103125 || (is_pcie && gen3 == 2)))
- __qlm_errata_gser_26150(0, qlm, is_pcie);
- /* Errata GSER-26636: 10G-KR/40G-KR - Inverted Tx Coefficient Direction
- * Change. Applied to all 10G standards (required for KR) but also
- * applied to other standards in case software training is used
- */
- if (baud_mhz == 103125)
- __qlm_kr_inc_dec_gser26636(0, qlm);
- /* Errata GSER-25992: RX EQ Default Settings Update (CTLE Bias) */
- /* This workaround will only be applied to Pass 1.x */
- /* It will also only be applied if the SERDES data-rate is 10G */
- /* or if PCIe Gen3 (gen3=2 is PCIe Gen3) */
- if (baud_mhz == 103125 || (is_pcie && gen3 == 2))
- cvmx_qlm_gser_errata_25992(0, qlm);
- /* Errata GSER-27140: Updating the RX EQ settings due to temperature
- * drift sensitivities
- */
- /* This workaround will also only be applied if the SERDES data-rate is 10G */
- if (baud_mhz == 103125)
- __qlm_rx_eq_temp_gser27140(0, qlm);
- /* Reduce the voltage amplitude coming from Marvell PHY and also change
- * DFE threshold settings for RXAUI interface
- */
- if (is_bgx) {
- int l;
- for (l = 0; l < 4; l++) {
- cvmx_gserx_lanex_rx_cfg_4_t cfg4;
- cvmx_gserx_lanex_tx_cfg_0_t cfg0;
- if (lmac_type[l] == 2) {
- /* Change the Q/QB error sampler 0 threshold from 0xD to 0xF */
- cfg4.u64 = csr_rd(CVMX_GSERX_LANEX_RX_CFG_4(l, qlm));
- cfg4.s.cfg_rx_errdet_ctrl = 0xcf6f;
- csr_wr(CVMX_GSERX_LANEX_RX_CFG_4(l, qlm), cfg4.u64);
- /* Reduce the voltage swing to roughly 460mV */
- cfg0.u64 = csr_rd(CVMX_GSERX_LANEX_TX_CFG_0(l, qlm));
- cfg0.s.cfg_tx_swing = 0x12;
- csr_wr(CVMX_GSERX_LANEX_TX_CFG_0(l, qlm), cfg0.u64);
- }
- }
- }
- return 0;
- }
- static int __rmac_pll_config(int baud_mhz, int qlm, int mode)
- {
- cvmx_gserx_pll_px_mode_0_t pmode0;
- cvmx_gserx_pll_px_mode_1_t pmode1;
- cvmx_gserx_lane_px_mode_0_t lmode0;
- cvmx_gserx_lane_px_mode_1_t lmode1;
- cvmx_gserx_lane_mode_t lmode;
- switch (baud_mhz) {
- case 98304:
- pmode0.u64 = 0x1a0a;
- pmode1.u64 = 0x3228;
- lmode0.u64 = 0x600f;
- lmode1.u64 = 0xa80f;
- break;
- case 49152:
- if (mode == CVMX_QLM_MODE_SDL) {
- pmode0.u64 = 0x3605;
- pmode1.u64 = 0x0814;
- lmode0.u64 = 0x000f;
- lmode1.u64 = 0x6814;
- } else {
- pmode0.u64 = 0x1a0a;
- pmode1.u64 = 0x3228;
- lmode0.u64 = 0x650f;
- lmode1.u64 = 0xe80f;
- }
- break;
- case 24576:
- pmode0.u64 = 0x1a0a;
- pmode1.u64 = 0x3228;
- lmode0.u64 = 0x6a0f;
- lmode1.u64 = 0xe80f;
- break;
- case 12288:
- pmode0.u64 = 0x1a0a;
- pmode1.u64 = 0x3228;
- lmode0.u64 = 0x6f0f;
- lmode1.u64 = 0xe80f;
- break;
- case 6144:
- pmode0.u64 = 0x160a;
- pmode1.u64 = 0x1019;
- lmode0.u64 = 0x000f;
- lmode1.u64 = 0x2814;
- break;
- case 3072:
- pmode0.u64 = 0x160a;
- pmode1.u64 = 0x1019;
- lmode0.u64 = 0x050f;
- lmode1.u64 = 0x6814;
- break;
- default:
- printf("Invalid speed for CPRI/SDL configuration\n");
- return -1;
- }
- lmode.u64 = csr_rd(CVMX_GSERX_LANE_MODE(qlm));
- csr_wr(CVMX_GSERX_PLL_PX_MODE_0(lmode.s.lmode, qlm), pmode0.u64);
- csr_wr(CVMX_GSERX_PLL_PX_MODE_1(lmode.s.lmode, qlm), pmode1.u64);
- csr_wr(CVMX_GSERX_LANE_PX_MODE_0(lmode.s.lmode, qlm), lmode0.u64);
- csr_wr(CVMX_GSERX_LANE_PX_MODE_1(lmode.s.lmode, qlm), lmode1.u64);
- return 0;
- }
- /**
- * Configure QLM/DLM speed and mode for cnf75xx.
- *
- * @param qlm The QLM to configure
- * @param baud_mhz The speed the QLM needs to be configured in Mhz.
- * @param mode The QLM to be configured as SGMII/XAUI/PCIe.
- * @param rc Only used for PCIe, rc = 1 for root complex mode, 0 for EP mode.
- * @param gen3 Only used for PCIe
- * gen3 = 2 GEN3 mode
- * gen3 = 1 GEN2 mode
- * gen3 = 0 GEN1 mode
- *
- * @param ref_clk_sel The reference-clock selection to use to configure QLM
- * 0 = REF_100MHZ
- * 1 = REF_125MHZ
- * 2 = REF_156MHZ
- * 3 = REF_122MHZ
- * @param ref_clk_input The reference-clock input to use to configure QLM
- *
- * Return: Return 0 on success or -1.
- */
- static int octeon_configure_qlm_cnf75xx(int qlm, int baud_mhz, int mode, int rc, int gen3,
- int ref_clk_sel, int ref_clk_input)
- {
- cvmx_gserx_phy_ctl_t phy_ctl;
- cvmx_gserx_lane_mode_t lmode;
- cvmx_gserx_cfg_t cfg;
- cvmx_gserx_refclk_sel_t refclk_sel;
- int is_pcie = 0;
- int is_bgx = 0;
- int is_srio = 0;
- int is_rmac = 0;
- int is_rmac_pipe = 0;
- int lane_mode = 0;
- short lmac_type[4] = { 0 };
- short sds_lane[4] = { 0 };
- bool alt_pll = false;
- int enable_training = 0;
- int additional_lmacs = 0;
- int port = (qlm == 3) ? 1 : 0;
- cvmx_sriox_status_reg_t status_reg;
- debug("%s(qlm: %d, baud_mhz: %d, mode: %d, rc: %d, gen3: %d, ref_clk_sel: %d, ref_clk_input: %d\n",
- __func__, qlm, baud_mhz, mode, rc, gen3, ref_clk_sel, ref_clk_input);
- if (qlm > 8) {
- printf("Invalid qlm%d passed\n", qlm);
- return -1;
- }
- /* Errata PEM-31375 PEM RSL accesses to PCLK registers can timeout
- * during speed change. Change SLI_WINDOW_CTL[time] to 525us
- */
- __set_sli_window_ctl_errata_31375(0);
- cfg.u64 = csr_rd(CVMX_GSERX_CFG(qlm));
- /* If PEM is in EP, no need to do anything */
- if (cfg.s.pcie && rc == 0) {
- debug("%s: qlm %d is in PCIe endpoint mode, returning\n", __func__, qlm);
- return 0;
- }
- if (cfg.s.srio && rc == 0) {
- debug("%s: qlm %d is in SRIO endpoint mode, returning\n", __func__, qlm);
- return 0;
- }
- /* Set the reference clock to use */
- refclk_sel.u64 = 0;
- if (ref_clk_input == 0) { /* External ref clock */
- refclk_sel.s.com_clk_sel = 0;
- refclk_sel.s.use_com1 = 0;
- } else if (ref_clk_input == 1) {
- refclk_sel.s.com_clk_sel = 1;
- refclk_sel.s.use_com1 = 0;
- } else {
- refclk_sel.s.com_clk_sel = 1;
- refclk_sel.s.use_com1 = 1;
- }
- csr_wr(CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);
- /* Reset the QLM after changing the reference clock */
- phy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(qlm));
- phy_ctl.s.phy_reset = 1;
- phy_ctl.s.phy_pd = 1;
- csr_wr(CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);
- udelay(1000);
- switch (mode) {
- case CVMX_QLM_MODE_PCIE:
- case CVMX_QLM_MODE_PCIE_1X2:
- case CVMX_QLM_MODE_PCIE_2X1: {
- cvmx_pemx_cfg_t pemx_cfg;
- cvmx_pemx_on_t pemx_on;
- cvmx_rst_soft_prstx_t rst_prst;
- is_pcie = 1;
- if (qlm > 1) {
- printf("Invalid PCIe mode for QLM%d\n", qlm);
- return -1;
- }
- if (ref_clk_sel == 0) {
- refclk_sel.u64 = csr_rd(CVMX_GSERX_REFCLK_SEL(qlm));
- refclk_sel.s.pcie_refclk125 = 0;
- csr_wr(CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);
- if (gen3 == 0) /* Gen1 mode */
- lane_mode = R_2_5G_REFCLK100;
- else if (gen3 == 1) /* Gen2 mode */
- lane_mode = R_5G_REFCLK100;
- else
- lane_mode = R_8G_REFCLK100;
- } else if (ref_clk_sel == 1) {
- refclk_sel.u64 = csr_rd(CVMX_GSERX_REFCLK_SEL(qlm));
- refclk_sel.s.pcie_refclk125 = 1;
- csr_wr(CVMX_GSERX_REFCLK_SEL(qlm), refclk_sel.u64);
- if (gen3 == 0) /* Gen1 mode */
- lane_mode = R_2_5G_REFCLK125;
- else if (gen3 == 1) /* Gen2 mode */
- lane_mode = R_5G_REFCLK125;
- else
- lane_mode = R_8G_REFCLK125;
- } else {
- printf("Invalid reference clock for PCIe on QLM%d\n", qlm);
- return -1;
- }
- switch (qlm) {
- case 0: /* Either x4 or x2 based on PEM0 */
- rst_prst.u64 = csr_rd(CVMX_RST_SOFT_PRSTX(0));
- rst_prst.s.soft_prst = rc;
- csr_wr(CVMX_RST_SOFT_PRSTX(0), rst_prst.u64);
- __setup_pem_reset(0, 0, !rc);
- pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(0));
- pemx_cfg.cnf75xx.hostmd = rc;
- pemx_cfg.cnf75xx.lanes8 = (mode == CVMX_QLM_MODE_PCIE);
- pemx_cfg.cnf75xx.md = gen3;
- csr_wr(CVMX_PEMX_CFG(0), pemx_cfg.u64);
- /* x4 mode waits for QLM1 setup before turning on the PEM */
- if (mode == CVMX_QLM_MODE_PCIE_1X2 || mode == CVMX_QLM_MODE_PCIE_2X1) {
- pemx_on.u64 = csr_rd(CVMX_PEMX_ON(0));
- pemx_on.s.pemon = 1;
- csr_wr(CVMX_PEMX_ON(0), pemx_on.u64);
- }
- break;
- case 1: /* Either PEM0 x4 or PEM1 x2 */
- if (mode == CVMX_QLM_MODE_PCIE_1X2 || mode == CVMX_QLM_MODE_PCIE_2X1) {
- rst_prst.u64 = csr_rd(CVMX_RST_SOFT_PRSTX(1));
- rst_prst.s.soft_prst = rc;
- csr_wr(CVMX_RST_SOFT_PRSTX(1), rst_prst.u64);
- __setup_pem_reset(0, 1, !rc);
- pemx_cfg.u64 = csr_rd(CVMX_PEMX_CFG(1));
- pemx_cfg.cnf75xx.hostmd = rc;
- pemx_cfg.cnf75xx.md = gen3;
- csr_wr(CVMX_PEMX_CFG(1), pemx_cfg.u64);
- pemx_on.u64 = csr_rd(CVMX_PEMX_ON(1));
- pemx_on.s.pemon = 1;
- csr_wr(CVMX_PEMX_ON(1), pemx_on.u64);
- } else {
- pemx_on.u64 = csr_rd(CVMX_PEMX_ON(0));
- pemx_on.s.pemon = 1;
- csr_wr(CVMX_PEMX_ON(0), pemx_on.u64);
- }
- break;
- default:
- break;
- }
- break;
- }
- case CVMX_QLM_MODE_SRIO_1X4:
- case CVMX_QLM_MODE_SRIO_2X2:
- case CVMX_QLM_MODE_SRIO_4X1: {
- int spd = 0xf;
- if (cvmx_fuse_read(1601)) {
- debug("SRIO is not supported on cnf73xx model\n");
- return -1;
- }
- switch (baud_mhz) {
- case 1250:
- switch (ref_clk_sel) {
- case 0: /* 100 MHz ref clock */
- spd = 0x3;
- break;
- case 1: /* 125 MHz ref clock */
- spd = 0xa;
- break;
- case 2: /* 156.25 MHz ref clock */
- spd = 0x4;
- break;
- default:
- spd = 0xf; /* Disabled */
- break;
- }
- break;
- case 2500:
- switch (ref_clk_sel) {
- case 0: /* 100 MHz ref clock */
- spd = 0x2;
- break;
- case 1: /* 125 MHz ref clock */
- spd = 0x9;
- break;
- case 2: /* 156.25 MHz ref clock */
- spd = 0x7;
- break;
- default:
- spd = 0xf; /* Disabled */
- break;
- }
- break;
- case 3125:
- switch (ref_clk_sel) {
- case 1: /* 125 MHz ref clock */
- spd = 0x8;
- break;
- case 2: /* 156.25 MHz ref clock */
- spd = 0xe;
- break;
- default:
- spd = 0xf; /* Disabled */
- break;
- }
- break;
- case 5000:
- switch (ref_clk_sel) {
- case 0: /* 100 MHz ref clock */
- spd = 0x0;
- break;
- case 1: /* 125 MHz ref clock */
- spd = 0x6;
- break;
- case 2: /* 156.25 MHz ref clock */
- spd = 0xb;
- break;
- default:
- spd = 0xf; /* Disabled */
- break;
- }
- break;
- default:
- spd = 0xf;
- break;
- }
- if (spd == 0xf) {
- printf("ERROR: Invalid SRIO speed (%d) configured for QLM%d\n", baud_mhz,
- qlm);
- return -1;
- }
- status_reg.u64 = csr_rd(CVMX_SRIOX_STATUS_REG(port));
- status_reg.s.spd = spd;
- csr_wr(CVMX_SRIOX_STATUS_REG(port), status_reg.u64);
- is_srio = 1;
- break;
- }
- case CVMX_QLM_MODE_SGMII_2X1:
- if (qlm == 4) {
- is_bgx = 1;
- lmac_type[0] = 0;
- lmac_type[1] = 0;
- lmac_type[2] = -1;
- lmac_type[3] = -1;
- sds_lane[0] = 0;
- sds_lane[1] = 1;
- } else if (qlm == 5) {
- is_bgx = 1;
- lmac_type[0] = -1;
- lmac_type[1] = -1;
- lmac_type[2] = 0;
- lmac_type[3] = 0;
- sds_lane[2] = 2;
- sds_lane[3] = 3;
- additional_lmacs = 2;
- }
- break;
- case CVMX_QLM_MODE_10G_KR_1X2:
- enable_training = 1;
- case CVMX_QLM_MODE_XFI_1X2:
- if (qlm == 5) {
- is_bgx = 1;
- lmac_type[0] = -1;
- lmac_type[1] = -1;
- lmac_type[2] = 3;
- lmac_type[3] = 3;
- sds_lane[2] = 2;
- sds_lane[3] = 3;
- additional_lmacs = 2;
- }
- break;
- case CVMX_QLM_MODE_CPRI: /* CPRI / JESD204B */
- is_rmac = 1;
- break;
- case CVMX_QLM_MODE_SDL: /* Serdes Lite (SDL) */
- is_rmac = 1;
- is_rmac_pipe = 1;
- lane_mode = 1;
- break;
- default:
- break;
- }
- if (is_rmac_pipe == 0 && is_pcie == 0) {
- lane_mode = __get_lane_mode_for_speed_and_ref_clk(ref_clk_sel, baud_mhz,
- &alt_pll);
- }
- debug("%s: %d lane mode: %d, alternate PLL: %s\n", __func__, mode, lane_mode,
- alt_pll ? "true" : "false");
- if (lane_mode == -1)
- return -1;
- if (alt_pll) {
- debug("%s: alternate PLL settings used for qlm %d, lane mode %d, reference clock %d\n",
- __func__, qlm, lane_mode, ref_clk_sel);
- if (__set_qlm_ref_clk_cn78xx(0, qlm, lane_mode, ref_clk_sel)) {
- printf("%s: Error: reference clock %d is not supported for qlm %d\n",
- __func__, ref_clk_sel, qlm);
- return -1;
- }
- }
- /* Power up PHY, but keep it in reset */
- phy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(qlm));
- phy_ctl.s.phy_pd = 0;
- phy_ctl.s.phy_reset = 1;
- csr_wr(CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);
- /* Set GSER for the interface mode */
- cfg.u64 = csr_rd(CVMX_GSERX_CFG(qlm));
- cfg.s.bgx = is_bgx & 1;
- cfg.s.bgx_quad = (is_bgx >> 2) & 1;
- cfg.s.bgx_dual = (is_bgx >> 1) & 1;
- cfg.s.pcie = is_pcie;
- cfg.s.srio = is_srio;
- cfg.s.rmac = is_rmac;
- cfg.s.rmac_pipe = is_rmac_pipe;
- csr_wr(CVMX_GSERX_CFG(qlm), cfg.u64);
- /* Lane mode */
- lmode.u64 = csr_rd(CVMX_GSERX_LANE_MODE(qlm));
- lmode.s.lmode = lane_mode;
- csr_wr(CVMX_GSERX_LANE_MODE(qlm), lmode.u64);
- /* Because of the Errata where quad mode does not work, program
- * lmac_type to figure out the type of BGX interface configured
- */
- if (is_bgx) {
- int bgx = 0;
- cvmx_bgxx_cmrx_config_t cmr_config;
- cvmx_bgxx_cmr_rx_lmacs_t rx_lmacs;
- cvmx_bgxx_spux_br_pmd_control_t spu_pmd_control;
- int index, total_lmacs = 0;
- for (index = 0; index < 4; index++) {
- cmr_config.u64 = csr_rd(CVMX_BGXX_CMRX_CONFIG(index, bgx));
- cmr_config.s.enable = 0;
- cmr_config.s.data_pkt_rx_en = 0;
- cmr_config.s.data_pkt_tx_en = 0;
- if (lmac_type[index] != -1) {
- cmr_config.s.lmac_type = lmac_type[index];
- cmr_config.s.lane_to_sds = sds_lane[index];
- total_lmacs++;
- }
- csr_wr(CVMX_BGXX_CMRX_CONFIG(index, bgx), cmr_config.u64);
- /* Enable training for 10G_KR/40G_KR4 modes */
- if (enable_training == 1 &&
- (lmac_type[index] == 3 || lmac_type[index] == 4)) {
- spu_pmd_control.u64 =
- csr_rd(CVMX_BGXX_SPUX_BR_PMD_CONTROL(index, bgx));
- spu_pmd_control.s.train_en = 1;
- csr_wr(CVMX_BGXX_SPUX_BR_PMD_CONTROL(index, bgx),
- spu_pmd_control.u64);
- }
- }
- /* Update the total number of lmacs */
- rx_lmacs.u64 = csr_rd(CVMX_BGXX_CMR_RX_LMACS(bgx));
- rx_lmacs.s.lmacs = total_lmacs + additional_lmacs;
- csr_wr(CVMX_BGXX_CMR_RX_LMACS(bgx), rx_lmacs.u64);
- csr_wr(CVMX_BGXX_CMR_TX_LMACS(bgx), rx_lmacs.u64);
- }
- /* Bring phy out of reset */
- phy_ctl.u64 = csr_rd(CVMX_GSERX_PHY_CTL(qlm));
- phy_ctl.s.phy_reset = 0;
- csr_wr(CVMX_GSERX_PHY_CTL(qlm), phy_ctl.u64);
- /*
- * Wait 1us until the management interface is ready to accept
- * read/write commands.
- */
- udelay(1);
- if (is_srio) {
- status_reg.u64 = csr_rd(CVMX_SRIOX_STATUS_REG(port));
- status_reg.s.srio = 1;
- csr_wr(CVMX_SRIOX_STATUS_REG(port), status_reg.u64);
- return 0;
- }
- /* Wait for reset to complete and the PLL to lock */
- /* PCIe mode doesn't become ready until the PEM block attempts to bring
- * the interface up. Skip this check for PCIe
- */
- if (!is_pcie && CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_QLM_STAT(qlm), cvmx_gserx_qlm_stat_t,
- rst_rdy, ==, 1, 10000)) {
- printf("QLM%d: Timeout waiting for GSERX_QLM_STAT[rst_rdy]\n", qlm);
- return -1;
- }
- /* Configure the gser pll */
- if (is_rmac)
- __rmac_pll_config(baud_mhz, qlm, mode);
- else if (!(is_pcie || is_srio))
- __qlm_setup_pll_cn78xx(0, qlm);
- /* Wait for reset to complete and the PLL to lock */
- if (CVMX_WAIT_FOR_FIELD64(CVMX_GSERX_PLL_STAT(qlm), cvmx_gserx_pll_stat_t,
- pll_lock, ==, 1, 10000)) {
- printf("QLM%d: Timeout waiting for GSERX_PLL_STAT[pll_lock]\n", qlm);
- return -1;
- }
- /* Errata GSER-27140: Updating the RX EQ settings due to temperature
- * drift sensitivities
- */
- /* This workaround will also only be applied if the SERDES data-rate is 10G */
- if (baud_mhz == 103125)
- __qlm_rx_eq_temp_gser27140(0, qlm);
- return 0;
- }
- /**
- * Configure qlm/dlm speed and mode.
- * @param qlm The QLM or DLM to configure
- * @param speed The speed the QLM needs to be configured in Mhz.
- * @param mode The QLM to be configured as SGMII/XAUI/PCIe.
- * @param rc Only used for PCIe, rc = 1 for root complex mode, 0 for EP
- * mode.
- * @param pcie_mode Only used when qlm/dlm are in pcie mode.
- * @param ref_clk_sel Reference clock to use for 70XX where:
- * 0: 100MHz
- * 1: 125MHz
- * 2: 156.25MHz
- * 3: 122MHz (Used by RMAC)
- * @param ref_clk_input This selects which reference clock input to use. For
- * cn70xx:
- * 0: DLMC_REF_CLK0
- * 1: DLMC_REF_CLK1
- * 2: DLM0_REF_CLK
- * cn61xx: (not used)
- * cn78xx/cn76xx/cn73xx:
- * 0: Internal clock (QLM[0-7]_REF_CLK)
- * 1: QLMC_REF_CLK0
- * 2: QLMC_REF_CLK1
- *
- * Return: Return 0 on success or -1.
- */
- int octeon_configure_qlm(int qlm, int speed, int mode, int rc, int pcie_mode, int ref_clk_sel,
- int ref_clk_input)
- {
- int node = 0; // ToDo: corrently only node 0 is supported
- debug("%s(%d, %d, %d, %d, %d, %d, %d)\n", __func__, qlm, speed, mode, rc, pcie_mode,
- ref_clk_sel, ref_clk_input);
- if (OCTEON_IS_MODEL(OCTEON_CN61XX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
- return octeon_configure_qlm_cn61xx(qlm, speed, mode, rc, pcie_mode);
- else if (OCTEON_IS_MODEL(OCTEON_CN70XX))
- return octeon_configure_qlm_cn70xx(qlm, speed, mode, rc, pcie_mode, ref_clk_sel,
- ref_clk_input);
- else if (OCTEON_IS_MODEL(OCTEON_CN78XX))
- return octeon_configure_qlm_cn78xx(node, qlm, speed, mode, rc, pcie_mode,
- ref_clk_sel, ref_clk_input);
- else if (OCTEON_IS_MODEL(OCTEON_CN73XX))
- return octeon_configure_qlm_cn73xx(qlm, speed, mode, rc, pcie_mode, ref_clk_sel,
- ref_clk_input);
- else if (OCTEON_IS_MODEL(OCTEON_CNF75XX))
- return octeon_configure_qlm_cnf75xx(qlm, speed, mode, rc, pcie_mode, ref_clk_sel,
- ref_clk_input);
- else
- return -1;
- }
- void octeon_init_qlm(int node)
- {
- int qlm;
- cvmx_gserx_phy_ctl_t phy_ctl;
- cvmx_gserx_cfg_t cfg;
- int baud_mhz;
- int pem;
- if (!OCTEON_IS_MODEL(OCTEON_CN78XX))
- return;
- for (qlm = 0; qlm < 8; qlm++) {
- phy_ctl.u64 = csr_rd_node(node, CVMX_GSERX_PHY_CTL(qlm));
- if (phy_ctl.s.phy_reset == 0) {
- cfg.u64 = csr_rd_node(node, CVMX_GSERX_CFG(qlm));
- if (cfg.s.pcie)
- __cvmx_qlm_pcie_errata_cn78xx(node, qlm);
- else
- __qlm_init_errata_20844(node, qlm);
- baud_mhz = cvmx_qlm_get_gbaud_mhz_node(node, qlm);
- if (baud_mhz == 6250 || baud_mhz == 6316)
- octeon_qlm_tune_v3(node, qlm, baud_mhz, 0xa, 0xa0, -1, -1);
- else if (baud_mhz == 103125)
- octeon_qlm_tune_v3(node, qlm, baud_mhz, 0xd, 0xd0, -1, -1);
- }
- }
- /* Setup how each PEM drives the PERST lines */
- for (pem = 0; pem < 4; pem++) {
- cvmx_rst_ctlx_t rst_ctl;
- rst_ctl.u64 = csr_rd_node(node, CVMX_RST_CTLX(pem));
- __setup_pem_reset(node, pem, !rst_ctl.s.host_mode);
- }
- }
|