0901-regulator-add-Qualcomm-CPR-regulators.patch 368 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144
  1. From c9df32c057e43e38c8113199e64f7a64f8d341df Mon Sep 17 00:00:00 2001
  2. From: Robert Marko <[email protected]>
  3. Date: Mon, 11 Apr 2022 14:35:36 +0200
  4. Subject: [PATCH] regulator: add Qualcomm CPR regulators
  5. Allow building Qualcomm CPR regulators.
  6. Signed-off-by: Robert Marko <[email protected]>
  7. ---
  8. drivers/regulator/Kconfig | 33 +
  9. drivers/regulator/Makefile | 3 +
  10. drivers/regulator/cpr3-npu-regulator.c | 695 +++
  11. drivers/regulator/cpr3-regulator.c | 5111 +++++++++++++++++++++++
  12. drivers/regulator/cpr3-regulator.h | 1211 ++++++
  13. drivers/regulator/cpr3-util.c | 2750 ++++++++++++
  14. drivers/regulator/cpr4-apss-regulator.c | 1819 ++++++++
  15. include/soc/qcom/socinfo.h | 463 ++
  16. 8 files changed, 12085 insertions(+)
  17. create mode 100644 drivers/regulator/cpr3-npu-regulator.c
  18. create mode 100644 drivers/regulator/cpr3-regulator.c
  19. create mode 100644 drivers/regulator/cpr3-regulator.h
  20. create mode 100644 drivers/regulator/cpr3-util.c
  21. create mode 100644 drivers/regulator/cpr4-apss-regulator.c
  22. create mode 100644 include/soc/qcom/socinfo.h
  23. --- a/drivers/regulator/Kconfig
  24. +++ b/drivers/regulator/Kconfig
  25. @@ -1524,4 +1524,37 @@ config REGULATOR_QCOM_LABIBB
  26. boost regulator and IBB can be used as a negative boost regulator
  27. for LCD display panel.
  28. +config REGULATOR_CPR3
  29. + bool "QCOM CPR3 regulator core support"
  30. + help
  31. + This driver supports Core Power Reduction (CPR) version 3 controllers
  32. + which are used by some Qualcomm Technologies, Inc. SoCs to
  33. + manage important voltage regulators. CPR3 controllers are capable of
  34. + monitoring several ring oscillator sensing loops simultaneously. The
  35. + CPR3 controller informs software when the silicon conditions require
  36. + the supply voltage to be increased or decreased. On certain supply
  37. + rails, the CPR3 controller is able to propagate the voltage increase
  38. + or decrease requests all the way to the PMIC without software
  39. + involvement.
  40. +
  41. +config REGULATOR_CPR3_NPU
  42. + bool "QCOM CPR3 regulator for NPU"
  43. + depends on OF && REGULATOR_CPR3
  44. + help
  45. + This driver supports Qualcomm Technologies, Inc. NPU CPR3
  46. + regulator Which will always operate in open loop.
  47. +
  48. +config REGULATOR_CPR4_APSS
  49. + bool "QCOM CPR4 regulator for APSS"
  50. + depends on OF && REGULATOR_CPR3
  51. + help
  52. + This driver supports Qualcomm Technologies, Inc. APSS application
  53. + processor specific features including memory array power mux (APM)
  54. + switching, one CPR4 thread which monitor the two APSS clusters that
  55. + are both powered by a shared supply, hardware closed-loop auto
  56. + voltage stepping, voltage adjustments based on online core count,
  57. + voltage adjustments based on temperature readings, and voltage
  58. + adjustments for performance boost mode. This driver reads both initial
  59. + voltage and CPR target quotient values out of hardware fuses.
  60. +
  61. endif
  62. --- a/drivers/regulator/Makefile
  63. +++ b/drivers/regulator/Makefile
  64. @@ -110,6 +110,9 @@ obj-$(CONFIG_REGULATOR_QCOM_RPMH) += qco
  65. obj-$(CONFIG_REGULATOR_QCOM_SMD_RPM) += qcom_smd-regulator.o
  66. obj-$(CONFIG_REGULATOR_QCOM_SPMI) += qcom_spmi-regulator.o
  67. obj-$(CONFIG_REGULATOR_QCOM_USB_VBUS) += qcom_usb_vbus-regulator.o
  68. +obj-$(CONFIG_REGULATOR_CPR3) += cpr3-regulator.o cpr3-util.o
  69. +obj-$(CONFIG_REGULATOR_CPR3_NPU) += cpr3-npu-regulator.o
  70. +obj-$(CONFIG_REGULATOR_CPR4_APSS) += cpr4-apss-regulator.o
  71. obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
  72. obj-$(CONFIG_REGULATOR_PCA9450) += pca9450-regulator.o
  73. obj-$(CONFIG_REGULATOR_PF8X00) += pf8x00-regulator.o
  74. --- /dev/null
  75. +++ b/drivers/regulator/cpr3-npu-regulator.c
  76. @@ -0,0 +1,695 @@
  77. +/*
  78. + * Copyright (c) 2017, The Linux Foundation. All rights reserved.
  79. + *
  80. + * Permission to use, copy, modify, and/or distribute this software for any
  81. + * purpose with or without fee is hereby granted, provided that the above
  82. + * copyright notice and this permission notice appear in all copies.
  83. + *
  84. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  85. + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  86. + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  87. + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  88. + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  89. + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  90. + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  91. + */
  92. +
  93. +#include <linux/err.h>
  94. +#include <linux/platform_device.h>
  95. +#include <linux/module.h>
  96. +#include <linux/of.h>
  97. +#include <linux/of_device.h>
  98. +#include <linux/slab.h>
  99. +#include <linux/thermal.h>
  100. +
  101. +#include "cpr3-regulator.h"
  102. +
  103. +#define IPQ807x_NPU_FUSE_CORNERS 2
  104. +#define IPQ817x_NPU_FUSE_CORNERS 1
  105. +#define IPQ807x_NPU_FUSE_STEP_VOLT 8000
  106. +#define IPQ807x_NPU_VOLTAGE_FUSE_SIZE 6
  107. +#define IPQ807x_NPU_CPR_CLOCK_RATE 19200000
  108. +
  109. +#define IPQ807x_NPU_CPR_TCSR_START 6
  110. +#define IPQ807x_NPU_CPR_TCSR_END 7
  111. +
  112. +#define NPU_TSENS 5
  113. +
  114. +u32 g_valid_npu_fuse_count = IPQ807x_NPU_FUSE_CORNERS;
  115. +/**
  116. + * struct cpr3_ipq807x_npu_fuses - NPU specific fuse data for IPQ807x
  117. + * @init_voltage: Initial (i.e. open-loop) voltage fuse parameter value
  118. + * for each fuse corner (raw, not converted to a voltage)
  119. + * This struct holds the values for all of the fuses read from memory.
  120. + */
  121. +struct cpr3_ipq807x_npu_fuses {
  122. + u64 init_voltage[IPQ807x_NPU_FUSE_CORNERS];
  123. +};
  124. +
  125. +/*
  126. + * Constants which define the name of each fuse corner.
  127. + */
  128. +enum cpr3_ipq807x_npu_fuse_corner {
  129. + CPR3_IPQ807x_NPU_FUSE_CORNER_NOM = 0,
  130. + CPR3_IPQ807x_NPU_FUSE_CORNER_TURBO = 1,
  131. +};
  132. +
  133. +static const char * const cpr3_ipq807x_npu_fuse_corner_name[] = {
  134. + [CPR3_IPQ807x_NPU_FUSE_CORNER_NOM] = "NOM",
  135. + [CPR3_IPQ807x_NPU_FUSE_CORNER_TURBO] = "TURBO",
  136. +};
  137. +
  138. +/*
  139. + * IPQ807x NPU fuse parameter locations:
  140. + *
  141. + * Structs are organized with the following dimensions:
  142. + * Outer: 0 to 1 for fuse corners from lowest to highest corner
  143. + * Inner: large enough to hold the longest set of parameter segments which
  144. + * fully defines a fuse parameter, +1 (for NULL termination).
  145. + * Each segment corresponds to a contiguous group of bits from a
  146. + * single fuse row. These segments are concatentated together in
  147. + * order to form the full fuse parameter value. The segments for
  148. + * a given parameter may correspond to different fuse rows.
  149. + */
  150. +static struct cpr3_fuse_param
  151. +ipq807x_npu_init_voltage_param[IPQ807x_NPU_FUSE_CORNERS][2] = {
  152. + {{73, 22, 27}, {} },
  153. + {{73, 16, 21}, {} },
  154. +};
  155. +
  156. +/*
  157. + * Open loop voltage fuse reference voltages in microvolts for IPQ807x
  158. + */
  159. +static int
  160. +ipq807x_npu_fuse_ref_volt [IPQ807x_NPU_FUSE_CORNERS] = {
  161. + 912000,
  162. + 992000,
  163. +};
  164. +
  165. +/*
  166. + * IPQ9574 (Few parameters are changed, remaining are same as IPQ807x)
  167. + */
  168. +#define IPQ9574_NPU_FUSE_CORNERS 2
  169. +#define IPQ9574_NPU_FUSE_STEP_VOLT 10000
  170. +#define IPQ9574_NPU_CPR_CLOCK_RATE 24000000
  171. +
  172. +/*
  173. + * fues parameters for IPQ9574
  174. + */
  175. +static struct cpr3_fuse_param
  176. +ipq9574_npu_init_voltage_param[IPQ9574_NPU_FUSE_CORNERS][2] = {
  177. + {{105, 12, 17}, {} },
  178. + {{105, 6, 11}, {} },
  179. +};
  180. +
  181. +/*
  182. + * Open loop voltage fuse reference voltages in microvolts for IPQ9574
  183. + */
  184. +static int
  185. +ipq9574_npu_fuse_ref_volt [IPQ9574_NPU_FUSE_CORNERS] = {
  186. + 862500,
  187. + 987500,
  188. +};
  189. +
  190. +struct cpr3_controller *g_ctrl;
  191. +
  192. +void cpr3_npu_temp_notify(int sensor, int temp, int low_notif)
  193. +{
  194. + u32 prev_sensor_state;
  195. +
  196. + if (sensor != NPU_TSENS)
  197. + return;
  198. +
  199. + prev_sensor_state = g_ctrl->cur_sensor_state;
  200. + if (low_notif)
  201. + g_ctrl->cur_sensor_state |= BIT(sensor);
  202. + else
  203. + g_ctrl->cur_sensor_state &= ~BIT(sensor);
  204. +
  205. + if (!prev_sensor_state && g_ctrl->cur_sensor_state)
  206. + cpr3_handle_temp_open_loop_adjustment(g_ctrl, true);
  207. + else if (prev_sensor_state && !g_ctrl->cur_sensor_state)
  208. + cpr3_handle_temp_open_loop_adjustment(g_ctrl, false);
  209. +}
  210. +
  211. +/**
  212. + * cpr3_ipq807x_npu_read_fuse_data() - load NPU specific fuse parameter values
  213. + * @vreg: Pointer to the CPR3 regulator
  214. + *
  215. + * This function allocates a cpr3_ipq807x_npu_fuses struct, fills it with
  216. + * values read out of hardware fuses, and finally copies common fuse values
  217. + * into the CPR3 regulator struct.
  218. + *
  219. + * Return: 0 on success, errno on failure
  220. + */
  221. +static int cpr3_ipq807x_npu_read_fuse_data(struct cpr3_regulator *vreg)
  222. +{
  223. + void __iomem *base = vreg->thread->ctrl->fuse_base;
  224. + struct cpr3_ipq807x_npu_fuses *fuse;
  225. + int i, rc;
  226. +
  227. + fuse = devm_kzalloc(vreg->thread->ctrl->dev, sizeof(*fuse), GFP_KERNEL);
  228. + if (!fuse)
  229. + return -ENOMEM;
  230. +
  231. + for (i = 0; i < g_valid_npu_fuse_count; i++) {
  232. + rc = cpr3_read_fuse_param(base,
  233. + vreg->cpr3_regulator_data->init_voltage_param[i],
  234. + &fuse->init_voltage[i]);
  235. + if (rc) {
  236. + cpr3_err(vreg, "Unable to read fuse-corner %d initial voltage fuse, rc=%d\n",
  237. + i, rc);
  238. + return rc;
  239. + }
  240. + }
  241. +
  242. + vreg->fuse_corner_count = g_valid_npu_fuse_count;
  243. + vreg->platform_fuses = fuse;
  244. +
  245. + return 0;
  246. +}
  247. +
  248. +/**
  249. + * cpr3_npu_parse_corner_data() - parse NPU corner data from device tree
  250. + * properties of the CPR3 regulator's device node
  251. + * @vreg: Pointer to the CPR3 regulator
  252. + *
  253. + * Return: 0 on success, errno on failure
  254. + */
  255. +static int cpr3_npu_parse_corner_data(struct cpr3_regulator *vreg)
  256. +{
  257. + int rc;
  258. +
  259. + rc = cpr3_parse_common_corner_data(vreg);
  260. + if (rc) {
  261. + cpr3_err(vreg, "error reading corner data, rc=%d\n", rc);
  262. + return rc;
  263. + }
  264. +
  265. + return rc;
  266. +}
  267. +
  268. +/**
  269. + * cpr3_ipq807x_npu_calculate_open_loop_voltages() - calculate the open-loop
  270. + * voltage for each corner of a CPR3 regulator
  271. + * @vreg: Pointer to the CPR3 regulator
  272. + * @temp_correction: Temperature based correction
  273. + *
  274. + * If open-loop voltage interpolation is allowed in device tree, then
  275. + * this function calculates the open-loop voltage for a given corner using
  276. + * linear interpolation. This interpolation is performed using the processor
  277. + * frequencies of the lower and higher Fmax corners along with their fused
  278. + * open-loop voltages.
  279. + *
  280. + * If open-loop voltage interpolation is not allowed, then this function uses
  281. + * the Fmax fused open-loop voltage for all of the corners associated with a
  282. + * given fuse corner.
  283. + *
  284. + * Return: 0 on success, errno on failure
  285. + */
  286. +static int cpr3_ipq807x_npu_calculate_open_loop_voltages(
  287. + struct cpr3_regulator *vreg, bool temp_correction)
  288. +{
  289. + struct cpr3_ipq807x_npu_fuses *fuse = vreg->platform_fuses;
  290. + struct cpr3_controller *ctrl = vreg->thread->ctrl;
  291. + int i, j, rc = 0;
  292. + u64 freq_low, volt_low, freq_high, volt_high;
  293. + int *fuse_volt;
  294. + int *fmax_corner;
  295. +
  296. + fuse_volt = kcalloc(vreg->fuse_corner_count, sizeof(*fuse_volt),
  297. + GFP_KERNEL);
  298. + fmax_corner = kcalloc(vreg->fuse_corner_count, sizeof(*fmax_corner),
  299. + GFP_KERNEL);
  300. + if (!fuse_volt || !fmax_corner) {
  301. + rc = -ENOMEM;
  302. + goto done;
  303. + }
  304. +
  305. + for (i = 0; i < vreg->fuse_corner_count; i++) {
  306. + if (ctrl->cpr_global_setting == CPR_DISABLED)
  307. + fuse_volt[i] = vreg->cpr3_regulator_data->fuse_ref_volt[i];
  308. + else
  309. + fuse_volt[i] = cpr3_convert_open_loop_voltage_fuse(
  310. + vreg->cpr3_regulator_data->fuse_ref_volt[i],
  311. + vreg->cpr3_regulator_data->fuse_step_volt,
  312. + fuse->init_voltage[i],
  313. + IPQ807x_NPU_VOLTAGE_FUSE_SIZE);
  314. +
  315. + /* Log fused open-loop voltage values for debugging purposes. */
  316. + cpr3_info(vreg, "fused %8s: open-loop=%7d uV\n",
  317. + cpr3_ipq807x_npu_fuse_corner_name[i],
  318. + fuse_volt[i]);
  319. + }
  320. +
  321. + rc = cpr3_determine_part_type(vreg,
  322. + fuse_volt[CPR3_IPQ807x_NPU_FUSE_CORNER_TURBO]);
  323. + if (rc) {
  324. + cpr3_err(vreg,
  325. + "fused part type detection failed failed, rc=%d\n", rc);
  326. + goto done;
  327. + }
  328. +
  329. + rc = cpr3_adjust_fused_open_loop_voltages(vreg, fuse_volt);
  330. + if (rc) {
  331. + cpr3_err(vreg,
  332. + "fused open-loop voltage adjustment failed, rc=%d\n",
  333. + rc);
  334. + goto done;
  335. + }
  336. + if (temp_correction) {
  337. + rc = cpr3_determine_temp_base_open_loop_correction(vreg,
  338. + fuse_volt);
  339. + if (rc) {
  340. + cpr3_err(vreg,
  341. + "temp open-loop voltage adj. failed, rc=%d\n",
  342. + rc);
  343. + goto done;
  344. + }
  345. + }
  346. +
  347. + for (i = 1; i < vreg->fuse_corner_count; i++) {
  348. + if (fuse_volt[i] < fuse_volt[i - 1]) {
  349. + cpr3_info(vreg,
  350. + "fuse corner %d voltage=%d uV < fuse corner %d \
  351. + voltage=%d uV; overriding: fuse corner %d \
  352. + voltage=%d\n",
  353. + i, fuse_volt[i], i - 1, fuse_volt[i - 1],
  354. + i, fuse_volt[i - 1]);
  355. + fuse_volt[i] = fuse_volt[i - 1];
  356. + }
  357. + }
  358. +
  359. + /* Determine highest corner mapped to each fuse corner */
  360. + j = vreg->fuse_corner_count - 1;
  361. + for (i = vreg->corner_count - 1; i >= 0; i--) {
  362. + if (vreg->corner[i].cpr_fuse_corner == j) {
  363. + fmax_corner[j] = i;
  364. + j--;
  365. + }
  366. + }
  367. +
  368. + if (j >= 0) {
  369. + cpr3_err(vreg, "invalid fuse corner mapping\n");
  370. + rc = -EINVAL;
  371. + goto done;
  372. + }
  373. +
  374. + /*
  375. + * Interpolation is not possible for corners mapped to the lowest fuse
  376. + * corner so use the fuse corner value directly.
  377. + */
  378. + for (i = 0; i <= fmax_corner[0]; i++)
  379. + vreg->corner[i].open_loop_volt = fuse_volt[0];
  380. +
  381. + /* Interpolate voltages for the higher fuse corners. */
  382. + for (i = 1; i < vreg->fuse_corner_count; i++) {
  383. + freq_low = vreg->corner[fmax_corner[i - 1]].proc_freq;
  384. + volt_low = fuse_volt[i - 1];
  385. + freq_high = vreg->corner[fmax_corner[i]].proc_freq;
  386. + volt_high = fuse_volt[i];
  387. +
  388. + for (j = fmax_corner[i - 1] + 1; j <= fmax_corner[i]; j++)
  389. + vreg->corner[j].open_loop_volt = cpr3_interpolate(
  390. + freq_low, volt_low, freq_high, volt_high,
  391. + vreg->corner[j].proc_freq);
  392. + }
  393. +
  394. +done:
  395. + if (rc == 0) {
  396. + cpr3_debug(vreg, "unadjusted per-corner open-loop voltages:\n");
  397. + for (i = 0; i < vreg->corner_count; i++)
  398. + cpr3_debug(vreg, "open-loop[%2d] = %d uV\n", i,
  399. + vreg->corner[i].open_loop_volt);
  400. +
  401. + rc = cpr3_adjust_open_loop_voltages(vreg);
  402. + if (rc)
  403. + cpr3_err(vreg,
  404. + "open-loop voltage adjustment failed, rc=%d\n",
  405. + rc);
  406. + }
  407. +
  408. + kfree(fuse_volt);
  409. + kfree(fmax_corner);
  410. + return rc;
  411. +}
  412. +
  413. +/**
  414. + * cpr3_npu_print_settings() - print out NPU CPR configuration settings into
  415. + * the kernel log for debugging purposes
  416. + * @vreg: Pointer to the CPR3 regulator
  417. + */
  418. +static void cpr3_npu_print_settings(struct cpr3_regulator *vreg)
  419. +{
  420. + struct cpr3_corner *corner;
  421. + int i;
  422. +
  423. + cpr3_debug(vreg,
  424. + "Corner: Frequency (Hz), Fuse Corner, Floor (uV), \
  425. + Open-Loop (uV), Ceiling (uV)\n");
  426. + for (i = 0; i < vreg->corner_count; i++) {
  427. + corner = &vreg->corner[i];
  428. + cpr3_debug(vreg, "%3d: %10u, %2d, %7d, %7d, %7d\n",
  429. + i, corner->proc_freq, corner->cpr_fuse_corner,
  430. + corner->floor_volt, corner->open_loop_volt,
  431. + corner->ceiling_volt);
  432. + }
  433. +
  434. + if (vreg->thread->ctrl->apm)
  435. + cpr3_debug(vreg, "APM threshold = %d uV, APM adjust = %d uV\n",
  436. + vreg->thread->ctrl->apm_threshold_volt,
  437. + vreg->thread->ctrl->apm_adj_volt);
  438. +}
  439. +
  440. +/**
  441. + * cpr3_ipq807x_npu_calc_temp_based_ol_voltages() - Calculate the open loop
  442. + * voltages based on temperature based correction margins
  443. + * @vreg: Pointer to the CPR3 regulator
  444. + */
  445. +
  446. +static int
  447. +cpr3_ipq807x_npu_calc_temp_based_ol_voltages(struct cpr3_regulator *vreg,
  448. + bool temp_correction)
  449. +{
  450. + int rc, i;
  451. +
  452. + rc = cpr3_ipq807x_npu_calculate_open_loop_voltages(vreg,
  453. + temp_correction);
  454. + if (rc) {
  455. + cpr3_err(vreg,
  456. + "unable to calculate open-loop voltages, rc=%d\n", rc);
  457. + return rc;
  458. + }
  459. +
  460. + rc = cpr3_limit_open_loop_voltages(vreg);
  461. + if (rc) {
  462. + cpr3_err(vreg, "unable to limit open-loop voltages, rc=%d\n",
  463. + rc);
  464. + return rc;
  465. + }
  466. +
  467. + cpr3_open_loop_voltage_as_ceiling(vreg);
  468. +
  469. + rc = cpr3_limit_floor_voltages(vreg);
  470. + if (rc) {
  471. + cpr3_err(vreg, "unable to limit floor voltages, rc=%d\n", rc);
  472. + return rc;
  473. + }
  474. +
  475. + for (i = 0; i < vreg->corner_count; i++) {
  476. + if (temp_correction)
  477. + vreg->corner[i].cold_temp_open_loop_volt =
  478. + vreg->corner[i].open_loop_volt;
  479. + else
  480. + vreg->corner[i].normal_temp_open_loop_volt =
  481. + vreg->corner[i].open_loop_volt;
  482. + }
  483. +
  484. + cpr3_npu_print_settings(vreg);
  485. +
  486. + return rc;
  487. +}
  488. +
  489. +/**
  490. + * cpr3_npu_init_thread() - perform steps necessary to initialize the
  491. + * configuration data for a CPR3 thread
  492. + * @thread: Pointer to the CPR3 thread
  493. + *
  494. + * Return: 0 on success, errno on failure
  495. + */
  496. +static int cpr3_npu_init_thread(struct cpr3_thread *thread)
  497. +{
  498. + int rc;
  499. +
  500. + rc = cpr3_parse_common_thread_data(thread);
  501. + if (rc) {
  502. + cpr3_err(thread->ctrl,
  503. + "thread %u CPR thread data from DT- failed, rc=%d\n",
  504. + thread->thread_id, rc);
  505. + return rc;
  506. + }
  507. +
  508. + return 0;
  509. +}
  510. +
  511. +/**
  512. + * cpr3_npu_init_regulator() - perform all steps necessary to initialize the
  513. + * configuration data for a CPR3 regulator
  514. + * @vreg: Pointer to the CPR3 regulator
  515. + *
  516. + * Return: 0 on success, errno on failure
  517. + */
  518. +static int cpr3_npu_init_regulator(struct cpr3_regulator *vreg)
  519. +{
  520. + struct cpr3_ipq807x_npu_fuses *fuse;
  521. + int rc, cold_temp = 0;
  522. + bool can_adj_cold_temp = cpr3_can_adjust_cold_temp(vreg);
  523. +
  524. + rc = cpr3_ipq807x_npu_read_fuse_data(vreg);
  525. + if (rc) {
  526. + cpr3_err(vreg, "unable to read CPR fuse data, rc=%d\n", rc);
  527. + return rc;
  528. + }
  529. +
  530. + fuse = vreg->platform_fuses;
  531. +
  532. + rc = cpr3_npu_parse_corner_data(vreg);
  533. + if (rc) {
  534. + cpr3_err(vreg,
  535. + "Cannot read CPR corner data from DT, rc=%d\n", rc);
  536. + return rc;
  537. + }
  538. +
  539. + rc = cpr3_mem_acc_init(vreg);
  540. + if (rc) {
  541. + if (rc != -EPROBE_DEFER)
  542. + cpr3_err(vreg,
  543. + "Cannot initialize mem-acc regulator settings, rc=%d\n",
  544. + rc);
  545. + return rc;
  546. + }
  547. +
  548. + if (can_adj_cold_temp) {
  549. + rc = cpr3_ipq807x_npu_calc_temp_based_ol_voltages(vreg, true);
  550. + if (rc) {
  551. + cpr3_err(vreg,
  552. + "unable to calculate open-loop voltages, rc=%d\n", rc);
  553. + return rc;
  554. + }
  555. + }
  556. +
  557. + rc = cpr3_ipq807x_npu_calc_temp_based_ol_voltages(vreg, false);
  558. + if (rc) {
  559. + cpr3_err(vreg,
  560. + "unable to calculate open-loop voltages, rc=%d\n", rc);
  561. + return rc;
  562. + }
  563. +
  564. + if (can_adj_cold_temp) {
  565. + cpr3_info(vreg,
  566. + "Normal and Cold condition init done. Default to normal.\n");
  567. +
  568. + rc = cpr3_get_cold_temp_threshold(vreg, &cold_temp);
  569. + if (rc) {
  570. + cpr3_err(vreg,
  571. + "Get cold temperature threshold failed, rc=%d\n", rc);
  572. + return rc;
  573. + }
  574. + register_low_temp_notif(NPU_TSENS, cold_temp,
  575. + cpr3_npu_temp_notify);
  576. + }
  577. +
  578. + return rc;
  579. +}
  580. +
  581. +/**
  582. + * cpr3_npu_init_controller() - perform NPU CPR3 controller specific
  583. + * initializations
  584. + * @ctrl: Pointer to the CPR3 controller
  585. + *
  586. + * Return: 0 on success, errno on failure
  587. + */
  588. +static int cpr3_npu_init_controller(struct cpr3_controller *ctrl)
  589. +{
  590. + int rc;
  591. +
  592. + rc = cpr3_parse_open_loop_common_ctrl_data(ctrl);
  593. + if (rc) {
  594. + if (rc != -EPROBE_DEFER)
  595. + cpr3_err(ctrl, "unable to parse common controller data, rc=%d\n",
  596. + rc);
  597. + return rc;
  598. + }
  599. +
  600. + ctrl->ctrl_type = CPR_CTRL_TYPE_CPR3;
  601. + ctrl->supports_hw_closed_loop = false;
  602. +
  603. + return 0;
  604. +}
  605. +
  606. +static const struct cpr3_reg_data ipq807x_cpr_npu = {
  607. + .cpr_valid_fuse_count = IPQ807x_NPU_FUSE_CORNERS,
  608. + .init_voltage_param = ipq807x_npu_init_voltage_param,
  609. + .fuse_ref_volt = ipq807x_npu_fuse_ref_volt,
  610. + .fuse_step_volt = IPQ807x_NPU_FUSE_STEP_VOLT,
  611. + .cpr_clk_rate = IPQ807x_NPU_CPR_CLOCK_RATE,
  612. +};
  613. +
  614. +static const struct cpr3_reg_data ipq817x_cpr_npu = {
  615. + .cpr_valid_fuse_count = IPQ817x_NPU_FUSE_CORNERS,
  616. + .init_voltage_param = ipq807x_npu_init_voltage_param,
  617. + .fuse_ref_volt = ipq807x_npu_fuse_ref_volt,
  618. + .fuse_step_volt = IPQ807x_NPU_FUSE_STEP_VOLT,
  619. + .cpr_clk_rate = IPQ807x_NPU_CPR_CLOCK_RATE,
  620. +};
  621. +
  622. +static const struct cpr3_reg_data ipq9574_cpr_npu = {
  623. + .cpr_valid_fuse_count = IPQ9574_NPU_FUSE_CORNERS,
  624. + .init_voltage_param = ipq9574_npu_init_voltage_param,
  625. + .fuse_ref_volt = ipq9574_npu_fuse_ref_volt,
  626. + .fuse_step_volt = IPQ9574_NPU_FUSE_STEP_VOLT,
  627. + .cpr_clk_rate = IPQ9574_NPU_CPR_CLOCK_RATE,
  628. +};
  629. +
  630. +static struct of_device_id cpr3_regulator_match_table[] = {
  631. + {
  632. + .compatible = "qcom,cpr3-ipq807x-npu-regulator",
  633. + .data = &ipq807x_cpr_npu
  634. + },
  635. + {
  636. + .compatible = "qcom,cpr3-ipq817x-npu-regulator",
  637. + .data = &ipq817x_cpr_npu
  638. + },
  639. + {
  640. + .compatible = "qcom,cpr3-ipq9574-npu-regulator",
  641. + .data = &ipq9574_cpr_npu
  642. + },
  643. + {}
  644. +};
  645. +
  646. +static int cpr3_npu_regulator_probe(struct platform_device *pdev)
  647. +{
  648. + struct device *dev = &pdev->dev;
  649. + struct cpr3_controller *ctrl;
  650. + int i, rc;
  651. + const struct of_device_id *match;
  652. + struct cpr3_reg_data *cpr_data;
  653. +
  654. + if (!dev->of_node) {
  655. + dev_err(dev, "Device tree node is missing\n");
  656. + return -EINVAL;
  657. + }
  658. +
  659. + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
  660. + if (!ctrl)
  661. + return -ENOMEM;
  662. + g_ctrl = ctrl;
  663. +
  664. + match = of_match_device(cpr3_regulator_match_table, &pdev->dev);
  665. + if (!match)
  666. + return -ENODEV;
  667. +
  668. + cpr_data = (struct cpr3_reg_data *)match->data;
  669. + g_valid_npu_fuse_count = cpr_data->cpr_valid_fuse_count;
  670. + dev_info(dev, "NPU CPR valid fuse count: %d\n", g_valid_npu_fuse_count);
  671. + ctrl->cpr_clock_rate = cpr_data->cpr_clk_rate;
  672. +
  673. + ctrl->dev = dev;
  674. + /* Set to false later if anything precludes CPR operation. */
  675. + ctrl->cpr_allowed_hw = true;
  676. +
  677. + rc = of_property_read_string(dev->of_node, "qcom,cpr-ctrl-name",
  678. + &ctrl->name);
  679. + if (rc) {
  680. + cpr3_err(ctrl, "unable to read qcom,cpr-ctrl-name, rc=%d\n",
  681. + rc);
  682. + return rc;
  683. + }
  684. +
  685. + rc = cpr3_map_fuse_base(ctrl, pdev);
  686. + if (rc) {
  687. + cpr3_err(ctrl, "could not map fuse base address\n");
  688. + return rc;
  689. + }
  690. +
  691. + rc = cpr3_read_tcsr_setting(ctrl, pdev, IPQ807x_NPU_CPR_TCSR_START,
  692. + IPQ807x_NPU_CPR_TCSR_END);
  693. + if (rc) {
  694. + cpr3_err(ctrl, "could not read CPR tcsr rsetting\n");
  695. + return rc;
  696. + }
  697. +
  698. + rc = cpr3_allocate_threads(ctrl, 0, 0);
  699. + if (rc) {
  700. + cpr3_err(ctrl, "failed to allocate CPR thread array, rc=%d\n",
  701. + rc);
  702. + return rc;
  703. + }
  704. +
  705. + if (ctrl->thread_count != 1) {
  706. + cpr3_err(ctrl, "expected 1 thread but found %d\n",
  707. + ctrl->thread_count);
  708. + return -EINVAL;
  709. + }
  710. +
  711. + rc = cpr3_npu_init_controller(ctrl);
  712. + if (rc) {
  713. + if (rc != -EPROBE_DEFER)
  714. + cpr3_err(ctrl, "failed to initialize CPR controller parameters, rc=%d\n",
  715. + rc);
  716. + return rc;
  717. + }
  718. +
  719. + rc = cpr3_npu_init_thread(&ctrl->thread[0]);
  720. + if (rc) {
  721. + cpr3_err(ctrl, "thread initialization failed, rc=%d\n", rc);
  722. + return rc;
  723. + }
  724. +
  725. + for (i = 0; i < ctrl->thread[0].vreg_count; i++) {
  726. + ctrl->thread[0].vreg[i].cpr3_regulator_data = cpr_data;
  727. + rc = cpr3_npu_init_regulator(&ctrl->thread[0].vreg[i]);
  728. + if (rc) {
  729. + cpr3_err(&ctrl->thread[0].vreg[i], "regulator initialization failed, rc=%d\n",
  730. + rc);
  731. + return rc;
  732. + }
  733. + }
  734. +
  735. + platform_set_drvdata(pdev, ctrl);
  736. +
  737. + return cpr3_open_loop_regulator_register(pdev, ctrl);
  738. +}
  739. +
  740. +static int cpr3_npu_regulator_remove(struct platform_device *pdev)
  741. +{
  742. + struct cpr3_controller *ctrl = platform_get_drvdata(pdev);
  743. +
  744. + return cpr3_open_loop_regulator_unregister(ctrl);
  745. +}
  746. +
  747. +static struct platform_driver cpr3_npu_regulator_driver = {
  748. + .driver = {
  749. + .name = "qcom,cpr3-npu-regulator",
  750. + .of_match_table = cpr3_regulator_match_table,
  751. + .owner = THIS_MODULE,
  752. + },
  753. + .probe = cpr3_npu_regulator_probe,
  754. + .remove = cpr3_npu_regulator_remove,
  755. +};
  756. +
  757. +static int cpr3_regulator_init(void)
  758. +{
  759. + return platform_driver_register(&cpr3_npu_regulator_driver);
  760. +}
  761. +arch_initcall(cpr3_regulator_init);
  762. +
  763. +static void cpr3_regulator_exit(void)
  764. +{
  765. + platform_driver_unregister(&cpr3_npu_regulator_driver);
  766. +}
  767. +module_exit(cpr3_regulator_exit);
  768. +
  769. +MODULE_DESCRIPTION("QCOM CPR3 NPU regulator driver");
  770. +MODULE_LICENSE("Dual BSD/GPLv2");
  771. +MODULE_ALIAS("platform:npu-ipq807x");
  772. --- /dev/null
  773. +++ b/drivers/regulator/cpr3-regulator.c
  774. @@ -0,0 +1,5111 @@
  775. +/*
  776. + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
  777. + *
  778. + * This program is free software; you can redistribute it and/or modify
  779. + * it under the terms of the GNU General Public License version 2 and
  780. + * only version 2 as published by the Free Software Foundation.
  781. + *
  782. + * This program is distributed in the hope that it will be useful,
  783. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  784. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  785. + * GNU General Public License for more details.
  786. + */
  787. +
  788. +#define pr_fmt(fmt) "%s: " fmt, __func__
  789. +
  790. +#include <linux/bitops.h>
  791. +#include <linux/debugfs.h>
  792. +#include <linux/delay.h>
  793. +#include <linux/err.h>
  794. +#include <linux/init.h>
  795. +#include <linux/interrupt.h>
  796. +#include <linux/io.h>
  797. +#include <linux/kernel.h>
  798. +#include <linux/ktime.h>
  799. +#include <linux/list.h>
  800. +#include <linux/module.h>
  801. +#include <linux/of.h>
  802. +#include <linux/of_device.h>
  803. +#include <linux/platform_device.h>
  804. +#include <linux/pm_opp.h>
  805. +#include <linux/slab.h>
  806. +#include <linux/sort.h>
  807. +#include <linux/string.h>
  808. +#include <linux/uaccess.h>
  809. +#include <linux/regulator/driver.h>
  810. +#include <linux/regulator/machine.h>
  811. +#include <linux/regulator/of_regulator.h>
  812. +#include <linux/panic_notifier.h>
  813. +
  814. +#include "cpr3-regulator.h"
  815. +
  816. +#define CPR3_REGULATOR_CORNER_INVALID (-1)
  817. +#define CPR3_RO_MASK GENMASK(CPR3_RO_COUNT - 1, 0)
  818. +
  819. +/* CPR3 registers */
  820. +#define CPR3_REG_CPR_CTL 0x4
  821. +#define CPR3_CPR_CTL_LOOP_EN_MASK BIT(0)
  822. +#define CPR3_CPR_CTL_LOOP_ENABLE BIT(0)
  823. +#define CPR3_CPR_CTL_LOOP_DISABLE 0
  824. +#define CPR3_CPR_CTL_IDLE_CLOCKS_MASK GENMASK(5, 1)
  825. +#define CPR3_CPR_CTL_IDLE_CLOCKS_SHIFT 1
  826. +#define CPR3_CPR_CTL_COUNT_MODE_MASK GENMASK(7, 6)
  827. +#define CPR3_CPR_CTL_COUNT_MODE_SHIFT 6
  828. +#define CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_MIN 0
  829. +#define CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_MAX 1
  830. +#define CPR3_CPR_CTL_COUNT_MODE_STAGGERED 2
  831. +#define CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_AGE 3
  832. +#define CPR3_CPR_CTL_COUNT_REPEAT_MASK GENMASK(31, 9)
  833. +#define CPR3_CPR_CTL_COUNT_REPEAT_SHIFT 9
  834. +
  835. +#define CPR3_REG_CPR_STATUS 0x8
  836. +#define CPR3_CPR_STATUS_BUSY_MASK BIT(0)
  837. +#define CPR3_CPR_STATUS_AGING_MEASUREMENT_MASK BIT(1)
  838. +
  839. +/*
  840. + * This register is not present on controllers that support HW closed-loop
  841. + * except CPR4 APSS controller.
  842. + */
  843. +#define CPR3_REG_CPR_TIMER_AUTO_CONT 0xC
  844. +
  845. +#define CPR3_REG_CPR_STEP_QUOT 0x14
  846. +#define CPR3_CPR_STEP_QUOT_MIN_MASK GENMASK(5, 0)
  847. +#define CPR3_CPR_STEP_QUOT_MIN_SHIFT 0
  848. +#define CPR3_CPR_STEP_QUOT_MAX_MASK GENMASK(11, 6)
  849. +#define CPR3_CPR_STEP_QUOT_MAX_SHIFT 6
  850. +
  851. +#define CPR3_REG_GCNT(ro) (0xA0 + 0x4 * (ro))
  852. +
  853. +#define CPR3_REG_SENSOR_BYPASS_WRITE(sensor) (0xE0 + 0x4 * ((sensor) / 32))
  854. +#define CPR3_REG_SENSOR_BYPASS_WRITE_BANK(bank) (0xE0 + 0x4 * (bank))
  855. +
  856. +#define CPR3_REG_SENSOR_MASK_WRITE(sensor) (0x120 + 0x4 * ((sensor) / 32))
  857. +#define CPR3_REG_SENSOR_MASK_WRITE_BANK(bank) (0x120 + 0x4 * (bank))
  858. +#define CPR3_REG_SENSOR_MASK_READ(sensor) (0x140 + 0x4 * ((sensor) / 32))
  859. +
  860. +#define CPR3_REG_SENSOR_OWNER(sensor) (0x200 + 0x4 * (sensor))
  861. +
  862. +#define CPR3_REG_CONT_CMD 0x800
  863. +#define CPR3_CONT_CMD_ACK 0x1
  864. +#define CPR3_CONT_CMD_NACK 0x0
  865. +
  866. +#define CPR3_REG_THRESH(thread) (0x808 + 0x440 * (thread))
  867. +#define CPR3_THRESH_CONS_DOWN_MASK GENMASK(3, 0)
  868. +#define CPR3_THRESH_CONS_DOWN_SHIFT 0
  869. +#define CPR3_THRESH_CONS_UP_MASK GENMASK(7, 4)
  870. +#define CPR3_THRESH_CONS_UP_SHIFT 4
  871. +#define CPR3_THRESH_DOWN_THRESH_MASK GENMASK(12, 8)
  872. +#define CPR3_THRESH_DOWN_THRESH_SHIFT 8
  873. +#define CPR3_THRESH_UP_THRESH_MASK GENMASK(17, 13)
  874. +#define CPR3_THRESH_UP_THRESH_SHIFT 13
  875. +
  876. +#define CPR3_REG_RO_MASK(thread) (0x80C + 0x440 * (thread))
  877. +
  878. +#define CPR3_REG_RESULT0(thread) (0x810 + 0x440 * (thread))
  879. +#define CPR3_RESULT0_BUSY_MASK BIT(0)
  880. +#define CPR3_RESULT0_STEP_DN_MASK BIT(1)
  881. +#define CPR3_RESULT0_STEP_UP_MASK BIT(2)
  882. +#define CPR3_RESULT0_ERROR_STEPS_MASK GENMASK(7, 3)
  883. +#define CPR3_RESULT0_ERROR_STEPS_SHIFT 3
  884. +#define CPR3_RESULT0_ERROR_MASK GENMASK(19, 8)
  885. +#define CPR3_RESULT0_ERROR_SHIFT 8
  886. +#define CPR3_RESULT0_NEGATIVE_MASK BIT(20)
  887. +
  888. +#define CPR3_REG_RESULT1(thread) (0x814 + 0x440 * (thread))
  889. +#define CPR3_RESULT1_QUOT_MIN_MASK GENMASK(11, 0)
  890. +#define CPR3_RESULT1_QUOT_MIN_SHIFT 0
  891. +#define CPR3_RESULT1_QUOT_MAX_MASK GENMASK(23, 12)
  892. +#define CPR3_RESULT1_QUOT_MAX_SHIFT 12
  893. +#define CPR3_RESULT1_RO_MIN_MASK GENMASK(27, 24)
  894. +#define CPR3_RESULT1_RO_MIN_SHIFT 24
  895. +#define CPR3_RESULT1_RO_MAX_MASK GENMASK(31, 28)
  896. +#define CPR3_RESULT1_RO_MAX_SHIFT 28
  897. +
  898. +#define CPR3_REG_RESULT2(thread) (0x818 + 0x440 * (thread))
  899. +#define CPR3_RESULT2_STEP_QUOT_MIN_MASK GENMASK(5, 0)
  900. +#define CPR3_RESULT2_STEP_QUOT_MIN_SHIFT 0
  901. +#define CPR3_RESULT2_STEP_QUOT_MAX_MASK GENMASK(11, 6)
  902. +#define CPR3_RESULT2_STEP_QUOT_MAX_SHIFT 6
  903. +#define CPR3_RESULT2_SENSOR_MIN_MASK GENMASK(23, 16)
  904. +#define CPR3_RESULT2_SENSOR_MIN_SHIFT 16
  905. +#define CPR3_RESULT2_SENSOR_MAX_MASK GENMASK(31, 24)
  906. +#define CPR3_RESULT2_SENSOR_MAX_SHIFT 24
  907. +
  908. +#define CPR3_REG_IRQ_EN 0x81C
  909. +#define CPR3_REG_IRQ_CLEAR 0x820
  910. +#define CPR3_REG_IRQ_STATUS 0x824
  911. +#define CPR3_IRQ_UP BIT(3)
  912. +#define CPR3_IRQ_MID BIT(2)
  913. +#define CPR3_IRQ_DOWN BIT(1)
  914. +
  915. +#define CPR3_REG_TARGET_QUOT(thread, ro) \
  916. + (0x840 + 0x440 * (thread) + 0x4 * (ro))
  917. +
  918. +/* Registers found only on controllers that support HW closed-loop. */
  919. +#define CPR3_REG_PD_THROTTLE 0xE8
  920. +#define CPR3_PD_THROTTLE_DISABLE 0x0
  921. +
  922. +#define CPR3_REG_HW_CLOSED_LOOP 0x3000
  923. +#define CPR3_HW_CLOSED_LOOP_ENABLE 0x0
  924. +#define CPR3_HW_CLOSED_LOOP_DISABLE 0x1
  925. +
  926. +#define CPR3_REG_CPR_TIMER_MID_CONT 0x3004
  927. +#define CPR3_REG_CPR_TIMER_UP_DN_CONT 0x3008
  928. +
  929. +#define CPR3_REG_LAST_MEASUREMENT 0x7F8
  930. +#define CPR3_LAST_MEASUREMENT_THREAD_DN_SHIFT 0
  931. +#define CPR3_LAST_MEASUREMENT_THREAD_UP_SHIFT 4
  932. +#define CPR3_LAST_MEASUREMENT_THREAD_DN(thread) \
  933. + (BIT(thread) << CPR3_LAST_MEASUREMENT_THREAD_DN_SHIFT)
  934. +#define CPR3_LAST_MEASUREMENT_THREAD_UP(thread) \
  935. + (BIT(thread) << CPR3_LAST_MEASUREMENT_THREAD_UP_SHIFT)
  936. +#define CPR3_LAST_MEASUREMENT_AGGR_DN BIT(8)
  937. +#define CPR3_LAST_MEASUREMENT_AGGR_MID BIT(9)
  938. +#define CPR3_LAST_MEASUREMENT_AGGR_UP BIT(10)
  939. +#define CPR3_LAST_MEASUREMENT_VALID BIT(11)
  940. +#define CPR3_LAST_MEASUREMENT_SAW_ERROR BIT(12)
  941. +#define CPR3_LAST_MEASUREMENT_PD_BYPASS_MASK GENMASK(23, 16)
  942. +#define CPR3_LAST_MEASUREMENT_PD_BYPASS_SHIFT 16
  943. +
  944. +/* CPR4 controller specific registers and bit definitions */
  945. +#define CPR4_REG_CPR_TIMER_CLAMP 0x10
  946. +#define CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN BIT(27)
  947. +
  948. +#define CPR4_REG_MISC 0x700
  949. +#define CPR4_MISC_MARGIN_TABLE_ROW_SELECT_MASK GENMASK(23, 20)
  950. +#define CPR4_MISC_MARGIN_TABLE_ROW_SELECT_SHIFT 20
  951. +#define CPR4_MISC_TEMP_SENSOR_ID_START_MASK GENMASK(27, 24)
  952. +#define CPR4_MISC_TEMP_SENSOR_ID_START_SHIFT 24
  953. +#define CPR4_MISC_TEMP_SENSOR_ID_END_MASK GENMASK(31, 28)
  954. +#define CPR4_MISC_TEMP_SENSOR_ID_END_SHIFT 28
  955. +
  956. +#define CPR4_REG_SAW_ERROR_STEP_LIMIT 0x7A4
  957. +#define CPR4_SAW_ERROR_STEP_LIMIT_UP_MASK GENMASK(4, 0)
  958. +#define CPR4_SAW_ERROR_STEP_LIMIT_UP_SHIFT 0
  959. +#define CPR4_SAW_ERROR_STEP_LIMIT_DN_MASK GENMASK(9, 5)
  960. +#define CPR4_SAW_ERROR_STEP_LIMIT_DN_SHIFT 5
  961. +
  962. +#define CPR4_REG_MARGIN_TEMP_CORE_TIMERS 0x7A8
  963. +#define CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_MASK GENMASK(28, 18)
  964. +#define CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_SHIFT 18
  965. +
  966. +#define CPR4_REG_MARGIN_TEMP_CORE(core) (0x7AC + 0x4 * (core))
  967. +#define CPR4_MARGIN_TEMP_CORE_ADJ_MASK GENMASK(7, 0)
  968. +#define CPR4_MARGIN_TEMP_CORE_ADJ_SHIFT 8
  969. +
  970. +#define CPR4_REG_MARGIN_TEMP_POINT0N1 0x7F0
  971. +#define CPR4_MARGIN_TEMP_POINT0_MASK GENMASK(11, 0)
  972. +#define CPR4_MARGIN_TEMP_POINT0_SHIFT 0
  973. +#define CPR4_MARGIN_TEMP_POINT1_MASK GENMASK(23, 12)
  974. +#define CPR4_MARGIN_TEMP_POINT1_SHIFT 12
  975. +#define CPR4_REG_MARGIN_TEMP_POINT2 0x7F4
  976. +#define CPR4_MARGIN_TEMP_POINT2_MASK GENMASK(11, 0)
  977. +#define CPR4_MARGIN_TEMP_POINT2_SHIFT 0
  978. +
  979. +#define CPR4_REG_MARGIN_ADJ_CTL 0x7F8
  980. +#define CPR4_MARGIN_ADJ_CTL_BOOST_EN BIT(0)
  981. +#define CPR4_MARGIN_ADJ_CTL_CORE_ADJ_EN BIT(1)
  982. +#define CPR4_MARGIN_ADJ_CTL_TEMP_ADJ_EN BIT(2)
  983. +#define CPR4_MARGIN_ADJ_CTL_TIMER_SETTLE_VOLTAGE_EN BIT(3)
  984. +#define CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK BIT(4)
  985. +#define CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE BIT(4)
  986. +#define CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE 0
  987. +#define CPR4_MARGIN_ADJ_CTL_PER_RO_KV_MARGIN_EN BIT(7)
  988. +#define CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_EN BIT(8)
  989. +#define CPR4_MARGIN_ADJ_CTL_PMIC_STEP_SIZE_MASK GENMASK(16, 12)
  990. +#define CPR4_MARGIN_ADJ_CTL_PMIC_STEP_SIZE_SHIFT 12
  991. +#define CPR4_MARGIN_ADJ_CTL_INITIAL_TEMP_BAND_MASK GENMASK(21, 19)
  992. +#define CPR4_MARGIN_ADJ_CTL_INITIAL_TEMP_BAND_SHIFT 19
  993. +#define CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_MASK GENMASK(25, 22)
  994. +#define CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_SHIFT 22
  995. +#define CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_STEP_QUOT_MASK GENMASK(31, 26)
  996. +#define CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_STEP_QUOT_SHIFT 26
  997. +
  998. +#define CPR4_REG_CPR_MASK_THREAD(thread) (0x80C + 0x440 * (thread))
  999. +#define CPR4_CPR_MASK_THREAD_DISABLE_THREAD BIT(31)
  1000. +#define CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK GENMASK(15, 0)
  1001. +
  1002. +/*
  1003. + * The amount of time to wait for the CPR controller to become idle when
  1004. + * performing an aging measurement.
  1005. + */
  1006. +#define CPR3_AGING_MEASUREMENT_TIMEOUT_NS 5000000
  1007. +
  1008. +/*
  1009. + * The number of individual aging measurements to perform which are then
  1010. + * averaged together in order to determine the final aging adjustment value.
  1011. + */
  1012. +#define CPR3_AGING_MEASUREMENT_ITERATIONS 16
  1013. +
  1014. +/*
  1015. + * Aging measurements for the aged and unaged ring oscillators take place a few
  1016. + * microseconds apart. If the vdd-supply voltage fluctuates between the two
  1017. + * measurements, then the difference between them will be incorrect. The
  1018. + * difference could end up too high or too low. This constant defines the
  1019. + * number of lowest and highest measurements to ignore when averaging.
  1020. + */
  1021. +#define CPR3_AGING_MEASUREMENT_FILTER 3
  1022. +
  1023. +/*
  1024. + * The number of times to attempt the full aging measurement sequence before
  1025. + * declaring a measurement failure.
  1026. + */
  1027. +#define CPR3_AGING_RETRY_COUNT 5
  1028. +
  1029. +/*
  1030. + * The maximum time to wait in microseconds for a CPR register write to
  1031. + * complete.
  1032. + */
  1033. +#define CPR3_REGISTER_WRITE_DELAY_US 200
  1034. +
  1035. +static DEFINE_MUTEX(cpr3_controller_list_mutex);
  1036. +static LIST_HEAD(cpr3_controller_list);
  1037. +static struct dentry *cpr3_debugfs_base;
  1038. +
  1039. +/**
  1040. + * cpr3_read() - read four bytes from the memory address specified
  1041. + * @ctrl: Pointer to the CPR3 controller
  1042. + * @offset: Offset in bytes from the CPR3 controller's base address
  1043. + *
  1044. + * Return: memory address value
  1045. + */
  1046. +static inline u32 cpr3_read(struct cpr3_controller *ctrl, u32 offset)
  1047. +{
  1048. + if (!ctrl->cpr_enabled) {
  1049. + cpr3_err(ctrl, "CPR register reads are not possible when CPR clocks are disabled\n");
  1050. + return 0;
  1051. + }
  1052. +
  1053. + return readl_relaxed(ctrl->cpr_ctrl_base + offset);
  1054. +}
  1055. +
  1056. +/**
  1057. + * cpr3_write() - write four bytes to the memory address specified
  1058. + * @ctrl: Pointer to the CPR3 controller
  1059. + * @offset: Offset in bytes from the CPR3 controller's base address
  1060. + * @value: Value to write to the memory address
  1061. + *
  1062. + * Return: none
  1063. + */
  1064. +static inline void cpr3_write(struct cpr3_controller *ctrl, u32 offset,
  1065. + u32 value)
  1066. +{
  1067. + if (!ctrl->cpr_enabled) {
  1068. + cpr3_err(ctrl, "CPR register writes are not possible when CPR clocks are disabled\n");
  1069. + return;
  1070. + }
  1071. +
  1072. + writel_relaxed(value, ctrl->cpr_ctrl_base + offset);
  1073. +}
  1074. +
  1075. +/**
  1076. + * cpr3_masked_write() - perform a read-modify-write sequence so that only
  1077. + * masked bits are modified
  1078. + * @ctrl: Pointer to the CPR3 controller
  1079. + * @offset: Offset in bytes from the CPR3 controller's base address
  1080. + * @mask: Mask identifying the bits that should be modified
  1081. + * @value: Value to write to the memory address
  1082. + *
  1083. + * Return: none
  1084. + */
  1085. +static inline void cpr3_masked_write(struct cpr3_controller *ctrl, u32 offset,
  1086. + u32 mask, u32 value)
  1087. +{
  1088. + u32 reg_val, orig_val;
  1089. +
  1090. + if (!ctrl->cpr_enabled) {
  1091. + cpr3_err(ctrl, "CPR register writes are not possible when CPR clocks are disabled\n");
  1092. + return;
  1093. + }
  1094. +
  1095. + reg_val = orig_val = readl_relaxed(ctrl->cpr_ctrl_base + offset);
  1096. + reg_val &= ~mask;
  1097. + reg_val |= value & mask;
  1098. +
  1099. + if (reg_val != orig_val)
  1100. + writel_relaxed(reg_val, ctrl->cpr_ctrl_base + offset);
  1101. +}
  1102. +
  1103. +/**
  1104. + * cpr3_ctrl_loop_enable() - enable the CPR sensing loop for a given controller
  1105. + * @ctrl: Pointer to the CPR3 controller
  1106. + *
  1107. + * Return: none
  1108. + */
  1109. +static inline void cpr3_ctrl_loop_enable(struct cpr3_controller *ctrl)
  1110. +{
  1111. + if (ctrl->cpr_enabled && !(ctrl->aggr_corner.sdelta
  1112. + && ctrl->aggr_corner.sdelta->allow_boost))
  1113. + cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL,
  1114. + CPR3_CPR_CTL_LOOP_EN_MASK, CPR3_CPR_CTL_LOOP_ENABLE);
  1115. +}
  1116. +
  1117. +/**
  1118. + * cpr3_ctrl_loop_disable() - disable the CPR sensing loop for a given
  1119. + * controller
  1120. + * @ctrl: Pointer to the CPR3 controller
  1121. + *
  1122. + * Return: none
  1123. + */
  1124. +static inline void cpr3_ctrl_loop_disable(struct cpr3_controller *ctrl)
  1125. +{
  1126. + if (ctrl->cpr_enabled)
  1127. + cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL,
  1128. + CPR3_CPR_CTL_LOOP_EN_MASK, CPR3_CPR_CTL_LOOP_DISABLE);
  1129. +}
  1130. +
  1131. +/**
  1132. + * cpr3_clock_enable() - prepare and enable all clocks used by this CPR3
  1133. + * controller
  1134. + * @ctrl: Pointer to the CPR3 controller
  1135. + *
  1136. + * Return: 0 on success, errno on failure
  1137. + */
  1138. +static int cpr3_clock_enable(struct cpr3_controller *ctrl)
  1139. +{
  1140. + int rc;
  1141. +
  1142. + rc = clk_prepare_enable(ctrl->bus_clk);
  1143. + if (rc) {
  1144. + cpr3_err(ctrl, "failed to enable bus clock, rc=%d\n", rc);
  1145. + return rc;
  1146. + }
  1147. +
  1148. + rc = clk_prepare_enable(ctrl->iface_clk);
  1149. + if (rc) {
  1150. + cpr3_err(ctrl, "failed to enable interface clock, rc=%d\n", rc);
  1151. + clk_disable_unprepare(ctrl->bus_clk);
  1152. + return rc;
  1153. + }
  1154. +
  1155. + rc = clk_prepare_enable(ctrl->core_clk);
  1156. + if (rc) {
  1157. + cpr3_err(ctrl, "failed to enable core clock, rc=%d\n", rc);
  1158. + clk_disable_unprepare(ctrl->iface_clk);
  1159. + clk_disable_unprepare(ctrl->bus_clk);
  1160. + return rc;
  1161. + }
  1162. +
  1163. + return 0;
  1164. +}
  1165. +
  1166. +/**
  1167. + * cpr3_clock_disable() - disable and unprepare all clocks used by this CPR3
  1168. + * controller
  1169. + * @ctrl: Pointer to the CPR3 controller
  1170. + *
  1171. + * Return: none
  1172. + */
  1173. +static void cpr3_clock_disable(struct cpr3_controller *ctrl)
  1174. +{
  1175. + clk_disable_unprepare(ctrl->core_clk);
  1176. + clk_disable_unprepare(ctrl->iface_clk);
  1177. + clk_disable_unprepare(ctrl->bus_clk);
  1178. +}
  1179. +
  1180. +/**
  1181. + * cpr3_ctrl_clear_cpr4_config() - clear the CPR4 register configuration
  1182. + * programmed for current aggregated corner of a given controller
  1183. + * @ctrl: Pointer to the CPR3 controller
  1184. + *
  1185. + * Return: 0 on success, errno on failure
  1186. + */
  1187. +static inline int cpr3_ctrl_clear_cpr4_config(struct cpr3_controller *ctrl)
  1188. +{
  1189. + struct cpr4_sdelta *aggr_sdelta = ctrl->aggr_corner.sdelta;
  1190. + bool cpr_enabled = ctrl->cpr_enabled;
  1191. + int i, rc = 0;
  1192. +
  1193. + if (!aggr_sdelta || !(aggr_sdelta->allow_core_count_adj
  1194. + || aggr_sdelta->allow_temp_adj || aggr_sdelta->allow_boost))
  1195. + /* cpr4 features are not enabled */
  1196. + return 0;
  1197. +
  1198. + /* Ensure that CPR clocks are enabled before writing to registers. */
  1199. + if (!cpr_enabled) {
  1200. + rc = cpr3_clock_enable(ctrl);
  1201. + if (rc) {
  1202. + cpr3_err(ctrl, "clock enable failed, rc=%d\n", rc);
  1203. + return rc;
  1204. + }
  1205. + ctrl->cpr_enabled = true;
  1206. + }
  1207. +
  1208. + /*
  1209. + * Clear feature enable configuration made for current
  1210. + * aggregated corner.
  1211. + */
  1212. + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
  1213. + CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_MASK
  1214. + | CPR4_MARGIN_ADJ_CTL_CORE_ADJ_EN
  1215. + | CPR4_MARGIN_ADJ_CTL_TEMP_ADJ_EN
  1216. + | CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_EN
  1217. + | CPR4_MARGIN_ADJ_CTL_BOOST_EN
  1218. + | CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK, 0);
  1219. +
  1220. + cpr3_masked_write(ctrl, CPR4_REG_MISC,
  1221. + CPR4_MISC_MARGIN_TABLE_ROW_SELECT_MASK,
  1222. + 0 << CPR4_MISC_MARGIN_TABLE_ROW_SELECT_SHIFT);
  1223. +
  1224. + for (i = 0; i <= aggr_sdelta->max_core_count; i++) {
  1225. + /* Clear voltage margin adjustments programmed in TEMP_COREi */
  1226. + cpr3_write(ctrl, CPR4_REG_MARGIN_TEMP_CORE(i), 0);
  1227. + }
  1228. +
  1229. + /* Turn off CPR clocks if they were off before this function call. */
  1230. + if (!cpr_enabled) {
  1231. + cpr3_clock_disable(ctrl);
  1232. + ctrl->cpr_enabled = false;
  1233. + }
  1234. +
  1235. + return 0;
  1236. +}
  1237. +
  1238. +/**
  1239. + * cpr3_closed_loop_enable() - enable logical CPR closed-loop operation
  1240. + * @ctrl: Pointer to the CPR3 controller
  1241. + *
  1242. + * Return: 0 on success, errno on failure
  1243. + */
  1244. +static int cpr3_closed_loop_enable(struct cpr3_controller *ctrl)
  1245. +{
  1246. + int rc;
  1247. +
  1248. + if (!ctrl->cpr_allowed_hw || !ctrl->cpr_allowed_sw) {
  1249. + cpr3_err(ctrl, "cannot enable closed-loop CPR operation because it is disallowed\n");
  1250. + return -EPERM;
  1251. + } else if (ctrl->cpr_enabled) {
  1252. + /* Already enabled */
  1253. + return 0;
  1254. + } else if (ctrl->cpr_suspended) {
  1255. + /*
  1256. + * CPR must remain disabled as the system is entering suspend.
  1257. + */
  1258. + return 0;
  1259. + }
  1260. +
  1261. + rc = cpr3_clock_enable(ctrl);
  1262. + if (rc) {
  1263. + cpr3_err(ctrl, "unable to enable CPR clocks, rc=%d\n", rc);
  1264. + return rc;
  1265. + }
  1266. +
  1267. + ctrl->cpr_enabled = true;
  1268. + cpr3_debug(ctrl, "CPR closed-loop operation enabled\n");
  1269. +
  1270. + return 0;
  1271. +}
  1272. +
  1273. +/**
  1274. + * cpr3_closed_loop_disable() - disable logical CPR closed-loop operation
  1275. + * @ctrl: Pointer to the CPR3 controller
  1276. + *
  1277. + * Return: 0 on success, errno on failure
  1278. + */
  1279. +static inline int cpr3_closed_loop_disable(struct cpr3_controller *ctrl)
  1280. +{
  1281. + if (!ctrl->cpr_enabled) {
  1282. + /* Already disabled */
  1283. + return 0;
  1284. + }
  1285. +
  1286. + cpr3_clock_disable(ctrl);
  1287. + ctrl->cpr_enabled = false;
  1288. + cpr3_debug(ctrl, "CPR closed-loop operation disabled\n");
  1289. +
  1290. + return 0;
  1291. +}
  1292. +
  1293. +/**
  1294. + * cpr3_regulator_get_gcnt() - returns the GCNT register value corresponding
  1295. + * to the clock rate and sensor time of the CPR3 controller
  1296. + * @ctrl: Pointer to the CPR3 controller
  1297. + *
  1298. + * Return: GCNT value
  1299. + */
  1300. +static u32 cpr3_regulator_get_gcnt(struct cpr3_controller *ctrl)
  1301. +{
  1302. + u64 temp;
  1303. + unsigned int remainder;
  1304. + u32 gcnt;
  1305. +
  1306. + temp = (u64)ctrl->cpr_clock_rate * (u64)ctrl->sensor_time;
  1307. + remainder = do_div(temp, 1000000000);
  1308. + if (remainder)
  1309. + temp++;
  1310. + /*
  1311. + * GCNT == 0 corresponds to a single ref clock measurement interval so
  1312. + * offset GCNT values by 1.
  1313. + */
  1314. + gcnt = temp - 1;
  1315. +
  1316. + return gcnt;
  1317. +}
  1318. +
  1319. +/**
  1320. + * cpr3_regulator_init_thread() - performs hardware initialization of CPR
  1321. + * thread registers
  1322. + * @thread: Pointer to the CPR3 thread
  1323. + *
  1324. + * CPR interface/bus clocks must be enabled before calling this function.
  1325. + *
  1326. + * Return: 0 on success, errno on failure
  1327. + */
  1328. +static int cpr3_regulator_init_thread(struct cpr3_thread *thread)
  1329. +{
  1330. + u32 reg;
  1331. +
  1332. + reg = (thread->consecutive_up << CPR3_THRESH_CONS_UP_SHIFT)
  1333. + & CPR3_THRESH_CONS_UP_MASK;
  1334. + reg |= (thread->consecutive_down << CPR3_THRESH_CONS_DOWN_SHIFT)
  1335. + & CPR3_THRESH_CONS_DOWN_MASK;
  1336. + reg |= (thread->up_threshold << CPR3_THRESH_UP_THRESH_SHIFT)
  1337. + & CPR3_THRESH_UP_THRESH_MASK;
  1338. + reg |= (thread->down_threshold << CPR3_THRESH_DOWN_THRESH_SHIFT)
  1339. + & CPR3_THRESH_DOWN_THRESH_MASK;
  1340. +
  1341. + cpr3_write(thread->ctrl, CPR3_REG_THRESH(thread->thread_id), reg);
  1342. +
  1343. + /*
  1344. + * Mask all RO's initially so that unused thread doesn't contribute
  1345. + * to closed-loop voltage.
  1346. + */
  1347. + cpr3_write(thread->ctrl, CPR3_REG_RO_MASK(thread->thread_id),
  1348. + CPR3_RO_MASK);
  1349. +
  1350. + return 0;
  1351. +}
  1352. +
  1353. +/**
  1354. + * cpr4_regulator_init_temp_points() - performs hardware initialization of CPR4
  1355. + * registers to track tsen temperature data and also specify the
  1356. + * temperature band range values to apply different voltage margins
  1357. + * @ctrl: Pointer to the CPR3 controller
  1358. + *
  1359. + * CPR interface/bus clocks must be enabled before calling this function.
  1360. + *
  1361. + * Return: 0 on success, errno on failure
  1362. + */
  1363. +static int cpr4_regulator_init_temp_points(struct cpr3_controller *ctrl)
  1364. +{
  1365. + if (!ctrl->allow_temp_adj)
  1366. + return 0;
  1367. +
  1368. + cpr3_masked_write(ctrl, CPR4_REG_MISC,
  1369. + CPR4_MISC_TEMP_SENSOR_ID_START_MASK,
  1370. + ctrl->temp_sensor_id_start
  1371. + << CPR4_MISC_TEMP_SENSOR_ID_START_SHIFT);
  1372. +
  1373. + cpr3_masked_write(ctrl, CPR4_REG_MISC,
  1374. + CPR4_MISC_TEMP_SENSOR_ID_END_MASK,
  1375. + ctrl->temp_sensor_id_end
  1376. + << CPR4_MISC_TEMP_SENSOR_ID_END_SHIFT);
  1377. +
  1378. + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_TEMP_POINT2,
  1379. + CPR4_MARGIN_TEMP_POINT2_MASK,
  1380. + (ctrl->temp_band_count == 4 ? ctrl->temp_points[2] : 0x7FF)
  1381. + << CPR4_MARGIN_TEMP_POINT2_SHIFT);
  1382. +
  1383. + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_TEMP_POINT0N1,
  1384. + CPR4_MARGIN_TEMP_POINT1_MASK,
  1385. + (ctrl->temp_band_count >= 3 ? ctrl->temp_points[1] : 0x7FF)
  1386. + << CPR4_MARGIN_TEMP_POINT1_SHIFT);
  1387. +
  1388. + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_TEMP_POINT0N1,
  1389. + CPR4_MARGIN_TEMP_POINT0_MASK,
  1390. + (ctrl->temp_band_count >= 2 ? ctrl->temp_points[0] : 0x7FF)
  1391. + << CPR4_MARGIN_TEMP_POINT0_SHIFT);
  1392. + return 0;
  1393. +}
  1394. +
  1395. +/**
  1396. + * cpr3_regulator_init_cpr4() - performs hardware initialization at the
  1397. + * controller and thread level required for CPR4 operation.
  1398. + * @ctrl: Pointer to the CPR3 controller
  1399. + *
  1400. + * CPR interface/bus clocks must be enabled before calling this function.
  1401. + * This function allocates sdelta structures and sdelta tables for aggregated
  1402. + * corners of the controller and its threads.
  1403. + *
  1404. + * Return: 0 on success, errno on failure
  1405. + */
  1406. +static int cpr3_regulator_init_cpr4(struct cpr3_controller *ctrl)
  1407. +{
  1408. + struct cpr3_thread *thread;
  1409. + struct cpr3_regulator *vreg;
  1410. + struct cpr4_sdelta *sdelta;
  1411. + int i, j, ctrl_max_core_count, thread_max_core_count, rc = 0;
  1412. + bool ctrl_valid_sdelta, thread_valid_sdelta;
  1413. + u32 pmic_step_size = 1;
  1414. + int thread_id = 0;
  1415. + u64 temp;
  1416. +
  1417. + if (ctrl->supports_hw_closed_loop) {
  1418. + if (ctrl->saw_use_unit_mV)
  1419. + pmic_step_size = ctrl->step_volt / 1000;
  1420. + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
  1421. + CPR4_MARGIN_ADJ_CTL_PMIC_STEP_SIZE_MASK,
  1422. + (pmic_step_size
  1423. + << CPR4_MARGIN_ADJ_CTL_PMIC_STEP_SIZE_SHIFT));
  1424. +
  1425. + cpr3_masked_write(ctrl, CPR4_REG_SAW_ERROR_STEP_LIMIT,
  1426. + CPR4_SAW_ERROR_STEP_LIMIT_DN_MASK,
  1427. + (ctrl->down_error_step_limit
  1428. + << CPR4_SAW_ERROR_STEP_LIMIT_DN_SHIFT));
  1429. +
  1430. + cpr3_masked_write(ctrl, CPR4_REG_SAW_ERROR_STEP_LIMIT,
  1431. + CPR4_SAW_ERROR_STEP_LIMIT_UP_MASK,
  1432. + (ctrl->up_error_step_limit
  1433. + << CPR4_SAW_ERROR_STEP_LIMIT_UP_SHIFT));
  1434. +
  1435. + /*
  1436. + * Enable thread aggregation regardless of which threads are
  1437. + * enabled or disabled.
  1438. + */
  1439. + cpr3_masked_write(ctrl, CPR4_REG_CPR_TIMER_CLAMP,
  1440. + CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN,
  1441. + CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN);
  1442. +
  1443. + switch (ctrl->thread_count) {
  1444. + case 0:
  1445. + /* Disable both threads */
  1446. + cpr3_masked_write(ctrl, CPR4_REG_CPR_MASK_THREAD(0),
  1447. + CPR4_CPR_MASK_THREAD_DISABLE_THREAD
  1448. + | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK,
  1449. + CPR4_CPR_MASK_THREAD_DISABLE_THREAD
  1450. + | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK);
  1451. +
  1452. + cpr3_masked_write(ctrl, CPR4_REG_CPR_MASK_THREAD(1),
  1453. + CPR4_CPR_MASK_THREAD_DISABLE_THREAD
  1454. + | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK,
  1455. + CPR4_CPR_MASK_THREAD_DISABLE_THREAD
  1456. + | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK);
  1457. + break;
  1458. + case 1:
  1459. + /* Disable unused thread */
  1460. + thread_id = ctrl->thread[0].thread_id ? 0 : 1;
  1461. + cpr3_masked_write(ctrl,
  1462. + CPR4_REG_CPR_MASK_THREAD(thread_id),
  1463. + CPR4_CPR_MASK_THREAD_DISABLE_THREAD
  1464. + | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK,
  1465. + CPR4_CPR_MASK_THREAD_DISABLE_THREAD
  1466. + | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK);
  1467. + break;
  1468. + }
  1469. + }
  1470. +
  1471. + if (!ctrl->allow_core_count_adj && !ctrl->allow_temp_adj
  1472. + && !ctrl->allow_boost) {
  1473. + /*
  1474. + * Skip below configuration as none of the features
  1475. + * are enabled.
  1476. + */
  1477. + return rc;
  1478. + }
  1479. +
  1480. + if (ctrl->supports_hw_closed_loop)
  1481. + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
  1482. + CPR4_MARGIN_ADJ_CTL_TIMER_SETTLE_VOLTAGE_EN,
  1483. + CPR4_MARGIN_ADJ_CTL_TIMER_SETTLE_VOLTAGE_EN);
  1484. +
  1485. + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
  1486. + CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_STEP_QUOT_MASK,
  1487. + ctrl->step_quot_fixed
  1488. + << CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_STEP_QUOT_SHIFT);
  1489. +
  1490. + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
  1491. + CPR4_MARGIN_ADJ_CTL_PER_RO_KV_MARGIN_EN,
  1492. + (ctrl->use_dynamic_step_quot
  1493. + ? CPR4_MARGIN_ADJ_CTL_PER_RO_KV_MARGIN_EN : 0));
  1494. +
  1495. + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
  1496. + CPR4_MARGIN_ADJ_CTL_INITIAL_TEMP_BAND_MASK,
  1497. + ctrl->initial_temp_band
  1498. + << CPR4_MARGIN_ADJ_CTL_INITIAL_TEMP_BAND_SHIFT);
  1499. +
  1500. + rc = cpr4_regulator_init_temp_points(ctrl);
  1501. + if (rc) {
  1502. + cpr3_err(ctrl, "initialize temp points failed, rc=%d\n", rc);
  1503. + return rc;
  1504. + }
  1505. +
  1506. + if (ctrl->voltage_settling_time) {
  1507. + /*
  1508. + * Configure the settling timer used to account for
  1509. + * one VDD supply step.
  1510. + */
  1511. + temp = (u64)ctrl->cpr_clock_rate
  1512. + * (u64)ctrl->voltage_settling_time;
  1513. + do_div(temp, 1000000000);
  1514. + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_TEMP_CORE_TIMERS,
  1515. + CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_MASK,
  1516. + temp
  1517. + << CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_SHIFT);
  1518. + }
  1519. +
  1520. + /*
  1521. + * Allocate memory for cpr4_sdelta structure and sdelta table for
  1522. + * controller aggregated corner by finding the maximum core count
  1523. + * used by any cpr3 regulators.
  1524. + */
  1525. + ctrl_max_core_count = 1;
  1526. + ctrl_valid_sdelta = false;
  1527. + for (i = 0; i < ctrl->thread_count; i++) {
  1528. + thread = &ctrl->thread[i];
  1529. +
  1530. + /*
  1531. + * Allocate memory for cpr4_sdelta structure and sdelta table
  1532. + * for thread aggregated corner by finding the maximum core
  1533. + * count used by any cpr3 regulators of the thread.
  1534. + */
  1535. + thread_max_core_count = 1;
  1536. + thread_valid_sdelta = false;
  1537. + for (j = 0; j < thread->vreg_count; j++) {
  1538. + vreg = &thread->vreg[j];
  1539. + thread_max_core_count = max(thread_max_core_count,
  1540. + vreg->max_core_count);
  1541. + thread_valid_sdelta |= (vreg->allow_core_count_adj
  1542. + | vreg->allow_temp_adj
  1543. + | vreg->allow_boost);
  1544. + }
  1545. + if (thread_valid_sdelta) {
  1546. + sdelta = devm_kzalloc(ctrl->dev, sizeof(*sdelta),
  1547. + GFP_KERNEL);
  1548. + if (!sdelta)
  1549. + return -ENOMEM;
  1550. +
  1551. + sdelta->table = devm_kcalloc(ctrl->dev,
  1552. + thread_max_core_count
  1553. + * ctrl->temp_band_count,
  1554. + sizeof(*sdelta->table),
  1555. + GFP_KERNEL);
  1556. + if (!sdelta->table)
  1557. + return -ENOMEM;
  1558. +
  1559. + sdelta->boost_table = devm_kcalloc(ctrl->dev,
  1560. + ctrl->temp_band_count,
  1561. + sizeof(*sdelta->boost_table),
  1562. + GFP_KERNEL);
  1563. + if (!sdelta->boost_table)
  1564. + return -ENOMEM;
  1565. +
  1566. + thread->aggr_corner.sdelta = sdelta;
  1567. + }
  1568. +
  1569. + ctrl_valid_sdelta |= thread_valid_sdelta;
  1570. + ctrl_max_core_count = max(ctrl_max_core_count,
  1571. + thread_max_core_count);
  1572. + }
  1573. +
  1574. + if (ctrl_valid_sdelta) {
  1575. + sdelta = devm_kzalloc(ctrl->dev, sizeof(*sdelta), GFP_KERNEL);
  1576. + if (!sdelta)
  1577. + return -ENOMEM;
  1578. +
  1579. + sdelta->table = devm_kcalloc(ctrl->dev, ctrl_max_core_count
  1580. + * ctrl->temp_band_count,
  1581. + sizeof(*sdelta->table), GFP_KERNEL);
  1582. + if (!sdelta->table)
  1583. + return -ENOMEM;
  1584. +
  1585. + sdelta->boost_table = devm_kcalloc(ctrl->dev,
  1586. + ctrl->temp_band_count,
  1587. + sizeof(*sdelta->boost_table),
  1588. + GFP_KERNEL);
  1589. + if (!sdelta->boost_table)
  1590. + return -ENOMEM;
  1591. +
  1592. + ctrl->aggr_corner.sdelta = sdelta;
  1593. + }
  1594. +
  1595. + return 0;
  1596. +}
  1597. +
  1598. +/**
  1599. + * cpr3_write_temp_core_margin() - programs hardware SDELTA registers with
  1600. + * the voltage margin adjustments that need to be applied for
  1601. + * different online core-count and temperature bands.
  1602. + * @ctrl: Pointer to the CPR3 controller
  1603. + * @addr: SDELTA register address
  1604. + * @temp_core_adj: Array of voltage margin values for different temperature
  1605. + * bands.
  1606. + *
  1607. + * CPR interface/bus clocks must be enabled before calling this function.
  1608. + *
  1609. + * Return: none
  1610. + */
  1611. +static void cpr3_write_temp_core_margin(struct cpr3_controller *ctrl,
  1612. + int addr, int *temp_core_adj)
  1613. +{
  1614. + int i, margin_steps;
  1615. + u32 reg = 0;
  1616. +
  1617. + for (i = 0; i < ctrl->temp_band_count; i++) {
  1618. + margin_steps = max(min(temp_core_adj[i], 127), -128);
  1619. + reg |= (margin_steps & CPR4_MARGIN_TEMP_CORE_ADJ_MASK) <<
  1620. + (i * CPR4_MARGIN_TEMP_CORE_ADJ_SHIFT);
  1621. + }
  1622. +
  1623. + cpr3_write(ctrl, addr, reg);
  1624. + cpr3_debug(ctrl, "sdelta offset=0x%08x, val=0x%08x\n", addr, reg);
  1625. +}
  1626. +
  1627. +/**
  1628. + * cpr3_controller_program_sdelta() - programs hardware SDELTA registers with
  1629. + * the voltage margin adjustments that need to be applied at
  1630. + * different online core-count and temperature bands. Also,
  1631. + * programs hardware register configuration for per-online-core
  1632. + * and per-temperature based adjustments.
  1633. + * @ctrl: Pointer to the CPR3 controller
  1634. + *
  1635. + * CPR interface/bus clocks must be enabled before calling this function.
  1636. + *
  1637. + * Return: 0 on success, errno on failure
  1638. + */
  1639. +static int cpr3_controller_program_sdelta(struct cpr3_controller *ctrl)
  1640. +{
  1641. + struct cpr3_corner *corner = &ctrl->aggr_corner;
  1642. + struct cpr4_sdelta *sdelta = corner->sdelta;
  1643. + int i, index, max_core_count, rc = 0;
  1644. + bool cpr_enabled = ctrl->cpr_enabled;
  1645. +
  1646. + if (!sdelta)
  1647. + /* cpr4_sdelta not defined for current aggregated corner */
  1648. + return 0;
  1649. +
  1650. + if (ctrl->supports_hw_closed_loop && ctrl->cpr_enabled) {
  1651. + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
  1652. + CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK,
  1653. + (ctrl->use_hw_closed_loop && !sdelta->allow_boost)
  1654. + ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE : 0);
  1655. + }
  1656. +
  1657. + if (!sdelta->allow_core_count_adj && !sdelta->allow_temp_adj
  1658. + && !sdelta->allow_boost) {
  1659. + /*
  1660. + * Per-online-core, per-temperature and voltage boost
  1661. + * adjustments are disabled for this aggregation corner.
  1662. + */
  1663. + return 0;
  1664. + }
  1665. +
  1666. + /* Ensure that CPR clocks are enabled before writing to registers. */
  1667. + if (!cpr_enabled) {
  1668. + rc = cpr3_clock_enable(ctrl);
  1669. + if (rc) {
  1670. + cpr3_err(ctrl, "clock enable failed, rc=%d\n", rc);
  1671. + return rc;
  1672. + }
  1673. + ctrl->cpr_enabled = true;
  1674. + }
  1675. +
  1676. + max_core_count = sdelta->max_core_count;
  1677. +
  1678. + if (sdelta->allow_core_count_adj || sdelta->allow_temp_adj) {
  1679. + if (sdelta->allow_core_count_adj) {
  1680. + /* Program TEMP_CORE0 to same margins as TEMP_CORE1 */
  1681. + cpr3_write_temp_core_margin(ctrl,
  1682. + CPR4_REG_MARGIN_TEMP_CORE(0),
  1683. + &sdelta->table[0]);
  1684. + }
  1685. +
  1686. + for (i = 0; i < max_core_count; i++) {
  1687. + index = i * sdelta->temp_band_count;
  1688. + /*
  1689. + * Program TEMP_COREi with voltage margin adjustments
  1690. + * that need to be applied when the number of cores
  1691. + * becomes i.
  1692. + */
  1693. + cpr3_write_temp_core_margin(ctrl,
  1694. + CPR4_REG_MARGIN_TEMP_CORE(
  1695. + sdelta->allow_core_count_adj
  1696. + ? i + 1 : max_core_count),
  1697. + &sdelta->table[index]);
  1698. + }
  1699. + }
  1700. +
  1701. + if (sdelta->allow_boost) {
  1702. + /* Program only boost_num_cores row of SDELTA */
  1703. + cpr3_write_temp_core_margin(ctrl,
  1704. + CPR4_REG_MARGIN_TEMP_CORE(sdelta->boost_num_cores),
  1705. + &sdelta->boost_table[0]);
  1706. + }
  1707. +
  1708. + if (!sdelta->allow_core_count_adj && !sdelta->allow_boost) {
  1709. + cpr3_masked_write(ctrl, CPR4_REG_MISC,
  1710. + CPR4_MISC_MARGIN_TABLE_ROW_SELECT_MASK,
  1711. + max_core_count
  1712. + << CPR4_MISC_MARGIN_TABLE_ROW_SELECT_SHIFT);
  1713. + }
  1714. +
  1715. + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
  1716. + CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_MASK
  1717. + | CPR4_MARGIN_ADJ_CTL_CORE_ADJ_EN
  1718. + | CPR4_MARGIN_ADJ_CTL_TEMP_ADJ_EN
  1719. + | CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_EN
  1720. + | CPR4_MARGIN_ADJ_CTL_BOOST_EN,
  1721. + max_core_count << CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_SHIFT
  1722. + | ((sdelta->allow_core_count_adj || sdelta->allow_boost)
  1723. + ? CPR4_MARGIN_ADJ_CTL_CORE_ADJ_EN : 0)
  1724. + | ((sdelta->allow_temp_adj && ctrl->supports_hw_closed_loop)
  1725. + ? CPR4_MARGIN_ADJ_CTL_TEMP_ADJ_EN : 0)
  1726. + | (((ctrl->use_hw_closed_loop && !sdelta->allow_boost)
  1727. + || !ctrl->supports_hw_closed_loop)
  1728. + ? CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_EN : 0)
  1729. + | (sdelta->allow_boost
  1730. + ? CPR4_MARGIN_ADJ_CTL_BOOST_EN : 0));
  1731. +
  1732. + /*
  1733. + * Ensure that all previous CPR register writes have completed before
  1734. + * continuing.
  1735. + */
  1736. + mb();
  1737. +
  1738. + /* Turn off CPR clocks if they were off before this function call. */
  1739. + if (!cpr_enabled) {
  1740. + cpr3_clock_disable(ctrl);
  1741. + ctrl->cpr_enabled = false;
  1742. + }
  1743. +
  1744. + return 0;
  1745. +}
  1746. +
  1747. +/**
  1748. + * cpr3_regulator_init_ctrl() - performs hardware initialization of CPR
  1749. + * controller registers
  1750. + * @ctrl: Pointer to the CPR3 controller
  1751. + *
  1752. + * Return: 0 on success, errno on failure
  1753. + */
  1754. +static int cpr3_regulator_init_ctrl(struct cpr3_controller *ctrl)
  1755. +{
  1756. + int i, j, k, m, rc;
  1757. + u32 ro_used = 0;
  1758. + u32 gcnt, cont_dly, up_down_dly, val;
  1759. + u64 temp;
  1760. + char *mode;
  1761. +
  1762. + if (ctrl->core_clk) {
  1763. + rc = clk_set_rate(ctrl->core_clk, ctrl->cpr_clock_rate);
  1764. + if (rc) {
  1765. + cpr3_err(ctrl, "clk_set_rate(core_clk, %u) failed, rc=%d\n",
  1766. + ctrl->cpr_clock_rate, rc);
  1767. + return rc;
  1768. + }
  1769. + }
  1770. +
  1771. + rc = cpr3_clock_enable(ctrl);
  1772. + if (rc) {
  1773. + cpr3_err(ctrl, "clock enable failed, rc=%d\n", rc);
  1774. + return rc;
  1775. + }
  1776. + ctrl->cpr_enabled = true;
  1777. +
  1778. + /* Find all RO's used by any corner of any regulator. */
  1779. + for (i = 0; i < ctrl->thread_count; i++)
  1780. + for (j = 0; j < ctrl->thread[i].vreg_count; j++)
  1781. + for (k = 0; k < ctrl->thread[i].vreg[j].corner_count;
  1782. + k++)
  1783. + for (m = 0; m < CPR3_RO_COUNT; m++)
  1784. + if (ctrl->thread[i].vreg[j].corner[k].
  1785. + target_quot[m])
  1786. + ro_used |= BIT(m);
  1787. +
  1788. + /* Configure the GCNT of the RO's that will be used */
  1789. + gcnt = cpr3_regulator_get_gcnt(ctrl);
  1790. + for (i = 0; i < CPR3_RO_COUNT; i++)
  1791. + if (ro_used & BIT(i))
  1792. + cpr3_write(ctrl, CPR3_REG_GCNT(i), gcnt);
  1793. +
  1794. + /* Configure the loop delay time */
  1795. + temp = (u64)ctrl->cpr_clock_rate * (u64)ctrl->loop_time;
  1796. + do_div(temp, 1000000000);
  1797. + cont_dly = temp;
  1798. + if (ctrl->supports_hw_closed_loop
  1799. + && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3)
  1800. + cpr3_write(ctrl, CPR3_REG_CPR_TIMER_MID_CONT, cont_dly);
  1801. + else
  1802. + cpr3_write(ctrl, CPR3_REG_CPR_TIMER_AUTO_CONT, cont_dly);
  1803. +
  1804. + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
  1805. + temp = (u64)ctrl->cpr_clock_rate *
  1806. + (u64)ctrl->up_down_delay_time;
  1807. + do_div(temp, 1000000000);
  1808. + up_down_dly = temp;
  1809. + if (ctrl->supports_hw_closed_loop)
  1810. + cpr3_write(ctrl, CPR3_REG_CPR_TIMER_UP_DN_CONT,
  1811. + up_down_dly);
  1812. + cpr3_debug(ctrl, "up_down_dly=%u, up_down_delay_time=%u ns\n",
  1813. + up_down_dly, ctrl->up_down_delay_time);
  1814. + }
  1815. +
  1816. + cpr3_debug(ctrl, "cpr_clock_rate=%u HZ, sensor_time=%u ns, loop_time=%u ns, gcnt=%u, cont_dly=%u\n",
  1817. + ctrl->cpr_clock_rate, ctrl->sensor_time, ctrl->loop_time,
  1818. + gcnt, cont_dly);
  1819. +
  1820. + /* Configure CPR sensor operation */
  1821. + val = (ctrl->idle_clocks << CPR3_CPR_CTL_IDLE_CLOCKS_SHIFT)
  1822. + & CPR3_CPR_CTL_IDLE_CLOCKS_MASK;
  1823. + val |= (ctrl->count_mode << CPR3_CPR_CTL_COUNT_MODE_SHIFT)
  1824. + & CPR3_CPR_CTL_COUNT_MODE_MASK;
  1825. + val |= (ctrl->count_repeat << CPR3_CPR_CTL_COUNT_REPEAT_SHIFT)
  1826. + & CPR3_CPR_CTL_COUNT_REPEAT_MASK;
  1827. + cpr3_write(ctrl, CPR3_REG_CPR_CTL, val);
  1828. +
  1829. + cpr3_debug(ctrl, "idle_clocks=%u, count_mode=%u, count_repeat=%u; CPR_CTL=0x%08X\n",
  1830. + ctrl->idle_clocks, ctrl->count_mode, ctrl->count_repeat, val);
  1831. +
  1832. + /* Configure CPR default step quotients */
  1833. + val = (ctrl->step_quot_init_min << CPR3_CPR_STEP_QUOT_MIN_SHIFT)
  1834. + & CPR3_CPR_STEP_QUOT_MIN_MASK;
  1835. + val |= (ctrl->step_quot_init_max << CPR3_CPR_STEP_QUOT_MAX_SHIFT)
  1836. + & CPR3_CPR_STEP_QUOT_MAX_MASK;
  1837. + cpr3_write(ctrl, CPR3_REG_CPR_STEP_QUOT, val);
  1838. +
  1839. + cpr3_debug(ctrl, "step_quot_min=%u, step_quot_max=%u; STEP_QUOT=0x%08X\n",
  1840. + ctrl->step_quot_init_min, ctrl->step_quot_init_max, val);
  1841. +
  1842. + /* Configure the CPR sensor ownership */
  1843. + for (i = 0; i < ctrl->sensor_count; i++)
  1844. + cpr3_write(ctrl, CPR3_REG_SENSOR_OWNER(i),
  1845. + ctrl->sensor_owner[i]);
  1846. +
  1847. + /* Configure per-thread registers */
  1848. + for (i = 0; i < ctrl->thread_count; i++) {
  1849. + rc = cpr3_regulator_init_thread(&ctrl->thread[i]);
  1850. + if (rc) {
  1851. + cpr3_err(ctrl, "CPR thread register initialization failed, rc=%d\n",
  1852. + rc);
  1853. + return rc;
  1854. + }
  1855. + }
  1856. +
  1857. + if (ctrl->supports_hw_closed_loop) {
  1858. + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
  1859. + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
  1860. + CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK,
  1861. + ctrl->use_hw_closed_loop
  1862. + ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE
  1863. + : CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE);
  1864. + } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
  1865. + cpr3_write(ctrl, CPR3_REG_HW_CLOSED_LOOP,
  1866. + ctrl->use_hw_closed_loop
  1867. + ? CPR3_HW_CLOSED_LOOP_ENABLE
  1868. + : CPR3_HW_CLOSED_LOOP_DISABLE);
  1869. +
  1870. + cpr3_debug(ctrl, "PD_THROTTLE=0x%08X\n",
  1871. + ctrl->proc_clock_throttle);
  1872. + }
  1873. +
  1874. + if ((ctrl->use_hw_closed_loop ||
  1875. + ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) &&
  1876. + ctrl->vdd_limit_regulator) {
  1877. + rc = regulator_enable(ctrl->vdd_limit_regulator);
  1878. + if (rc) {
  1879. + cpr3_err(ctrl, "CPR limit regulator enable failed, rc=%d\n",
  1880. + rc);
  1881. + return rc;
  1882. + }
  1883. + }
  1884. + }
  1885. +
  1886. + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
  1887. + rc = cpr3_regulator_init_cpr4(ctrl);
  1888. + if (rc) {
  1889. + cpr3_err(ctrl, "CPR4-specific controller initialization failed, rc=%d\n",
  1890. + rc);
  1891. + return rc;
  1892. + }
  1893. + }
  1894. +
  1895. + /* Ensure that all register writes complete before disabling clocks. */
  1896. + wmb();
  1897. +
  1898. + cpr3_clock_disable(ctrl);
  1899. + ctrl->cpr_enabled = false;
  1900. +
  1901. + if (!ctrl->cpr_allowed_sw || !ctrl->cpr_allowed_hw)
  1902. + mode = "open-loop";
  1903. + else if (ctrl->supports_hw_closed_loop)
  1904. + mode = ctrl->use_hw_closed_loop
  1905. + ? "HW closed-loop" : "SW closed-loop";
  1906. + else
  1907. + mode = "closed-loop";
  1908. +
  1909. + cpr3_info(ctrl, "Default CPR mode = %s", mode);
  1910. +
  1911. + return 0;
  1912. +}
  1913. +
  1914. +/**
  1915. + * cpr3_regulator_set_target_quot() - configure the target quotient for each
  1916. + * RO of the CPR3 thread and set the RO mask
  1917. + * @thread: Pointer to the CPR3 thread
  1918. + *
  1919. + * Return: none
  1920. + */
  1921. +static void cpr3_regulator_set_target_quot(struct cpr3_thread *thread)
  1922. +{
  1923. + u32 new_quot, last_quot;
  1924. + int i;
  1925. +
  1926. + if (thread->aggr_corner.ro_mask == CPR3_RO_MASK
  1927. + && thread->last_closed_loop_aggr_corner.ro_mask == CPR3_RO_MASK) {
  1928. + /* Avoid writing target quotients since all RO's are masked. */
  1929. + return;
  1930. + } else if (thread->aggr_corner.ro_mask == CPR3_RO_MASK) {
  1931. + cpr3_write(thread->ctrl, CPR3_REG_RO_MASK(thread->thread_id),
  1932. + CPR3_RO_MASK);
  1933. + thread->last_closed_loop_aggr_corner.ro_mask = CPR3_RO_MASK;
  1934. + /*
  1935. + * Only the RO_MASK register needs to be written since all
  1936. + * RO's are masked.
  1937. + */
  1938. + return;
  1939. + } else if (thread->aggr_corner.ro_mask
  1940. + != thread->last_closed_loop_aggr_corner.ro_mask) {
  1941. + cpr3_write(thread->ctrl, CPR3_REG_RO_MASK(thread->thread_id),
  1942. + thread->aggr_corner.ro_mask);
  1943. + }
  1944. +
  1945. + for (i = 0; i < CPR3_RO_COUNT; i++) {
  1946. + new_quot = thread->aggr_corner.target_quot[i];
  1947. + last_quot = thread->last_closed_loop_aggr_corner.target_quot[i];
  1948. + if (new_quot != last_quot)
  1949. + cpr3_write(thread->ctrl,
  1950. + CPR3_REG_TARGET_QUOT(thread->thread_id, i),
  1951. + new_quot);
  1952. + }
  1953. +
  1954. + thread->last_closed_loop_aggr_corner = thread->aggr_corner;
  1955. +
  1956. + return;
  1957. +}
  1958. +
  1959. +/**
  1960. + * cpr3_update_vreg_closed_loop_volt() - update the last known settled
  1961. + * closed loop voltage for a CPR3 regulator
  1962. + * @vreg: Pointer to the CPR3 regulator
  1963. + * @vdd_volt: Last known settled voltage in microvolts for the
  1964. + * VDD supply
  1965. + * @reg_last_measurement: Value read from the LAST_MEASUREMENT register
  1966. + *
  1967. + * Return: none
  1968. + */
  1969. +static void cpr3_update_vreg_closed_loop_volt(struct cpr3_regulator *vreg,
  1970. + int vdd_volt, u32 reg_last_measurement)
  1971. +{
  1972. + bool step_dn, step_up, aggr_step_up, aggr_step_dn, aggr_step_mid;
  1973. + bool valid, pd_valid, saw_error;
  1974. + struct cpr3_controller *ctrl = vreg->thread->ctrl;
  1975. + struct cpr3_corner *corner;
  1976. + u32 id;
  1977. +
  1978. + if (vreg->last_closed_loop_corner == CPR3_REGULATOR_CORNER_INVALID)
  1979. + return;
  1980. + else
  1981. + corner = &vreg->corner[vreg->last_closed_loop_corner];
  1982. +
  1983. + if (vreg->thread->last_closed_loop_aggr_corner.ro_mask
  1984. + == CPR3_RO_MASK || !vreg->aggregated) {
  1985. + return;
  1986. + } else if (!ctrl->cpr_enabled || !ctrl->last_corner_was_closed_loop) {
  1987. + return;
  1988. + } else if (ctrl->thread_count == 1
  1989. + && vdd_volt >= corner->floor_volt
  1990. + && vdd_volt <= corner->ceiling_volt) {
  1991. + corner->last_volt = vdd_volt;
  1992. + cpr3_debug(vreg, "last_volt updated: last_volt[%d]=%d, ceiling_volt[%d]=%d, floor_volt[%d]=%d\n",
  1993. + vreg->last_closed_loop_corner, corner->last_volt,
  1994. + vreg->last_closed_loop_corner,
  1995. + corner->ceiling_volt,
  1996. + vreg->last_closed_loop_corner,
  1997. + corner->floor_volt);
  1998. + return;
  1999. + } else if (!ctrl->supports_hw_closed_loop) {
  2000. + return;
  2001. + } else if (ctrl->ctrl_type != CPR_CTRL_TYPE_CPR3) {
  2002. + corner->last_volt = vdd_volt;
  2003. + cpr3_debug(vreg, "last_volt updated: last_volt[%d]=%d, ceiling_volt[%d]=%d, floor_volt[%d]=%d\n",
  2004. + vreg->last_closed_loop_corner, corner->last_volt,
  2005. + vreg->last_closed_loop_corner,
  2006. + corner->ceiling_volt,
  2007. + vreg->last_closed_loop_corner,
  2008. + corner->floor_volt);
  2009. + return;
  2010. + }
  2011. +
  2012. + /* CPR clocks are on and HW closed loop is supported */
  2013. + valid = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_VALID);
  2014. + if (!valid) {
  2015. + cpr3_debug(vreg, "CPR_LAST_VALID_MEASUREMENT=0x%X valid bit not set\n",
  2016. + reg_last_measurement);
  2017. + return;
  2018. + }
  2019. +
  2020. + id = vreg->thread->thread_id;
  2021. +
  2022. + step_dn
  2023. + = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_THREAD_DN(id));
  2024. + step_up
  2025. + = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_THREAD_UP(id));
  2026. + aggr_step_dn = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_AGGR_DN);
  2027. + aggr_step_mid
  2028. + = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_AGGR_MID);
  2029. + aggr_step_up = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_AGGR_UP);
  2030. + saw_error = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_SAW_ERROR);
  2031. + pd_valid
  2032. + = !((((reg_last_measurement & CPR3_LAST_MEASUREMENT_PD_BYPASS_MASK)
  2033. + >> CPR3_LAST_MEASUREMENT_PD_BYPASS_SHIFT)
  2034. + & vreg->pd_bypass_mask) == vreg->pd_bypass_mask);
  2035. +
  2036. + if (!pd_valid) {
  2037. + cpr3_debug(vreg, "CPR_LAST_VALID_MEASUREMENT=0x%X, all power domains bypassed\n",
  2038. + reg_last_measurement);
  2039. + return;
  2040. + } else if (step_dn && step_up) {
  2041. + cpr3_err(vreg, "both up and down status bits set, CPR_LAST_VALID_MEASUREMENT=0x%X\n",
  2042. + reg_last_measurement);
  2043. + return;
  2044. + } else if (aggr_step_dn && step_dn && vdd_volt < corner->last_volt
  2045. + && vdd_volt >= corner->floor_volt) {
  2046. + corner->last_volt = vdd_volt;
  2047. + } else if (aggr_step_up && step_up && vdd_volt > corner->last_volt
  2048. + && vdd_volt <= corner->ceiling_volt) {
  2049. + corner->last_volt = vdd_volt;
  2050. + } else if (aggr_step_mid
  2051. + && vdd_volt >= corner->floor_volt
  2052. + && vdd_volt <= corner->ceiling_volt) {
  2053. + corner->last_volt = vdd_volt;
  2054. + } else if (saw_error && (vdd_volt == corner->ceiling_volt
  2055. + || vdd_volt == corner->floor_volt)) {
  2056. + corner->last_volt = vdd_volt;
  2057. + } else {
  2058. + cpr3_debug(vreg, "last_volt not updated: last_volt[%d]=%d, ceiling_volt[%d]=%d, floor_volt[%d]=%d, vdd_volt=%d, CPR_LAST_VALID_MEASUREMENT=0x%X\n",
  2059. + vreg->last_closed_loop_corner, corner->last_volt,
  2060. + vreg->last_closed_loop_corner,
  2061. + corner->ceiling_volt,
  2062. + vreg->last_closed_loop_corner, corner->floor_volt,
  2063. + vdd_volt, reg_last_measurement);
  2064. + return;
  2065. + }
  2066. +
  2067. + cpr3_debug(vreg, "last_volt updated: last_volt[%d]=%d, ceiling_volt[%d]=%d, floor_volt[%d]=%d, CPR_LAST_VALID_MEASUREMENT=0x%X\n",
  2068. + vreg->last_closed_loop_corner, corner->last_volt,
  2069. + vreg->last_closed_loop_corner, corner->ceiling_volt,
  2070. + vreg->last_closed_loop_corner, corner->floor_volt,
  2071. + reg_last_measurement);
  2072. +}
  2073. +
  2074. +/**
  2075. + * cpr3_regulator_mem_acc_bhs_used() - determines if mem-acc regulators powered
  2076. + * through a BHS are associated with the CPR3 controller or any of
  2077. + * the CPR3 regulators it controls.
  2078. + * @ctrl: Pointer to the CPR3 controller
  2079. + *
  2080. + * This function determines if the CPR3 controller or any of its CPR3 regulators
  2081. + * need to manage mem-acc regulators that are currently powered through a BHS
  2082. + * and whose corner selection is based upon a particular voltage threshold.
  2083. + *
  2084. + * Return: true or false
  2085. + */
  2086. +static bool cpr3_regulator_mem_acc_bhs_used(struct cpr3_controller *ctrl)
  2087. +{
  2088. + struct cpr3_regulator *vreg;
  2089. + int i, j;
  2090. +
  2091. + if (!ctrl->mem_acc_threshold_volt)
  2092. + return false;
  2093. +
  2094. + if (ctrl->mem_acc_regulator)
  2095. + return true;
  2096. +
  2097. + for (i = 0; i < ctrl->thread_count; i++) {
  2098. + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
  2099. + vreg = &ctrl->thread[i].vreg[j];
  2100. +
  2101. + if (vreg->mem_acc_regulator)
  2102. + return true;
  2103. + }
  2104. + }
  2105. +
  2106. + return false;
  2107. +}
  2108. +
  2109. +/**
  2110. + * cpr3_regulator_config_bhs_mem_acc() - configure the mem-acc regulator
  2111. + * settings for hardware blocks currently powered through the BHS.
  2112. + * @ctrl: Pointer to the CPR3 controller
  2113. + * @new_volt: New voltage in microvolts that VDD supply needs to
  2114. + * end up at
  2115. + * @last_volt: Pointer to the last known voltage in microvolts for the
  2116. + * VDD supply
  2117. + * @aggr_corner: Pointer to the CPR3 corner which corresponds to the max
  2118. + * corner aggregated from all CPR3 threads managed by the
  2119. + * CPR3 controller
  2120. + *
  2121. + * This function programs the mem-acc regulator corners for CPR3 regulators
  2122. + * whose LDO regulators are in bypassed state. The function also handles
  2123. + * CPR3 controllers which utilize mem-acc regulators that operate independently
  2124. + * from the LDO hardware and that must be programmed when the VDD supply
  2125. + * crosses a particular voltage threshold.
  2126. + *
  2127. + * Return: 0 on success, errno on failure. If the VDD supply voltage is
  2128. + * modified, last_volt is updated to reflect the new voltage setpoint.
  2129. + */
  2130. +static int cpr3_regulator_config_bhs_mem_acc(struct cpr3_controller *ctrl,
  2131. + int new_volt, int *last_volt,
  2132. + struct cpr3_corner *aggr_corner)
  2133. +{
  2134. + struct cpr3_regulator *vreg;
  2135. + int i, j, rc, mem_acc_corn, safe_volt;
  2136. + int mem_acc_volt = ctrl->mem_acc_threshold_volt;
  2137. + int ref_volt;
  2138. +
  2139. + if (!cpr3_regulator_mem_acc_bhs_used(ctrl))
  2140. + return 0;
  2141. +
  2142. + ref_volt = ctrl->use_hw_closed_loop ? aggr_corner->floor_volt :
  2143. + new_volt;
  2144. +
  2145. + if (((*last_volt < mem_acc_volt && mem_acc_volt <= ref_volt) ||
  2146. + (*last_volt >= mem_acc_volt && mem_acc_volt > ref_volt))) {
  2147. + if (ref_volt < *last_volt)
  2148. + safe_volt = max(mem_acc_volt, aggr_corner->last_volt);
  2149. + else
  2150. + safe_volt = max(mem_acc_volt, *last_volt);
  2151. +
  2152. + rc = regulator_set_voltage(ctrl->vdd_regulator, safe_volt,
  2153. + new_volt < *last_volt ?
  2154. + ctrl->aggr_corner.ceiling_volt :
  2155. + new_volt);
  2156. + if (rc) {
  2157. + cpr3_err(ctrl, "regulator_set_voltage(vdd) == %d failed, rc=%d\n",
  2158. + safe_volt, rc);
  2159. + return rc;
  2160. + }
  2161. +
  2162. + *last_volt = safe_volt;
  2163. +
  2164. + mem_acc_corn = ref_volt < mem_acc_volt ?
  2165. + ctrl->mem_acc_corner_map[CPR3_MEM_ACC_LOW_CORNER] :
  2166. + ctrl->mem_acc_corner_map[CPR3_MEM_ACC_HIGH_CORNER];
  2167. +
  2168. + if (ctrl->mem_acc_regulator) {
  2169. + rc = regulator_set_voltage(ctrl->mem_acc_regulator,
  2170. + mem_acc_corn, mem_acc_corn);
  2171. + if (rc) {
  2172. + cpr3_err(ctrl, "regulator_set_voltage(mem_acc) == %d failed, rc=%d\n",
  2173. + mem_acc_corn, rc);
  2174. + return rc;
  2175. + }
  2176. + }
  2177. +
  2178. + for (i = 0; i < ctrl->thread_count; i++) {
  2179. + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
  2180. + vreg = &ctrl->thread[i].vreg[j];
  2181. +
  2182. + if (!vreg->mem_acc_regulator)
  2183. + continue;
  2184. +
  2185. + rc = regulator_set_voltage(
  2186. + vreg->mem_acc_regulator, mem_acc_corn,
  2187. + mem_acc_corn);
  2188. + if (rc) {
  2189. + cpr3_err(vreg, "regulator_set_voltage(mem_acc) == %d failed, rc=%d\n",
  2190. + mem_acc_corn, rc);
  2191. + return rc;
  2192. + }
  2193. + }
  2194. + }
  2195. + }
  2196. +
  2197. + return 0;
  2198. +}
  2199. +
  2200. +/**
  2201. + * cpr3_regulator_switch_apm_mode() - switch the mode of the APM controller
  2202. + * associated with a given CPR3 controller
  2203. + * @ctrl: Pointer to the CPR3 controller
  2204. + * @new_volt: New voltage in microvolts that VDD supply needs to
  2205. + * end up at
  2206. + * @last_volt: Pointer to the last known voltage in microvolts for the
  2207. + * VDD supply
  2208. + * @aggr_corner: Pointer to the CPR3 corner which corresponds to the max
  2209. + * corner aggregated from all CPR3 threads managed by the
  2210. + * CPR3 controller
  2211. + *
  2212. + * This function requests a switch of the APM mode while guaranteeing
  2213. + * any LDO regulator hardware requirements are satisfied. The function must
  2214. + * be called once it is known a new VDD supply setpoint crosses the APM
  2215. + * voltage threshold.
  2216. + *
  2217. + * Return: 0 on success, errno on failure. If the VDD supply voltage is
  2218. + * modified, last_volt is updated to reflect the new voltage setpoint.
  2219. + */
  2220. +static int cpr3_regulator_switch_apm_mode(struct cpr3_controller *ctrl,
  2221. + int new_volt, int *last_volt,
  2222. + struct cpr3_corner *aggr_corner)
  2223. +{
  2224. + struct regulator *vdd = ctrl->vdd_regulator;
  2225. + int apm_volt = ctrl->apm_threshold_volt;
  2226. + int orig_last_volt = *last_volt;
  2227. + int rc;
  2228. +
  2229. + rc = regulator_set_voltage(vdd, apm_volt, apm_volt);
  2230. + if (rc) {
  2231. + cpr3_err(ctrl, "regulator_set_voltage(vdd) == %d failed, rc=%d\n",
  2232. + apm_volt, rc);
  2233. + return rc;
  2234. + }
  2235. +
  2236. + *last_volt = apm_volt;
  2237. +
  2238. + rc = msm_apm_set_supply(ctrl->apm, new_volt >= apm_volt
  2239. + ? ctrl->apm_high_supply : ctrl->apm_low_supply);
  2240. + if (rc) {
  2241. + cpr3_err(ctrl, "APM switch failed, rc=%d\n", rc);
  2242. + /* Roll back the voltage. */
  2243. + regulator_set_voltage(vdd, orig_last_volt, INT_MAX);
  2244. + *last_volt = orig_last_volt;
  2245. + return rc;
  2246. + }
  2247. + return 0;
  2248. +}
  2249. +
  2250. +/**
  2251. + * cpr3_regulator_config_voltage_crossings() - configure APM and mem-acc
  2252. + * settings depending upon a new VDD supply setpoint
  2253. + *
  2254. + * @ctrl: Pointer to the CPR3 controller
  2255. + * @new_volt: New voltage in microvolts that VDD supply needs to
  2256. + * end up at
  2257. + * @last_volt: Pointer to the last known voltage in microvolts for the
  2258. + * VDD supply
  2259. + * @aggr_corner: Pointer to the CPR3 corner which corresponds to the max
  2260. + * corner aggregated from all CPR3 threads managed by the
  2261. + * CPR3 controller
  2262. + *
  2263. + * This function handles the APM and mem-acc regulator reconfiguration if
  2264. + * the new VDD supply voltage will result in crossing their respective voltage
  2265. + * thresholds.
  2266. + *
  2267. + * Return: 0 on success, errno on failure. If the VDD supply voltage is
  2268. + * modified, last_volt is updated to reflect the new voltage setpoint.
  2269. + */
  2270. +static int cpr3_regulator_config_voltage_crossings(struct cpr3_controller *ctrl,
  2271. + int new_volt, int *last_volt,
  2272. + struct cpr3_corner *aggr_corner)
  2273. +{
  2274. + bool apm_crossing = false, mem_acc_crossing = false;
  2275. + bool mem_acc_bhs_used;
  2276. + int apm_volt = ctrl->apm_threshold_volt;
  2277. + int mem_acc_volt = ctrl->mem_acc_threshold_volt;
  2278. + int ref_volt, rc;
  2279. +
  2280. + if (ctrl->apm && apm_volt > 0
  2281. + && ((*last_volt < apm_volt && apm_volt <= new_volt)
  2282. + || (*last_volt >= apm_volt && apm_volt > new_volt)))
  2283. + apm_crossing = true;
  2284. +
  2285. + mem_acc_bhs_used = cpr3_regulator_mem_acc_bhs_used(ctrl);
  2286. +
  2287. + ref_volt = ctrl->use_hw_closed_loop ? aggr_corner->floor_volt :
  2288. + new_volt;
  2289. +
  2290. + if (mem_acc_bhs_used &&
  2291. + (((*last_volt < mem_acc_volt && mem_acc_volt <= ref_volt) ||
  2292. + (*last_volt >= mem_acc_volt && mem_acc_volt > ref_volt))))
  2293. + mem_acc_crossing = true;
  2294. +
  2295. + if (apm_crossing && mem_acc_crossing) {
  2296. + if ((new_volt < *last_volt && apm_volt >= mem_acc_volt) ||
  2297. + (new_volt >= *last_volt && apm_volt < mem_acc_volt)) {
  2298. + rc = cpr3_regulator_switch_apm_mode(ctrl, new_volt,
  2299. + last_volt,
  2300. + aggr_corner);
  2301. + if (rc) {
  2302. + cpr3_err(ctrl, "unable to switch APM mode\n");
  2303. + return rc;
  2304. + }
  2305. +
  2306. + rc = cpr3_regulator_config_bhs_mem_acc(ctrl, new_volt,
  2307. + last_volt, aggr_corner);
  2308. + if (rc) {
  2309. + cpr3_err(ctrl, "unable to configure BHS mem-acc settings\n");
  2310. + return rc;
  2311. + }
  2312. + } else {
  2313. + rc = cpr3_regulator_config_bhs_mem_acc(ctrl, new_volt,
  2314. + last_volt, aggr_corner);
  2315. + if (rc) {
  2316. + cpr3_err(ctrl, "unable to configure BHS mem-acc settings\n");
  2317. + return rc;
  2318. + }
  2319. +
  2320. + rc = cpr3_regulator_switch_apm_mode(ctrl, new_volt,
  2321. + last_volt,
  2322. + aggr_corner);
  2323. + if (rc) {
  2324. + cpr3_err(ctrl, "unable to switch APM mode\n");
  2325. + return rc;
  2326. + }
  2327. + }
  2328. + } else if (apm_crossing) {
  2329. + rc = cpr3_regulator_switch_apm_mode(ctrl, new_volt, last_volt,
  2330. + aggr_corner);
  2331. + if (rc) {
  2332. + cpr3_err(ctrl, "unable to switch APM mode\n");
  2333. + return rc;
  2334. + }
  2335. + } else if (mem_acc_crossing) {
  2336. + rc = cpr3_regulator_config_bhs_mem_acc(ctrl, new_volt,
  2337. + last_volt, aggr_corner);
  2338. + if (rc) {
  2339. + cpr3_err(ctrl, "unable to configure BHS mem-acc settings\n");
  2340. + return rc;
  2341. + }
  2342. + }
  2343. +
  2344. + return 0;
  2345. +}
  2346. +
  2347. +/**
  2348. + * cpr3_regulator_config_mem_acc() - configure the corner of the mem-acc
  2349. + * regulator associated with the CPR3 controller
  2350. + * @ctrl: Pointer to the CPR3 controller
  2351. + * @aggr_corner: Pointer to the CPR3 corner which corresponds to the max
  2352. + * corner aggregated from all CPR3 threads managed by the
  2353. + * CPR3 controller
  2354. + *
  2355. + * Return: 0 on success, errno on failure
  2356. + */
  2357. +static int cpr3_regulator_config_mem_acc(struct cpr3_controller *ctrl,
  2358. + struct cpr3_corner *aggr_corner)
  2359. +{
  2360. + int rc;
  2361. +
  2362. + if (ctrl->mem_acc_regulator && aggr_corner->mem_acc_volt) {
  2363. + rc = regulator_set_voltage(ctrl->mem_acc_regulator,
  2364. + aggr_corner->mem_acc_volt,
  2365. + aggr_corner->mem_acc_volt);
  2366. + if (rc) {
  2367. + cpr3_err(ctrl, "regulator_set_voltage(mem_acc) == %d failed, rc=%d\n",
  2368. + aggr_corner->mem_acc_volt, rc);
  2369. + return rc;
  2370. + }
  2371. + }
  2372. +
  2373. + return 0;
  2374. +}
  2375. +
  2376. +/**
  2377. + * cpr3_regulator_scale_vdd_voltage() - scale the CPR controlled VDD supply
  2378. + * voltage to the new level while satisfying any other hardware
  2379. + * requirements
  2380. + * @ctrl: Pointer to the CPR3 controller
  2381. + * @new_volt: New voltage in microvolts that VDD supply needs to end
  2382. + * up at
  2383. + * @last_volt: Last known voltage in microvolts for the VDD supply
  2384. + * @aggr_corner: Pointer to the CPR3 corner which corresponds to the max
  2385. + * corner aggregated from all CPR3 threads managed by the
  2386. + * CPR3 controller
  2387. + *
  2388. + * This function scales the CPR controlled VDD supply voltage from its
  2389. + * current level to the new voltage that is specified. If the supply is
  2390. + * configured to use the APM and the APM threshold is crossed as a result of
  2391. + * the voltage scaling, then this function also stops at the APM threshold,
  2392. + * switches the APM source, and finally sets the final new voltage.
  2393. + *
  2394. + * Return: 0 on success, errno on failure
  2395. + */
  2396. +static int cpr3_regulator_scale_vdd_voltage(struct cpr3_controller *ctrl,
  2397. + int new_volt, int last_volt,
  2398. + struct cpr3_corner *aggr_corner)
  2399. +{
  2400. + struct regulator *vdd = ctrl->vdd_regulator;
  2401. + int rc;
  2402. +
  2403. + if (new_volt < last_volt) {
  2404. + rc = cpr3_regulator_config_mem_acc(ctrl, aggr_corner);
  2405. + if (rc)
  2406. + return rc;
  2407. + } else {
  2408. + /* Increasing VDD voltage */
  2409. + if (ctrl->system_regulator) {
  2410. + rc = regulator_set_voltage(ctrl->system_regulator,
  2411. + aggr_corner->system_volt, INT_MAX);
  2412. + if (rc) {
  2413. + cpr3_err(ctrl, "regulator_set_voltage(system) == %d failed, rc=%d\n",
  2414. + aggr_corner->system_volt, rc);
  2415. + return rc;
  2416. + }
  2417. + }
  2418. + }
  2419. +
  2420. + rc = cpr3_regulator_config_voltage_crossings(ctrl, new_volt, &last_volt,
  2421. + aggr_corner);
  2422. + if (rc) {
  2423. + cpr3_err(ctrl, "unable to handle voltage threshold crossing configurations, rc=%d\n",
  2424. + rc);
  2425. + return rc;
  2426. + }
  2427. +
  2428. + /*
  2429. + * Subtract a small amount from the min_uV parameter so that the
  2430. + * set voltage request is not dropped by the framework due to being
  2431. + * duplicate. This is needed in order to switch from hardware
  2432. + * closed-loop to open-loop successfully.
  2433. + */
  2434. + rc = regulator_set_voltage(vdd, new_volt - (ctrl->cpr_enabled ? 0 : 1),
  2435. + aggr_corner->ceiling_volt);
  2436. + if (rc) {
  2437. + cpr3_err(ctrl, "regulator_set_voltage(vdd) == %d failed, rc=%d\n",
  2438. + new_volt, rc);
  2439. + return rc;
  2440. + }
  2441. +
  2442. + if (new_volt == last_volt && ctrl->supports_hw_closed_loop
  2443. + && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
  2444. + /*
  2445. + * CPR4 features enforce voltage reprogramming when the last
  2446. + * set voltage and new set voltage are same. This way, we can
  2447. + * ensure that SAW PMIC STATUS register is updated with newly
  2448. + * programmed voltage.
  2449. + */
  2450. + rc = regulator_sync_voltage(vdd);
  2451. + if (rc) {
  2452. + cpr3_err(ctrl, "regulator_sync_voltage(vdd) == %d failed, rc=%d\n",
  2453. + new_volt, rc);
  2454. + return rc;
  2455. + }
  2456. + }
  2457. +
  2458. + if (new_volt >= last_volt) {
  2459. + rc = cpr3_regulator_config_mem_acc(ctrl, aggr_corner);
  2460. + if (rc)
  2461. + return rc;
  2462. + } else {
  2463. + /* Decreasing VDD voltage */
  2464. + if (ctrl->system_regulator) {
  2465. + rc = regulator_set_voltage(ctrl->system_regulator,
  2466. + aggr_corner->system_volt, INT_MAX);
  2467. + if (rc) {
  2468. + cpr3_err(ctrl, "regulator_set_voltage(system) == %d failed, rc=%d\n",
  2469. + aggr_corner->system_volt, rc);
  2470. + return rc;
  2471. + }
  2472. + }
  2473. + }
  2474. +
  2475. + return 0;
  2476. +}
  2477. +
  2478. +/**
  2479. + * cpr3_regulator_get_dynamic_floor_volt() - returns the current dynamic floor
  2480. + * voltage based upon static configurations and the state of all
  2481. + * power domains during the last CPR measurement
  2482. + * @ctrl: Pointer to the CPR3 controller
  2483. + * @reg_last_measurement: Value read from the LAST_MEASUREMENT register
  2484. + *
  2485. + * When using HW closed-loop, the dynamic floor voltage is always returned
  2486. + * regardless of the current state of the power domains.
  2487. + *
  2488. + * Return: dynamic floor voltage in microvolts or 0 if dynamic floor is not
  2489. + * currently required
  2490. + */
  2491. +static int cpr3_regulator_get_dynamic_floor_volt(struct cpr3_controller *ctrl,
  2492. + u32 reg_last_measurement)
  2493. +{
  2494. + int dynamic_floor_volt = 0;
  2495. + struct cpr3_regulator *vreg;
  2496. + bool valid, pd_valid;
  2497. + u32 bypass_bits;
  2498. + int i, j;
  2499. +
  2500. + if (!ctrl->supports_hw_closed_loop)
  2501. + return 0;
  2502. +
  2503. + if (likely(!ctrl->use_hw_closed_loop)) {
  2504. + valid = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_VALID);
  2505. + bypass_bits
  2506. + = (reg_last_measurement & CPR3_LAST_MEASUREMENT_PD_BYPASS_MASK)
  2507. + >> CPR3_LAST_MEASUREMENT_PD_BYPASS_SHIFT;
  2508. + } else {
  2509. + /*
  2510. + * Ensure that the dynamic floor voltage is always used for
  2511. + * HW closed-loop since the conditions below cannot be evaluated
  2512. + * after each CPR measurement.
  2513. + */
  2514. + valid = false;
  2515. + bypass_bits = 0;
  2516. + }
  2517. +
  2518. + for (i = 0; i < ctrl->thread_count; i++) {
  2519. + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
  2520. + vreg = &ctrl->thread[i].vreg[j];
  2521. +
  2522. + if (!vreg->uses_dynamic_floor)
  2523. + continue;
  2524. +
  2525. + pd_valid = !((bypass_bits & vreg->pd_bypass_mask)
  2526. + == vreg->pd_bypass_mask);
  2527. +
  2528. + if (!valid || !pd_valid)
  2529. + dynamic_floor_volt = max(dynamic_floor_volt,
  2530. + vreg->corner[
  2531. + vreg->dynamic_floor_corner].last_volt);
  2532. + }
  2533. + }
  2534. +
  2535. + return dynamic_floor_volt;
  2536. +}
  2537. +
  2538. +/**
  2539. + * cpr3_regulator_max_sdelta_diff() - returns the maximum voltage difference in
  2540. + * microvolts that can result from different operating conditions
  2541. + * for the specified sdelta struct
  2542. + * @sdelta: Pointer to the sdelta structure
  2543. + * @step_volt: Step size in microvolts between available set
  2544. + * points of the VDD supply.
  2545. + *
  2546. + * Return: voltage difference between the highest and lowest adjustments if
  2547. + * sdelta and sdelta->table are valid, else 0.
  2548. + */
  2549. +static int cpr3_regulator_max_sdelta_diff(const struct cpr4_sdelta *sdelta,
  2550. + int step_volt)
  2551. +{
  2552. + int i, j, index, sdelta_min = INT_MAX, sdelta_max = INT_MIN;
  2553. +
  2554. + if (!sdelta || !sdelta->table)
  2555. + return 0;
  2556. +
  2557. + for (i = 0; i < sdelta->max_core_count; i++) {
  2558. + for (j = 0; j < sdelta->temp_band_count; j++) {
  2559. + index = i * sdelta->temp_band_count + j;
  2560. + sdelta_min = min(sdelta_min, sdelta->table[index]);
  2561. + sdelta_max = max(sdelta_max, sdelta->table[index]);
  2562. + }
  2563. + }
  2564. +
  2565. + return (sdelta_max - sdelta_min) * step_volt;
  2566. +}
  2567. +
  2568. +/**
  2569. + * cpr3_regulator_aggregate_sdelta() - check open-loop voltages of current
  2570. + * aggregated corner and current corner of a given regulator
  2571. + * and adjust the sdelta strucuture data of aggregate corner.
  2572. + * @aggr_corner: Pointer to accumulated aggregated corner which
  2573. + * is both an input and an output
  2574. + * @corner: Pointer to the corner to be aggregated with
  2575. + * aggr_corner
  2576. + * @step_volt: Step size in microvolts between available set
  2577. + * points of the VDD supply.
  2578. + *
  2579. + * Return: none
  2580. + */
  2581. +static void cpr3_regulator_aggregate_sdelta(
  2582. + struct cpr3_corner *aggr_corner,
  2583. + const struct cpr3_corner *corner, int step_volt)
  2584. +{
  2585. + struct cpr4_sdelta *aggr_sdelta, *sdelta;
  2586. + int aggr_core_count, core_count, temp_band_count;
  2587. + u32 aggr_index, index;
  2588. + int i, j, sdelta_size, cap_steps, adjust_sdelta;
  2589. +
  2590. + aggr_sdelta = aggr_corner->sdelta;
  2591. + sdelta = corner->sdelta;
  2592. +
  2593. + if (aggr_corner->open_loop_volt < corner->open_loop_volt) {
  2594. + /*
  2595. + * Found the new dominant regulator as its open-loop requirement
  2596. + * is higher than previous dominant regulator. Calculate cap
  2597. + * voltage to limit the SDELTA values to make sure the runtime
  2598. + * (Core-count/temp) adjustments do not violate other
  2599. + * regulators' voltage requirements. Use cpr4_sdelta values of
  2600. + * new dominant regulator.
  2601. + */
  2602. + aggr_sdelta->cap_volt = min(aggr_sdelta->cap_volt,
  2603. + (corner->open_loop_volt -
  2604. + aggr_corner->open_loop_volt));
  2605. +
  2606. + /* Clear old data in the sdelta table */
  2607. + sdelta_size = aggr_sdelta->max_core_count
  2608. + * aggr_sdelta->temp_band_count;
  2609. +
  2610. + if (aggr_sdelta->allow_core_count_adj
  2611. + || aggr_sdelta->allow_temp_adj)
  2612. + memset(aggr_sdelta->table, 0, sdelta_size
  2613. + * sizeof(*aggr_sdelta->table));
  2614. +
  2615. + if (sdelta->allow_temp_adj || sdelta->allow_core_count_adj) {
  2616. + /* Copy new data in sdelta table */
  2617. + sdelta_size = sdelta->max_core_count
  2618. + * sdelta->temp_band_count;
  2619. + if (sdelta->table)
  2620. + memcpy(aggr_sdelta->table, sdelta->table,
  2621. + sdelta_size * sizeof(*sdelta->table));
  2622. + }
  2623. +
  2624. + if (sdelta->allow_boost) {
  2625. + memcpy(aggr_sdelta->boost_table, sdelta->boost_table,
  2626. + sdelta->temp_band_count
  2627. + * sizeof(*sdelta->boost_table));
  2628. + aggr_sdelta->boost_num_cores = sdelta->boost_num_cores;
  2629. + } else if (aggr_sdelta->allow_boost) {
  2630. + for (i = 0; i < aggr_sdelta->temp_band_count; i++) {
  2631. + adjust_sdelta = (corner->open_loop_volt
  2632. + - aggr_corner->open_loop_volt)
  2633. + / step_volt;
  2634. + aggr_sdelta->boost_table[i] += adjust_sdelta;
  2635. + aggr_sdelta->boost_table[i]
  2636. + = min(aggr_sdelta->boost_table[i], 0);
  2637. + }
  2638. + }
  2639. +
  2640. + aggr_corner->open_loop_volt = corner->open_loop_volt;
  2641. + aggr_sdelta->allow_temp_adj = sdelta->allow_temp_adj;
  2642. + aggr_sdelta->allow_core_count_adj
  2643. + = sdelta->allow_core_count_adj;
  2644. + aggr_sdelta->max_core_count = sdelta->max_core_count;
  2645. + aggr_sdelta->temp_band_count = sdelta->temp_band_count;
  2646. + } else if (aggr_corner->open_loop_volt > corner->open_loop_volt) {
  2647. + /*
  2648. + * Adjust the cap voltage if the open-loop requirement of new
  2649. + * regulator is the next highest.
  2650. + */
  2651. + aggr_sdelta->cap_volt = min(aggr_sdelta->cap_volt,
  2652. + (aggr_corner->open_loop_volt
  2653. + - corner->open_loop_volt));
  2654. +
  2655. + if (sdelta->allow_boost) {
  2656. + for (i = 0; i < aggr_sdelta->temp_band_count; i++) {
  2657. + adjust_sdelta = (aggr_corner->open_loop_volt
  2658. + - corner->open_loop_volt)
  2659. + / step_volt;
  2660. + aggr_sdelta->boost_table[i] =
  2661. + sdelta->boost_table[i] + adjust_sdelta;
  2662. + aggr_sdelta->boost_table[i]
  2663. + = min(aggr_sdelta->boost_table[i], 0);
  2664. + }
  2665. + aggr_sdelta->boost_num_cores = sdelta->boost_num_cores;
  2666. + }
  2667. + } else {
  2668. + /*
  2669. + * Found another dominant regulator with same open-loop
  2670. + * requirement. Make cap voltage to '0'. Disable core-count
  2671. + * adjustments as we couldn't support for both regulators.
  2672. + * Keep enable temp based adjustments if enabled for both
  2673. + * regulators and choose mininum margin adjustment values
  2674. + * between them.
  2675. + */
  2676. + aggr_sdelta->cap_volt = 0;
  2677. + aggr_sdelta->allow_core_count_adj = false;
  2678. +
  2679. + if (aggr_sdelta->allow_temp_adj
  2680. + && sdelta->allow_temp_adj) {
  2681. + aggr_core_count = aggr_sdelta->max_core_count - 1;
  2682. + core_count = sdelta->max_core_count - 1;
  2683. + temp_band_count = sdelta->temp_band_count;
  2684. + for (j = 0; j < temp_band_count; j++) {
  2685. + aggr_index = aggr_core_count * temp_band_count
  2686. + + j;
  2687. + index = core_count * temp_band_count + j;
  2688. + aggr_sdelta->table[aggr_index] =
  2689. + min(aggr_sdelta->table[aggr_index],
  2690. + sdelta->table[index]);
  2691. + }
  2692. + } else {
  2693. + aggr_sdelta->allow_temp_adj = false;
  2694. + }
  2695. +
  2696. + if (sdelta->allow_boost) {
  2697. + memcpy(aggr_sdelta->boost_table, sdelta->boost_table,
  2698. + sdelta->temp_band_count
  2699. + * sizeof(*sdelta->boost_table));
  2700. + aggr_sdelta->boost_num_cores = sdelta->boost_num_cores;
  2701. + }
  2702. + }
  2703. +
  2704. + /* Keep non-dominant clients boost enable state */
  2705. + aggr_sdelta->allow_boost |= sdelta->allow_boost;
  2706. + if (aggr_sdelta->allow_boost)
  2707. + aggr_sdelta->allow_core_count_adj = false;
  2708. +
  2709. + if (aggr_sdelta->cap_volt && !(aggr_sdelta->cap_volt == INT_MAX)) {
  2710. + core_count = aggr_sdelta->max_core_count;
  2711. + temp_band_count = aggr_sdelta->temp_band_count;
  2712. + /*
  2713. + * Convert cap voltage from uV to PMIC steps and use to limit
  2714. + * sdelta margin adjustments.
  2715. + */
  2716. + cap_steps = aggr_sdelta->cap_volt / step_volt;
  2717. + for (i = 0; i < core_count; i++)
  2718. + for (j = 0; j < temp_band_count; j++) {
  2719. + index = i * temp_band_count + j;
  2720. + aggr_sdelta->table[index] =
  2721. + min(aggr_sdelta->table[index],
  2722. + cap_steps);
  2723. + }
  2724. + }
  2725. +}
  2726. +
  2727. +/**
  2728. + * cpr3_regulator_aggregate_corners() - aggregate two corners together
  2729. + * @aggr_corner: Pointer to accumulated aggregated corner which
  2730. + * is both an input and an output
  2731. + * @corner: Pointer to the corner to be aggregated with
  2732. + * aggr_corner
  2733. + * @aggr_quot: Flag indicating that target quotients should be
  2734. + * aggregated as well.
  2735. + * @step_volt: Step size in microvolts between available set
  2736. + * points of the VDD supply.
  2737. + *
  2738. + * Return: none
  2739. + */
  2740. +static void cpr3_regulator_aggregate_corners(struct cpr3_corner *aggr_corner,
  2741. + const struct cpr3_corner *corner, bool aggr_quot,
  2742. + int step_volt)
  2743. +{
  2744. + int i;
  2745. +
  2746. + aggr_corner->ceiling_volt
  2747. + = max(aggr_corner->ceiling_volt, corner->ceiling_volt);
  2748. + aggr_corner->floor_volt
  2749. + = max(aggr_corner->floor_volt, corner->floor_volt);
  2750. + aggr_corner->last_volt
  2751. + = max(aggr_corner->last_volt, corner->last_volt);
  2752. + aggr_corner->system_volt
  2753. + = max(aggr_corner->system_volt, corner->system_volt);
  2754. + aggr_corner->mem_acc_volt
  2755. + = max(aggr_corner->mem_acc_volt, corner->mem_acc_volt);
  2756. + aggr_corner->irq_en |= corner->irq_en;
  2757. + aggr_corner->use_open_loop |= corner->use_open_loop;
  2758. +
  2759. + if (aggr_quot) {
  2760. + aggr_corner->ro_mask &= corner->ro_mask;
  2761. +
  2762. + for (i = 0; i < CPR3_RO_COUNT; i++)
  2763. + aggr_corner->target_quot[i]
  2764. + = max(aggr_corner->target_quot[i],
  2765. + corner->target_quot[i]);
  2766. + }
  2767. +
  2768. + if (aggr_corner->sdelta && corner->sdelta
  2769. + && (aggr_corner->sdelta->table
  2770. + || aggr_corner->sdelta->boost_table)) {
  2771. + cpr3_regulator_aggregate_sdelta(aggr_corner, corner, step_volt);
  2772. + } else {
  2773. + aggr_corner->open_loop_volt
  2774. + = max(aggr_corner->open_loop_volt,
  2775. + corner->open_loop_volt);
  2776. + }
  2777. +}
  2778. +
  2779. +/**
  2780. + * cpr3_regulator_update_ctrl_state() - update the state of the CPR controller
  2781. + * to reflect the corners used by all CPR3 regulators as well as
  2782. + * the CPR operating mode
  2783. + * @ctrl: Pointer to the CPR3 controller
  2784. + *
  2785. + * This function aggregates the CPR parameters for all CPR3 regulators
  2786. + * associated with the VDD supply. Upon success, it sets the aggregated last
  2787. + * known good voltage.
  2788. + *
  2789. + * The VDD supply voltage will not be physically configured unless this
  2790. + * condition is met by at least one of the regulators of the controller:
  2791. + * regulator->vreg_enabled == true &&
  2792. + * regulator->current_corner != CPR3_REGULATOR_CORNER_INVALID
  2793. + *
  2794. + * CPR registers for the controller and each thread are updated as long as
  2795. + * ctrl->cpr_enabled == true.
  2796. + *
  2797. + * Note, CPR3 controller lock must be held by the caller.
  2798. + *
  2799. + * Return: 0 on success, errno on failure
  2800. + */
  2801. +static int _cpr3_regulator_update_ctrl_state(struct cpr3_controller *ctrl)
  2802. +{
  2803. + struct cpr3_corner aggr_corner = {};
  2804. + struct cpr3_thread *thread;
  2805. + struct cpr3_regulator *vreg;
  2806. + struct cpr4_sdelta *sdelta;
  2807. + bool valid = false;
  2808. + bool thread_valid;
  2809. + int i, j, rc, new_volt, vdd_volt, dynamic_floor_volt, last_corner_volt;
  2810. + u32 reg_last_measurement = 0, sdelta_size;
  2811. + int *sdelta_table, *boost_table;
  2812. +
  2813. + last_corner_volt = 0;
  2814. + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
  2815. + rc = cpr3_ctrl_clear_cpr4_config(ctrl);
  2816. + if (rc) {
  2817. + cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
  2818. + rc);
  2819. + return rc;
  2820. + }
  2821. + }
  2822. +
  2823. + cpr3_ctrl_loop_disable(ctrl);
  2824. +
  2825. + vdd_volt = regulator_get_voltage(ctrl->vdd_regulator);
  2826. + if (vdd_volt < 0) {
  2827. + cpr3_err(ctrl, "regulator_get_voltage(vdd) failed, rc=%d\n",
  2828. + vdd_volt);
  2829. + return vdd_volt;
  2830. + }
  2831. +
  2832. + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
  2833. + /*
  2834. + * Save aggregated corner open-loop voltage which was programmed
  2835. + * during last corner switch which is used when programming new
  2836. + * aggregated corner open-loop voltage.
  2837. + */
  2838. + last_corner_volt = ctrl->aggr_corner.open_loop_volt;
  2839. + }
  2840. +
  2841. + if (ctrl->cpr_enabled && ctrl->use_hw_closed_loop &&
  2842. + ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3)
  2843. + reg_last_measurement
  2844. + = cpr3_read(ctrl, CPR3_REG_LAST_MEASUREMENT);
  2845. +
  2846. + aggr_corner.sdelta = ctrl->aggr_corner.sdelta;
  2847. + if (aggr_corner.sdelta) {
  2848. + sdelta = aggr_corner.sdelta;
  2849. + sdelta_table = sdelta->table;
  2850. + if (sdelta_table) {
  2851. + sdelta_size = sdelta->max_core_count *
  2852. + sdelta->temp_band_count;
  2853. + memset(sdelta_table, 0, sdelta_size
  2854. + * sizeof(*sdelta_table));
  2855. + }
  2856. +
  2857. + boost_table = sdelta->boost_table;
  2858. + if (boost_table)
  2859. + memset(boost_table, 0, sdelta->temp_band_count
  2860. + * sizeof(*boost_table));
  2861. +
  2862. + memset(sdelta, 0, sizeof(*sdelta));
  2863. + sdelta->table = sdelta_table;
  2864. + sdelta->cap_volt = INT_MAX;
  2865. + sdelta->boost_table = boost_table;
  2866. + }
  2867. +
  2868. + /* Aggregate the requests of all threads */
  2869. + for (i = 0; i < ctrl->thread_count; i++) {
  2870. + thread = &ctrl->thread[i];
  2871. + thread_valid = false;
  2872. +
  2873. + sdelta = thread->aggr_corner.sdelta;
  2874. + if (sdelta) {
  2875. + sdelta_table = sdelta->table;
  2876. + if (sdelta_table) {
  2877. + sdelta_size = sdelta->max_core_count *
  2878. + sdelta->temp_band_count;
  2879. + memset(sdelta_table, 0, sdelta_size
  2880. + * sizeof(*sdelta_table));
  2881. + }
  2882. +
  2883. + boost_table = sdelta->boost_table;
  2884. + if (boost_table)
  2885. + memset(boost_table, 0, sdelta->temp_band_count
  2886. + * sizeof(*boost_table));
  2887. +
  2888. + memset(sdelta, 0, sizeof(*sdelta));
  2889. + sdelta->table = sdelta_table;
  2890. + sdelta->cap_volt = INT_MAX;
  2891. + sdelta->boost_table = boost_table;
  2892. + }
  2893. +
  2894. + memset(&thread->aggr_corner, 0, sizeof(thread->aggr_corner));
  2895. + thread->aggr_corner.sdelta = sdelta;
  2896. + thread->aggr_corner.ro_mask = CPR3_RO_MASK;
  2897. +
  2898. + for (j = 0; j < thread->vreg_count; j++) {
  2899. + vreg = &thread->vreg[j];
  2900. +
  2901. + if (ctrl->cpr_enabled && ctrl->use_hw_closed_loop)
  2902. + cpr3_update_vreg_closed_loop_volt(vreg,
  2903. + vdd_volt, reg_last_measurement);
  2904. +
  2905. + if (!vreg->vreg_enabled
  2906. + || vreg->current_corner
  2907. + == CPR3_REGULATOR_CORNER_INVALID) {
  2908. + /* Cannot participate in aggregation. */
  2909. + vreg->aggregated = false;
  2910. + continue;
  2911. + } else {
  2912. + vreg->aggregated = true;
  2913. + thread_valid = true;
  2914. + }
  2915. +
  2916. + cpr3_regulator_aggregate_corners(&thread->aggr_corner,
  2917. + &vreg->corner[vreg->current_corner],
  2918. + true, ctrl->step_volt);
  2919. + }
  2920. +
  2921. + valid |= thread_valid;
  2922. +
  2923. + if (thread_valid)
  2924. + cpr3_regulator_aggregate_corners(&aggr_corner,
  2925. + &thread->aggr_corner,
  2926. + false, ctrl->step_volt);
  2927. + }
  2928. +
  2929. + if (valid && ctrl->cpr_allowed_hw && ctrl->cpr_allowed_sw) {
  2930. + rc = cpr3_closed_loop_enable(ctrl);
  2931. + if (rc) {
  2932. + cpr3_err(ctrl, "could not enable CPR, rc=%d\n", rc);
  2933. + return rc;
  2934. + }
  2935. + } else {
  2936. + rc = cpr3_closed_loop_disable(ctrl);
  2937. + if (rc) {
  2938. + cpr3_err(ctrl, "could not disable CPR, rc=%d\n", rc);
  2939. + return rc;
  2940. + }
  2941. + }
  2942. +
  2943. + /* No threads are enabled with a valid corner so exit. */
  2944. + if (!valid)
  2945. + return 0;
  2946. +
  2947. + /*
  2948. + * When using CPR hardware closed-loop, the voltage may vary anywhere
  2949. + * between the floor and ceiling voltage without software notification.
  2950. + * Therefore, it is required that the floor to ceiling range for the
  2951. + * aggregated corner not intersect the APM threshold voltage. Adjust
  2952. + * the floor to ceiling range if this requirement is violated.
  2953. + *
  2954. + * The following algorithm is applied in the case that
  2955. + * floor < threshold <= ceiling:
  2956. + * if open_loop >= threshold - adj, then floor = threshold
  2957. + * else ceiling = threshold - step
  2958. + * where adj = an adjustment factor to ensure sufficient voltage margin
  2959. + * and step = VDD output step size
  2960. + *
  2961. + * The open-loop and last known voltages are also bounded by the new
  2962. + * floor or ceiling value as needed.
  2963. + */
  2964. + if (ctrl->use_hw_closed_loop
  2965. + && aggr_corner.ceiling_volt >= ctrl->apm_threshold_volt
  2966. + && aggr_corner.floor_volt < ctrl->apm_threshold_volt) {
  2967. +
  2968. + if (aggr_corner.open_loop_volt
  2969. + >= ctrl->apm_threshold_volt - ctrl->apm_adj_volt)
  2970. + aggr_corner.floor_volt = ctrl->apm_threshold_volt;
  2971. + else
  2972. + aggr_corner.ceiling_volt
  2973. + = ctrl->apm_threshold_volt - ctrl->step_volt;
  2974. +
  2975. + aggr_corner.last_volt
  2976. + = max(aggr_corner.last_volt, aggr_corner.floor_volt);
  2977. + aggr_corner.last_volt
  2978. + = min(aggr_corner.last_volt, aggr_corner.ceiling_volt);
  2979. + aggr_corner.open_loop_volt
  2980. + = max(aggr_corner.open_loop_volt, aggr_corner.floor_volt);
  2981. + aggr_corner.open_loop_volt
  2982. + = min(aggr_corner.open_loop_volt, aggr_corner.ceiling_volt);
  2983. + }
  2984. +
  2985. + if (ctrl->use_hw_closed_loop
  2986. + && aggr_corner.ceiling_volt >= ctrl->mem_acc_threshold_volt
  2987. + && aggr_corner.floor_volt < ctrl->mem_acc_threshold_volt) {
  2988. + aggr_corner.floor_volt = ctrl->mem_acc_threshold_volt;
  2989. + aggr_corner.last_volt = max(aggr_corner.last_volt,
  2990. + aggr_corner.floor_volt);
  2991. + aggr_corner.open_loop_volt = max(aggr_corner.open_loop_volt,
  2992. + aggr_corner.floor_volt);
  2993. + }
  2994. +
  2995. + if (ctrl->use_hw_closed_loop) {
  2996. + dynamic_floor_volt
  2997. + = cpr3_regulator_get_dynamic_floor_volt(ctrl,
  2998. + reg_last_measurement);
  2999. + if (aggr_corner.floor_volt < dynamic_floor_volt) {
  3000. + aggr_corner.floor_volt = dynamic_floor_volt;
  3001. + aggr_corner.last_volt = max(aggr_corner.last_volt,
  3002. + aggr_corner.floor_volt);
  3003. + aggr_corner.open_loop_volt
  3004. + = max(aggr_corner.open_loop_volt,
  3005. + aggr_corner.floor_volt);
  3006. + aggr_corner.ceiling_volt = max(aggr_corner.ceiling_volt,
  3007. + aggr_corner.floor_volt);
  3008. + }
  3009. + }
  3010. +
  3011. + if (ctrl->cpr_enabled && ctrl->last_corner_was_closed_loop) {
  3012. + /*
  3013. + * Always program open-loop voltage for CPR4 controllers which
  3014. + * support hardware closed-loop. Storing the last closed loop
  3015. + * voltage in corner structure can still help with debugging.
  3016. + */
  3017. + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3)
  3018. + new_volt = aggr_corner.last_volt;
  3019. + else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4
  3020. + && ctrl->supports_hw_closed_loop)
  3021. + new_volt = aggr_corner.open_loop_volt;
  3022. + else
  3023. + new_volt = min(aggr_corner.last_volt +
  3024. + cpr3_regulator_max_sdelta_diff(aggr_corner.sdelta,
  3025. + ctrl->step_volt),
  3026. + aggr_corner.ceiling_volt);
  3027. +
  3028. + aggr_corner.last_volt = new_volt;
  3029. + } else {
  3030. + new_volt = aggr_corner.open_loop_volt;
  3031. + aggr_corner.last_volt = aggr_corner.open_loop_volt;
  3032. + }
  3033. +
  3034. + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4
  3035. + && ctrl->supports_hw_closed_loop) {
  3036. + /*
  3037. + * Store last aggregated corner open-loop voltage in vdd_volt
  3038. + * which is used when programming current aggregated corner
  3039. + * required voltage.
  3040. + */
  3041. + vdd_volt = last_corner_volt;
  3042. + }
  3043. +
  3044. + cpr3_debug(ctrl, "setting new voltage=%d uV\n", new_volt);
  3045. + rc = cpr3_regulator_scale_vdd_voltage(ctrl, new_volt,
  3046. + vdd_volt, &aggr_corner);
  3047. + if (rc) {
  3048. + cpr3_err(ctrl, "vdd voltage scaling failed, rc=%d\n", rc);
  3049. + return rc;
  3050. + }
  3051. +
  3052. + /* Only update registers if CPR is enabled. */
  3053. + if (ctrl->cpr_enabled) {
  3054. + if (ctrl->use_hw_closed_loop) {
  3055. + /* Hardware closed-loop */
  3056. +
  3057. + /* Set ceiling and floor limits in hardware */
  3058. + rc = regulator_set_voltage(ctrl->vdd_limit_regulator,
  3059. + aggr_corner.floor_volt,
  3060. + aggr_corner.ceiling_volt);
  3061. + if (rc) {
  3062. + cpr3_err(ctrl, "could not configure HW closed-loop voltage limits, rc=%d\n",
  3063. + rc);
  3064. + return rc;
  3065. + }
  3066. + } else {
  3067. + /* Software closed-loop */
  3068. +
  3069. + /*
  3070. + * Disable UP or DOWN interrupts when at ceiling or
  3071. + * floor respectively.
  3072. + */
  3073. + if (new_volt == aggr_corner.floor_volt)
  3074. + aggr_corner.irq_en &= ~CPR3_IRQ_DOWN;
  3075. + if (new_volt == aggr_corner.ceiling_volt)
  3076. + aggr_corner.irq_en &= ~CPR3_IRQ_UP;
  3077. +
  3078. + cpr3_write(ctrl, CPR3_REG_IRQ_CLEAR,
  3079. + CPR3_IRQ_UP | CPR3_IRQ_DOWN);
  3080. + cpr3_write(ctrl, CPR3_REG_IRQ_EN, aggr_corner.irq_en);
  3081. + }
  3082. +
  3083. + for (i = 0; i < ctrl->thread_count; i++) {
  3084. + cpr3_regulator_set_target_quot(&ctrl->thread[i]);
  3085. +
  3086. + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
  3087. + vreg = &ctrl->thread[i].vreg[j];
  3088. +
  3089. + if (vreg->vreg_enabled)
  3090. + vreg->last_closed_loop_corner
  3091. + = vreg->current_corner;
  3092. + }
  3093. + }
  3094. +
  3095. + if (ctrl->proc_clock_throttle) {
  3096. + if (aggr_corner.ceiling_volt > aggr_corner.floor_volt
  3097. + && (ctrl->use_hw_closed_loop
  3098. + || new_volt < aggr_corner.ceiling_volt))
  3099. + cpr3_write(ctrl, CPR3_REG_PD_THROTTLE,
  3100. + ctrl->proc_clock_throttle);
  3101. + else
  3102. + cpr3_write(ctrl, CPR3_REG_PD_THROTTLE,
  3103. + CPR3_PD_THROTTLE_DISABLE);
  3104. + }
  3105. +
  3106. + /*
  3107. + * Ensure that all CPR register writes complete before
  3108. + * re-enabling CPR loop operation.
  3109. + */
  3110. + wmb();
  3111. + } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4
  3112. + && ctrl->vdd_limit_regulator) {
  3113. + /* Set ceiling and floor limits in hardware */
  3114. + rc = regulator_set_voltage(ctrl->vdd_limit_regulator,
  3115. + aggr_corner.floor_volt,
  3116. + aggr_corner.ceiling_volt);
  3117. + if (rc) {
  3118. + cpr3_err(ctrl, "could not configure HW closed-loop voltage limits, rc=%d\n",
  3119. + rc);
  3120. + return rc;
  3121. + }
  3122. + }
  3123. +
  3124. + ctrl->aggr_corner = aggr_corner;
  3125. +
  3126. + if (ctrl->allow_core_count_adj || ctrl->allow_temp_adj
  3127. + || ctrl->allow_boost) {
  3128. + rc = cpr3_controller_program_sdelta(ctrl);
  3129. + if (rc) {
  3130. + cpr3_err(ctrl, "failed to program sdelta, rc=%d\n", rc);
  3131. + return rc;
  3132. + }
  3133. + }
  3134. +
  3135. + /*
  3136. + * Only enable the CPR controller if it is possible to set more than
  3137. + * one vdd-supply voltage.
  3138. + */
  3139. + if (aggr_corner.ceiling_volt > aggr_corner.floor_volt &&
  3140. + !aggr_corner.use_open_loop)
  3141. + cpr3_ctrl_loop_enable(ctrl);
  3142. +
  3143. + ctrl->last_corner_was_closed_loop = ctrl->cpr_enabled;
  3144. + cpr3_debug(ctrl, "CPR configuration updated\n");
  3145. +
  3146. + return 0;
  3147. +}
  3148. +
  3149. +/**
  3150. + * cpr3_regulator_wait_for_idle() - wait for the CPR controller to no longer be
  3151. + * busy
  3152. + * @ctrl: Pointer to the CPR3 controller
  3153. + * @max_wait_ns: Max wait time in nanoseconds
  3154. + *
  3155. + * Return: 0 on success or -ETIMEDOUT if the controller was still busy after
  3156. + * the maximum delay time
  3157. + */
  3158. +static int cpr3_regulator_wait_for_idle(struct cpr3_controller *ctrl,
  3159. + s64 max_wait_ns)
  3160. +{
  3161. + ktime_t start, end;
  3162. + s64 time_ns;
  3163. + u32 reg;
  3164. +
  3165. + /*
  3166. + * Ensure that all previous CPR register writes have completed before
  3167. + * checking the status register.
  3168. + */
  3169. + mb();
  3170. +
  3171. + start = ktime_get();
  3172. + do {
  3173. + end = ktime_get();
  3174. + time_ns = ktime_to_ns(ktime_sub(end, start));
  3175. + if (time_ns > max_wait_ns) {
  3176. + cpr3_err(ctrl, "CPR controller still busy after %lld us\n",
  3177. + div_s64(time_ns, 1000));
  3178. + return -ETIMEDOUT;
  3179. + }
  3180. + usleep_range(50, 100);
  3181. + reg = cpr3_read(ctrl, CPR3_REG_CPR_STATUS);
  3182. + } while (reg & CPR3_CPR_STATUS_BUSY_MASK);
  3183. +
  3184. + return 0;
  3185. +}
  3186. +
  3187. +/**
  3188. + * cmp_int() - int comparison function to be passed into the sort() function
  3189. + * which leads to ascending sorting
  3190. + * @a: First int value
  3191. + * @b: Second int value
  3192. + *
  3193. + * Return: >0 if a > b, 0 if a == b, <0 if a < b
  3194. + */
  3195. +static int cmp_int(const void *a, const void *b)
  3196. +{
  3197. + return *(int *)a - *(int *)b;
  3198. +}
  3199. +
  3200. +/**
  3201. + * cpr3_regulator_measure_aging() - measure the quotient difference for the
  3202. + * specified CPR aging sensor
  3203. + * @ctrl: Pointer to the CPR3 controller
  3204. + * @aging_sensor: Aging sensor to measure
  3205. + *
  3206. + * Note that vdd-supply must be configured to the aging reference voltage before
  3207. + * calling this function.
  3208. + *
  3209. + * Return: 0 on success, errno on failure
  3210. + */
  3211. +static int cpr3_regulator_measure_aging(struct cpr3_controller *ctrl,
  3212. + struct cpr3_aging_sensor_info *aging_sensor)
  3213. +{
  3214. + u32 mask, reg, result, quot_min, quot_max, sel_min, sel_max;
  3215. + u32 quot_min_scaled, quot_max_scaled;
  3216. + u32 gcnt, gcnt_ref, gcnt0_restore, gcnt1_restore, irq_restore;
  3217. + u32 ro_mask_restore, cont_dly_restore, up_down_dly_restore = 0;
  3218. + int quot_delta, quot_delta_scaled, quot_delta_scaled_sum;
  3219. + int *quot_delta_results;
  3220. + int rc, rc2, i, aging_measurement_count, filtered_count;
  3221. + bool is_aging_measurement;
  3222. +
  3223. + quot_delta_results = kcalloc(CPR3_AGING_MEASUREMENT_ITERATIONS,
  3224. + sizeof(*quot_delta_results), GFP_KERNEL);
  3225. + if (!quot_delta_results)
  3226. + return -ENOMEM;
  3227. +
  3228. + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
  3229. + rc = cpr3_ctrl_clear_cpr4_config(ctrl);
  3230. + if (rc) {
  3231. + cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
  3232. + rc);
  3233. + kfree(quot_delta_results);
  3234. + return rc;
  3235. + }
  3236. + }
  3237. +
  3238. + cpr3_ctrl_loop_disable(ctrl);
  3239. +
  3240. + /* Enable up, down, and mid CPR interrupts */
  3241. + irq_restore = cpr3_read(ctrl, CPR3_REG_IRQ_EN);
  3242. + cpr3_write(ctrl, CPR3_REG_IRQ_EN,
  3243. + CPR3_IRQ_UP | CPR3_IRQ_DOWN | CPR3_IRQ_MID);
  3244. +
  3245. + /* Ensure that the aging sensor is assigned to CPR thread 0 */
  3246. + cpr3_write(ctrl, CPR3_REG_SENSOR_OWNER(aging_sensor->sensor_id), 0);
  3247. +
  3248. + /* Switch from HW to SW closed-loop if necessary */
  3249. + if (ctrl->supports_hw_closed_loop) {
  3250. + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
  3251. + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
  3252. + CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK,
  3253. + CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE);
  3254. + } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
  3255. + cpr3_write(ctrl, CPR3_REG_HW_CLOSED_LOOP,
  3256. + CPR3_HW_CLOSED_LOOP_DISABLE);
  3257. + }
  3258. + }
  3259. +
  3260. + /* Configure the GCNT for RO0 and RO1 that are used for aging */
  3261. + gcnt0_restore = cpr3_read(ctrl, CPR3_REG_GCNT(0));
  3262. + gcnt1_restore = cpr3_read(ctrl, CPR3_REG_GCNT(1));
  3263. + gcnt_ref = cpr3_regulator_get_gcnt(ctrl);
  3264. + gcnt = gcnt_ref * 3 / 2;
  3265. + cpr3_write(ctrl, CPR3_REG_GCNT(0), gcnt);
  3266. + cpr3_write(ctrl, CPR3_REG_GCNT(1), gcnt);
  3267. +
  3268. + /* Unmask all RO's */
  3269. + ro_mask_restore = cpr3_read(ctrl, CPR3_REG_RO_MASK(0));
  3270. + cpr3_write(ctrl, CPR3_REG_RO_MASK(0), 0);
  3271. +
  3272. + /*
  3273. + * Mask all sensors except for the one to measure and bypass all
  3274. + * sensors in collapsible domains.
  3275. + */
  3276. + for (i = 0; i <= ctrl->sensor_count / 32; i++) {
  3277. + mask = GENMASK(min(31, ctrl->sensor_count - i * 32), 0);
  3278. + if (aging_sensor->sensor_id / 32 >= i
  3279. + && aging_sensor->sensor_id / 32 < (i + 1))
  3280. + mask &= ~BIT(aging_sensor->sensor_id % 32);
  3281. + cpr3_write(ctrl, CPR3_REG_SENSOR_MASK_WRITE_BANK(i), mask);
  3282. + cpr3_write(ctrl, CPR3_REG_SENSOR_BYPASS_WRITE_BANK(i),
  3283. + aging_sensor->bypass_mask[i]);
  3284. + }
  3285. +
  3286. + /* Set CPR loop delays to 0 us */
  3287. + if (ctrl->supports_hw_closed_loop
  3288. + && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
  3289. + cont_dly_restore = cpr3_read(ctrl, CPR3_REG_CPR_TIMER_MID_CONT);
  3290. + up_down_dly_restore = cpr3_read(ctrl,
  3291. + CPR3_REG_CPR_TIMER_UP_DN_CONT);
  3292. + cpr3_write(ctrl, CPR3_REG_CPR_TIMER_MID_CONT, 0);
  3293. + cpr3_write(ctrl, CPR3_REG_CPR_TIMER_UP_DN_CONT, 0);
  3294. + } else {
  3295. + cont_dly_restore = cpr3_read(ctrl,
  3296. + CPR3_REG_CPR_TIMER_AUTO_CONT);
  3297. + cpr3_write(ctrl, CPR3_REG_CPR_TIMER_AUTO_CONT, 0);
  3298. + }
  3299. +
  3300. + /* Set count mode to all-at-once min with no repeat */
  3301. + cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL,
  3302. + CPR3_CPR_CTL_COUNT_MODE_MASK | CPR3_CPR_CTL_COUNT_REPEAT_MASK,
  3303. + CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_MIN
  3304. + << CPR3_CPR_CTL_COUNT_MODE_SHIFT);
  3305. +
  3306. + cpr3_ctrl_loop_enable(ctrl);
  3307. +
  3308. + rc = cpr3_regulator_wait_for_idle(ctrl,
  3309. + CPR3_AGING_MEASUREMENT_TIMEOUT_NS);
  3310. + if (rc)
  3311. + goto cleanup;
  3312. +
  3313. + /* Set count mode to all-at-once aging */
  3314. + cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL, CPR3_CPR_CTL_COUNT_MODE_MASK,
  3315. + CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_AGE
  3316. + << CPR3_CPR_CTL_COUNT_MODE_SHIFT);
  3317. +
  3318. + aging_measurement_count = 0;
  3319. + for (i = 0; i < CPR3_AGING_MEASUREMENT_ITERATIONS; i++) {
  3320. + /* Send CONT_NACK */
  3321. + cpr3_write(ctrl, CPR3_REG_CONT_CMD, CPR3_CONT_CMD_NACK);
  3322. +
  3323. + rc = cpr3_regulator_wait_for_idle(ctrl,
  3324. + CPR3_AGING_MEASUREMENT_TIMEOUT_NS);
  3325. + if (rc)
  3326. + goto cleanup;
  3327. +
  3328. + /* Check for PAGE_IS_AGE flag in status register */
  3329. + reg = cpr3_read(ctrl, CPR3_REG_CPR_STATUS);
  3330. + is_aging_measurement
  3331. + = reg & CPR3_CPR_STATUS_AGING_MEASUREMENT_MASK;
  3332. +
  3333. + /* Read CPR measurement results */
  3334. + result = cpr3_read(ctrl, CPR3_REG_RESULT1(0));
  3335. + quot_min = (result & CPR3_RESULT1_QUOT_MIN_MASK)
  3336. + >> CPR3_RESULT1_QUOT_MIN_SHIFT;
  3337. + quot_max = (result & CPR3_RESULT1_QUOT_MAX_MASK)
  3338. + >> CPR3_RESULT1_QUOT_MAX_SHIFT;
  3339. + sel_min = (result & CPR3_RESULT1_RO_MIN_MASK)
  3340. + >> CPR3_RESULT1_RO_MIN_SHIFT;
  3341. + sel_max = (result & CPR3_RESULT1_RO_MAX_MASK)
  3342. + >> CPR3_RESULT1_RO_MAX_SHIFT;
  3343. +
  3344. + /*
  3345. + * Scale the quotients so that they are equivalent to the fused
  3346. + * values. This accounts for the difference in measurement
  3347. + * interval times.
  3348. + */
  3349. + quot_min_scaled = quot_min * (gcnt_ref + 1) / (gcnt + 1);
  3350. + quot_max_scaled = quot_max * (gcnt_ref + 1) / (gcnt + 1);
  3351. +
  3352. + if (sel_max == 1) {
  3353. + quot_delta = quot_max - quot_min;
  3354. + quot_delta_scaled = quot_max_scaled - quot_min_scaled;
  3355. + } else {
  3356. + quot_delta = quot_min - quot_max;
  3357. + quot_delta_scaled = quot_min_scaled - quot_max_scaled;
  3358. + }
  3359. +
  3360. + if (is_aging_measurement)
  3361. + quot_delta_results[aging_measurement_count++]
  3362. + = quot_delta_scaled;
  3363. +
  3364. + cpr3_debug(ctrl, "aging results: page_is_age=%u, sel_min=%u, sel_max=%u, quot_min=%u, quot_max=%u, quot_delta=%d, quot_min_scaled=%u, quot_max_scaled=%u, quot_delta_scaled=%d\n",
  3365. + is_aging_measurement, sel_min, sel_max, quot_min,
  3366. + quot_max, quot_delta, quot_min_scaled, quot_max_scaled,
  3367. + quot_delta_scaled);
  3368. + }
  3369. +
  3370. + filtered_count
  3371. + = aging_measurement_count - CPR3_AGING_MEASUREMENT_FILTER * 2;
  3372. + if (filtered_count > 0) {
  3373. + sort(quot_delta_results, aging_measurement_count,
  3374. + sizeof(*quot_delta_results), cmp_int, NULL);
  3375. +
  3376. + quot_delta_scaled_sum = 0;
  3377. + for (i = 0; i < filtered_count; i++)
  3378. + quot_delta_scaled_sum
  3379. + += quot_delta_results[i
  3380. + + CPR3_AGING_MEASUREMENT_FILTER];
  3381. +
  3382. + aging_sensor->measured_quot_diff
  3383. + = quot_delta_scaled_sum / filtered_count;
  3384. + cpr3_info(ctrl, "average quotient delta=%d (count=%d)\n",
  3385. + aging_sensor->measured_quot_diff,
  3386. + filtered_count);
  3387. + } else {
  3388. + cpr3_err(ctrl, "%d aging measurements completed after %d iterations\n",
  3389. + aging_measurement_count,
  3390. + CPR3_AGING_MEASUREMENT_ITERATIONS);
  3391. + rc = -EBUSY;
  3392. + }
  3393. +
  3394. +cleanup:
  3395. + kfree(quot_delta_results);
  3396. +
  3397. + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
  3398. + rc2 = cpr3_ctrl_clear_cpr4_config(ctrl);
  3399. + if (rc2) {
  3400. + cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
  3401. + rc2);
  3402. + rc = rc2;
  3403. + }
  3404. + }
  3405. +
  3406. + cpr3_ctrl_loop_disable(ctrl);
  3407. +
  3408. + cpr3_write(ctrl, CPR3_REG_IRQ_EN, irq_restore);
  3409. +
  3410. + cpr3_write(ctrl, CPR3_REG_RO_MASK(0), ro_mask_restore);
  3411. +
  3412. + cpr3_write(ctrl, CPR3_REG_GCNT(0), gcnt0_restore);
  3413. + cpr3_write(ctrl, CPR3_REG_GCNT(1), gcnt1_restore);
  3414. +
  3415. + if (ctrl->supports_hw_closed_loop
  3416. + && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
  3417. + cpr3_write(ctrl, CPR3_REG_CPR_TIMER_MID_CONT, cont_dly_restore);
  3418. + cpr3_write(ctrl, CPR3_REG_CPR_TIMER_UP_DN_CONT,
  3419. + up_down_dly_restore);
  3420. + } else {
  3421. + cpr3_write(ctrl, CPR3_REG_CPR_TIMER_AUTO_CONT,
  3422. + cont_dly_restore);
  3423. + }
  3424. +
  3425. + for (i = 0; i <= ctrl->sensor_count / 32; i++) {
  3426. + cpr3_write(ctrl, CPR3_REG_SENSOR_MASK_WRITE_BANK(i), 0);
  3427. + cpr3_write(ctrl, CPR3_REG_SENSOR_BYPASS_WRITE_BANK(i), 0);
  3428. + }
  3429. +
  3430. + cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL,
  3431. + CPR3_CPR_CTL_COUNT_MODE_MASK | CPR3_CPR_CTL_COUNT_REPEAT_MASK,
  3432. + (ctrl->count_mode << CPR3_CPR_CTL_COUNT_MODE_SHIFT)
  3433. + | (ctrl->count_repeat << CPR3_CPR_CTL_COUNT_REPEAT_SHIFT));
  3434. +
  3435. + cpr3_write(ctrl, CPR3_REG_SENSOR_OWNER(aging_sensor->sensor_id),
  3436. + ctrl->sensor_owner[aging_sensor->sensor_id]);
  3437. +
  3438. + cpr3_write(ctrl, CPR3_REG_IRQ_CLEAR,
  3439. + CPR3_IRQ_UP | CPR3_IRQ_DOWN | CPR3_IRQ_MID);
  3440. +
  3441. + if (ctrl->supports_hw_closed_loop) {
  3442. + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
  3443. + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
  3444. + CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK,
  3445. + ctrl->use_hw_closed_loop
  3446. + ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE
  3447. + : CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE);
  3448. + } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
  3449. + cpr3_write(ctrl, CPR3_REG_HW_CLOSED_LOOP,
  3450. + ctrl->use_hw_closed_loop
  3451. + ? CPR3_HW_CLOSED_LOOP_ENABLE
  3452. + : CPR3_HW_CLOSED_LOOP_DISABLE);
  3453. + }
  3454. + }
  3455. +
  3456. + return rc;
  3457. +}
  3458. +
  3459. +/**
  3460. + * cpr3_regulator_readjust_volt_and_quot() - readjust the target quotients as
  3461. + * well as the floor, ceiling, and open-loop voltages for the
  3462. + * regulator by removing the old adjustment and adding the new one
  3463. + * @vreg: Pointer to the CPR3 regulator
  3464. + * @old_adjust_volt: Old aging adjustment voltage in microvolts
  3465. + * @new_adjust_volt: New aging adjustment voltage in microvolts
  3466. + *
  3467. + * Also reset the cached closed loop voltage (last_volt) to equal the open-loop
  3468. + * voltage for each corner.
  3469. + *
  3470. + * Return: None
  3471. + */
  3472. +static void cpr3_regulator_readjust_volt_and_quot(struct cpr3_regulator *vreg,
  3473. + int old_adjust_volt, int new_adjust_volt)
  3474. +{
  3475. + unsigned long long temp;
  3476. + int i, j, old_volt, new_volt, rounded_volt;
  3477. +
  3478. + if (!vreg->aging_allowed)
  3479. + return;
  3480. +
  3481. + for (i = 0; i < vreg->corner_count; i++) {
  3482. + temp = (unsigned long long)old_adjust_volt
  3483. + * (unsigned long long)vreg->corner[i].aging_derate;
  3484. + do_div(temp, 1000);
  3485. + old_volt = temp;
  3486. +
  3487. + temp = (unsigned long long)new_adjust_volt
  3488. + * (unsigned long long)vreg->corner[i].aging_derate;
  3489. + do_div(temp, 1000);
  3490. + new_volt = temp;
  3491. +
  3492. + old_volt = min(vreg->aging_max_adjust_volt, old_volt);
  3493. + new_volt = min(vreg->aging_max_adjust_volt, new_volt);
  3494. +
  3495. + for (j = 0; j < CPR3_RO_COUNT; j++) {
  3496. + if (vreg->corner[i].target_quot[j] != 0) {
  3497. + vreg->corner[i].target_quot[j]
  3498. + += cpr3_quot_adjustment(
  3499. + vreg->corner[i].ro_scale[j],
  3500. + new_volt)
  3501. + - cpr3_quot_adjustment(
  3502. + vreg->corner[i].ro_scale[j],
  3503. + old_volt);
  3504. + }
  3505. + }
  3506. +
  3507. + rounded_volt = CPR3_ROUND(new_volt,
  3508. + vreg->thread->ctrl->step_volt);
  3509. +
  3510. + if (!vreg->aging_allow_open_loop_adj)
  3511. + rounded_volt = 0;
  3512. +
  3513. + vreg->corner[i].ceiling_volt
  3514. + = vreg->corner[i].unaged_ceiling_volt + rounded_volt;
  3515. + vreg->corner[i].ceiling_volt = min(vreg->corner[i].ceiling_volt,
  3516. + vreg->corner[i].abs_ceiling_volt);
  3517. + vreg->corner[i].floor_volt
  3518. + = vreg->corner[i].unaged_floor_volt + rounded_volt;
  3519. + vreg->corner[i].floor_volt = min(vreg->corner[i].floor_volt,
  3520. + vreg->corner[i].ceiling_volt);
  3521. + vreg->corner[i].open_loop_volt
  3522. + = vreg->corner[i].unaged_open_loop_volt + rounded_volt;
  3523. + vreg->corner[i].open_loop_volt
  3524. + = min(vreg->corner[i].open_loop_volt,
  3525. + vreg->corner[i].ceiling_volt);
  3526. +
  3527. + vreg->corner[i].last_volt = vreg->corner[i].open_loop_volt;
  3528. +
  3529. + cpr3_debug(vreg, "corner %d: applying %d uV closed-loop and %d uV open-loop voltage margin adjustment\n",
  3530. + i, new_volt, rounded_volt);
  3531. + }
  3532. +}
  3533. +
  3534. +/**
  3535. + * cpr3_regulator_set_aging_ref_adjustment() - adjust target quotients for the
  3536. + * regulators managed by this CPR controller to account for aging
  3537. + * @ctrl: Pointer to the CPR3 controller
  3538. + * @ref_adjust_volt: New aging reference adjustment voltage in microvolts to
  3539. + * apply to all regulators managed by this CPR controller
  3540. + *
  3541. + * The existing aging adjustment as defined by ctrl->aging_ref_adjust_volt is
  3542. + * first removed and then the adjustment is applied. Lastly, the value of
  3543. + * ctrl->aging_ref_adjust_volt is updated to ref_adjust_volt.
  3544. + */
  3545. +static void cpr3_regulator_set_aging_ref_adjustment(
  3546. + struct cpr3_controller *ctrl, int ref_adjust_volt)
  3547. +{
  3548. + struct cpr3_regulator *vreg;
  3549. + int i, j;
  3550. +
  3551. + for (i = 0; i < ctrl->thread_count; i++) {
  3552. + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
  3553. + vreg = &ctrl->thread[i].vreg[j];
  3554. + cpr3_regulator_readjust_volt_and_quot(vreg,
  3555. + ctrl->aging_ref_adjust_volt, ref_adjust_volt);
  3556. + }
  3557. + }
  3558. +
  3559. + ctrl->aging_ref_adjust_volt = ref_adjust_volt;
  3560. +}
  3561. +
  3562. +/**
  3563. + * cpr3_regulator_aging_adjust() - adjust the target quotients for regulators
  3564. + * based on the output of CPR aging sensors
  3565. + * @ctrl: Pointer to the CPR3 controller
  3566. + *
  3567. + * Return: 0 on success, errno on failure
  3568. + */
  3569. +static int cpr3_regulator_aging_adjust(struct cpr3_controller *ctrl)
  3570. +{
  3571. + struct cpr3_regulator *vreg;
  3572. + struct cpr3_corner restore_aging_corner;
  3573. + struct cpr3_corner *corner;
  3574. + int *restore_current_corner;
  3575. + bool *restore_vreg_enabled;
  3576. + int i, j, id, rc, rc2, vreg_count, aging_volt, max_aging_volt = 0;
  3577. + u32 reg;
  3578. +
  3579. + if (!ctrl->aging_required || !ctrl->cpr_enabled
  3580. + || ctrl->aggr_corner.ceiling_volt == 0
  3581. + || ctrl->aggr_corner.ceiling_volt > ctrl->aging_ref_volt)
  3582. + return 0;
  3583. +
  3584. + for (i = 0, vreg_count = 0; i < ctrl->thread_count; i++) {
  3585. + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
  3586. + vreg = &ctrl->thread[i].vreg[j];
  3587. + vreg_count++;
  3588. +
  3589. + if (vreg->aging_allowed && vreg->vreg_enabled
  3590. + && vreg->current_corner > vreg->aging_corner)
  3591. + return 0;
  3592. + }
  3593. + }
  3594. +
  3595. + /* Verify that none of the aging sensors are currently masked. */
  3596. + for (i = 0; i < ctrl->aging_sensor_count; i++) {
  3597. + id = ctrl->aging_sensor[i].sensor_id;
  3598. + reg = cpr3_read(ctrl, CPR3_REG_SENSOR_MASK_READ(id));
  3599. + if (reg & BIT(id % 32))
  3600. + return 0;
  3601. + }
  3602. +
  3603. + /*
  3604. + * Verify that the aging possible register (if specified) has an
  3605. + * acceptable value.
  3606. + */
  3607. + if (ctrl->aging_possible_reg) {
  3608. + reg = readl_relaxed(ctrl->aging_possible_reg);
  3609. + reg &= ctrl->aging_possible_mask;
  3610. + if (reg != ctrl->aging_possible_val)
  3611. + return 0;
  3612. + }
  3613. +
  3614. + restore_current_corner = kcalloc(vreg_count,
  3615. + sizeof(*restore_current_corner), GFP_KERNEL);
  3616. + restore_vreg_enabled = kcalloc(vreg_count,
  3617. + sizeof(*restore_vreg_enabled), GFP_KERNEL);
  3618. + if (!restore_current_corner || !restore_vreg_enabled) {
  3619. + kfree(restore_current_corner);
  3620. + kfree(restore_vreg_enabled);
  3621. + return -ENOMEM;
  3622. + }
  3623. +
  3624. + /* Force all regulators to the aging corner */
  3625. + for (i = 0, vreg_count = 0; i < ctrl->thread_count; i++) {
  3626. + for (j = 0; j < ctrl->thread[i].vreg_count; j++, vreg_count++) {
  3627. + vreg = &ctrl->thread[i].vreg[j];
  3628. +
  3629. + restore_current_corner[vreg_count]
  3630. + = vreg->current_corner;
  3631. + restore_vreg_enabled[vreg_count]
  3632. + = vreg->vreg_enabled;
  3633. +
  3634. + vreg->current_corner = vreg->aging_corner;
  3635. + vreg->vreg_enabled = true;
  3636. + }
  3637. + }
  3638. +
  3639. + /* Force one of the regulators to require the aging reference voltage */
  3640. + vreg = &ctrl->thread[0].vreg[0];
  3641. + corner = &vreg->corner[vreg->current_corner];
  3642. + restore_aging_corner = *corner;
  3643. + corner->ceiling_volt = ctrl->aging_ref_volt;
  3644. + corner->floor_volt = ctrl->aging_ref_volt;
  3645. + corner->open_loop_volt = ctrl->aging_ref_volt;
  3646. + corner->last_volt = ctrl->aging_ref_volt;
  3647. +
  3648. + /* Skip last_volt caching */
  3649. + ctrl->last_corner_was_closed_loop = false;
  3650. +
  3651. + /* Set the vdd supply voltage to the aging reference voltage */
  3652. + rc = _cpr3_regulator_update_ctrl_state(ctrl);
  3653. + if (rc) {
  3654. + cpr3_err(ctrl, "unable to force vdd-supply to the aging reference voltage=%d uV, rc=%d\n",
  3655. + ctrl->aging_ref_volt, rc);
  3656. + goto cleanup;
  3657. + }
  3658. +
  3659. + if (ctrl->aging_vdd_mode) {
  3660. + rc = regulator_set_mode(ctrl->vdd_regulator,
  3661. + ctrl->aging_vdd_mode);
  3662. + if (rc) {
  3663. + cpr3_err(ctrl, "unable to configure vdd-supply for mode=%u, rc=%d\n",
  3664. + ctrl->aging_vdd_mode, rc);
  3665. + goto cleanup;
  3666. + }
  3667. + }
  3668. +
  3669. + /* Perform aging measurement on all aging sensors */
  3670. + for (i = 0; i < ctrl->aging_sensor_count; i++) {
  3671. + for (j = 0; j < CPR3_AGING_RETRY_COUNT; j++) {
  3672. + rc = cpr3_regulator_measure_aging(ctrl,
  3673. + &ctrl->aging_sensor[i]);
  3674. + if (!rc)
  3675. + break;
  3676. + }
  3677. +
  3678. + if (!rc) {
  3679. + aging_volt =
  3680. + cpr3_voltage_adjustment(
  3681. + ctrl->aging_sensor[i].ro_scale,
  3682. + ctrl->aging_sensor[i].measured_quot_diff
  3683. + - ctrl->aging_sensor[i].init_quot_diff);
  3684. + max_aging_volt = max(max_aging_volt, aging_volt);
  3685. + } else {
  3686. + cpr3_err(ctrl, "CPR aging measurement failed after %d tries, rc=%d\n",
  3687. + j, rc);
  3688. + ctrl->aging_failed = true;
  3689. + ctrl->aging_required = false;
  3690. + goto cleanup;
  3691. + }
  3692. + }
  3693. +
  3694. +cleanup:
  3695. + vreg = &ctrl->thread[0].vreg[0];
  3696. + vreg->corner[vreg->current_corner] = restore_aging_corner;
  3697. +
  3698. + for (i = 0, vreg_count = 0; i < ctrl->thread_count; i++) {
  3699. + for (j = 0; j < ctrl->thread[i].vreg_count; j++, vreg_count++) {
  3700. + vreg = &ctrl->thread[i].vreg[j];
  3701. + vreg->current_corner
  3702. + = restore_current_corner[vreg_count];
  3703. + vreg->vreg_enabled = restore_vreg_enabled[vreg_count];
  3704. + }
  3705. + }
  3706. +
  3707. + kfree(restore_current_corner);
  3708. + kfree(restore_vreg_enabled);
  3709. +
  3710. + /* Adjust the CPR target quotients according to the aging measurement */
  3711. + if (!rc) {
  3712. + cpr3_regulator_set_aging_ref_adjustment(ctrl, max_aging_volt);
  3713. +
  3714. + cpr3_info(ctrl, "aging measurement successful; aging reference adjustment voltage=%d uV\n",
  3715. + ctrl->aging_ref_adjust_volt);
  3716. + ctrl->aging_succeeded = true;
  3717. + ctrl->aging_required = false;
  3718. + }
  3719. +
  3720. + if (ctrl->aging_complete_vdd_mode) {
  3721. + rc = regulator_set_mode(ctrl->vdd_regulator,
  3722. + ctrl->aging_complete_vdd_mode);
  3723. + if (rc)
  3724. + cpr3_err(ctrl, "unable to configure vdd-supply for mode=%u, rc=%d\n",
  3725. + ctrl->aging_complete_vdd_mode, rc);
  3726. + }
  3727. +
  3728. + /* Skip last_volt caching */
  3729. + ctrl->last_corner_was_closed_loop = false;
  3730. +
  3731. + /*
  3732. + * Restore vdd-supply to the voltage before the aging measurement and
  3733. + * restore the CPR3 controller hardware state.
  3734. + */
  3735. + rc2 = _cpr3_regulator_update_ctrl_state(ctrl);
  3736. +
  3737. + /* Stop last_volt caching on for the next request */
  3738. + ctrl->last_corner_was_closed_loop = false;
  3739. +
  3740. + return rc ? rc : rc2;
  3741. +}
  3742. +
  3743. +/**
  3744. + * cpr3_regulator_update_ctrl_state() - update the state of the CPR controller
  3745. + * to reflect the corners used by all CPR3 regulators as well as
  3746. + * the CPR operating mode and perform aging adjustments if needed
  3747. + * @ctrl: Pointer to the CPR3 controller
  3748. + *
  3749. + * Note, CPR3 controller lock must be held by the caller.
  3750. + *
  3751. + * Return: 0 on success, errno on failure
  3752. + */
  3753. +static int cpr3_regulator_update_ctrl_state(struct cpr3_controller *ctrl)
  3754. +{
  3755. + int rc;
  3756. +
  3757. + rc = _cpr3_regulator_update_ctrl_state(ctrl);
  3758. + if (rc)
  3759. + return rc;
  3760. +
  3761. + return cpr3_regulator_aging_adjust(ctrl);
  3762. +}
  3763. +
  3764. +/**
  3765. + * cpr3_regulator_set_voltage() - set the voltage corner for the CPR3 regulator
  3766. + * associated with the regulator device
  3767. + * @rdev: Regulator device pointer for the cpr3-regulator
  3768. + * @corner: New voltage corner to set (offset by CPR3_CORNER_OFFSET)
  3769. + * @corner_max: Maximum voltage corner allowed (offset by
  3770. + * CPR3_CORNER_OFFSET)
  3771. + * @selector: Pointer which is filled with the selector value for the
  3772. + * corner
  3773. + *
  3774. + * This function is passed as a callback function into the regulator ops that
  3775. + * are registered for each cpr3-regulator device. The VDD voltage will not be
  3776. + * physically configured until both this function and cpr3_regulator_enable()
  3777. + * are called.
  3778. + *
  3779. + * Return: 0 on success, errno on failure
  3780. + */
  3781. +static int cpr3_regulator_set_voltage(struct regulator_dev *rdev,
  3782. + int corner, int corner_max, unsigned *selector)
  3783. +{
  3784. + struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
  3785. + struct cpr3_controller *ctrl = vreg->thread->ctrl;
  3786. + int rc = 0;
  3787. + int last_corner;
  3788. +
  3789. + corner -= CPR3_CORNER_OFFSET;
  3790. + corner_max -= CPR3_CORNER_OFFSET;
  3791. + *selector = corner;
  3792. +
  3793. + mutex_lock(&ctrl->lock);
  3794. +
  3795. + if (!vreg->vreg_enabled) {
  3796. + vreg->current_corner = corner;
  3797. + cpr3_debug(vreg, "stored corner=%d\n", corner);
  3798. + goto done;
  3799. + } else if (vreg->current_corner == corner) {
  3800. + goto done;
  3801. + }
  3802. +
  3803. + last_corner = vreg->current_corner;
  3804. + vreg->current_corner = corner;
  3805. +
  3806. + if (vreg->cpr4_regulator_data != NULL)
  3807. + if (vreg->cpr4_regulator_data->mem_acc_funcs != NULL)
  3808. + vreg->cpr4_regulator_data->mem_acc_funcs->set_mem_acc(rdev);
  3809. +
  3810. + rc = cpr3_regulator_update_ctrl_state(ctrl);
  3811. + if (rc) {
  3812. + cpr3_err(vreg, "could not update CPR state, rc=%d\n", rc);
  3813. + vreg->current_corner = last_corner;
  3814. + }
  3815. +
  3816. + if (vreg->cpr4_regulator_data != NULL)
  3817. + if (vreg->cpr4_regulator_data->mem_acc_funcs != NULL)
  3818. + vreg->cpr4_regulator_data->mem_acc_funcs->clear_mem_acc(rdev);
  3819. +
  3820. + cpr3_debug(vreg, "set corner=%d\n", corner);
  3821. +done:
  3822. + mutex_unlock(&ctrl->lock);
  3823. +
  3824. + return rc;
  3825. +}
  3826. +
  3827. +/**
  3828. + * cpr3_handle_temp_open_loop_adjustment() - voltage based cold temperature
  3829. + *
  3830. + * @rdev: Regulator device pointer for the cpr3-regulator
  3831. + * @is_cold: Flag to denote enter/exit cold condition
  3832. + *
  3833. + * This function is adjusts voltage margin based on cold condition
  3834. + *
  3835. + * Return: 0 = success
  3836. + */
  3837. +
  3838. +int cpr3_handle_temp_open_loop_adjustment(struct cpr3_controller *ctrl,
  3839. + bool is_cold)
  3840. +{
  3841. + int i ,j, k, rc;
  3842. + struct cpr3_regulator *vreg;
  3843. +
  3844. + mutex_lock(&ctrl->lock);
  3845. + for (i = 0; i < ctrl->thread_count; i++) {
  3846. + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
  3847. + vreg = &ctrl->thread[i].vreg[j];
  3848. + for (k = 0; k < vreg->corner_count; k++) {
  3849. + vreg->corner[k].open_loop_volt = is_cold ?
  3850. + vreg->corner[k].cold_temp_open_loop_volt :
  3851. + vreg->corner[k].normal_temp_open_loop_volt;
  3852. + }
  3853. + }
  3854. + }
  3855. + rc = cpr3_regulator_update_ctrl_state(ctrl);
  3856. + mutex_unlock(&ctrl->lock);
  3857. +
  3858. + return rc;
  3859. +}
  3860. +
  3861. +/**
  3862. + * cpr3_regulator_get_voltage() - get the voltage corner for the CPR3 regulator
  3863. + * associated with the regulator device
  3864. + * @rdev: Regulator device pointer for the cpr3-regulator
  3865. + *
  3866. + * This function is passed as a callback function into the regulator ops that
  3867. + * are registered for each cpr3-regulator device.
  3868. + *
  3869. + * Return: voltage corner value offset by CPR3_CORNER_OFFSET
  3870. + */
  3871. +static int cpr3_regulator_get_voltage(struct regulator_dev *rdev)
  3872. +{
  3873. + struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
  3874. +
  3875. + if (vreg->current_corner == CPR3_REGULATOR_CORNER_INVALID)
  3876. + return CPR3_CORNER_OFFSET;
  3877. + else
  3878. + return vreg->current_corner + CPR3_CORNER_OFFSET;
  3879. +}
  3880. +
  3881. +/**
  3882. + * cpr3_regulator_list_voltage() - return the voltage corner mapped to the
  3883. + * specified selector
  3884. + * @rdev: Regulator device pointer for the cpr3-regulator
  3885. + * @selector: Regulator selector
  3886. + *
  3887. + * This function is passed as a callback function into the regulator ops that
  3888. + * are registered for each cpr3-regulator device.
  3889. + *
  3890. + * Return: voltage corner value offset by CPR3_CORNER_OFFSET
  3891. + */
  3892. +static int cpr3_regulator_list_voltage(struct regulator_dev *rdev,
  3893. + unsigned selector)
  3894. +{
  3895. + struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
  3896. +
  3897. + if (selector < vreg->corner_count)
  3898. + return selector + CPR3_CORNER_OFFSET;
  3899. + else
  3900. + return 0;
  3901. +}
  3902. +
  3903. +/**
  3904. + * cpr3_regulator_is_enabled() - return the enable state of the CPR3 regulator
  3905. + * @rdev: Regulator device pointer for the cpr3-regulator
  3906. + *
  3907. + * This function is passed as a callback function into the regulator ops that
  3908. + * are registered for each cpr3-regulator device.
  3909. + *
  3910. + * Return: true if regulator is enabled, false if regulator is disabled
  3911. + */
  3912. +static int cpr3_regulator_is_enabled(struct regulator_dev *rdev)
  3913. +{
  3914. + struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
  3915. +
  3916. + return vreg->vreg_enabled;
  3917. +}
  3918. +
  3919. +/**
  3920. + * cpr3_regulator_enable() - enable the CPR3 regulator
  3921. + * @rdev: Regulator device pointer for the cpr3-regulator
  3922. + *
  3923. + * This function is passed as a callback function into the regulator ops that
  3924. + * are registered for each cpr3-regulator device.
  3925. + *
  3926. + * Return: 0 on success, errno on failure
  3927. + */
  3928. +static int cpr3_regulator_enable(struct regulator_dev *rdev)
  3929. +{
  3930. + struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
  3931. + struct cpr3_controller *ctrl = vreg->thread->ctrl;
  3932. + int rc = 0;
  3933. +
  3934. + if (vreg->vreg_enabled == true)
  3935. + return 0;
  3936. +
  3937. + mutex_lock(&ctrl->lock);
  3938. +
  3939. + if (ctrl->system_regulator) {
  3940. + rc = regulator_enable(ctrl->system_regulator);
  3941. + if (rc) {
  3942. + cpr3_err(ctrl, "regulator_enable(system) failed, rc=%d\n",
  3943. + rc);
  3944. + goto done;
  3945. + }
  3946. + }
  3947. +
  3948. + rc = regulator_enable(ctrl->vdd_regulator);
  3949. + if (rc) {
  3950. + cpr3_err(vreg, "regulator_enable(vdd) failed, rc=%d\n", rc);
  3951. + goto done;
  3952. + }
  3953. +
  3954. + vreg->vreg_enabled = true;
  3955. + rc = cpr3_regulator_update_ctrl_state(ctrl);
  3956. + if (rc) {
  3957. + cpr3_err(vreg, "could not update CPR state, rc=%d\n", rc);
  3958. + regulator_disable(ctrl->vdd_regulator);
  3959. + vreg->vreg_enabled = false;
  3960. + goto done;
  3961. + }
  3962. +
  3963. + cpr3_debug(vreg, "Enabled\n");
  3964. +done:
  3965. + mutex_unlock(&ctrl->lock);
  3966. +
  3967. + return rc;
  3968. +}
  3969. +
  3970. +/**
  3971. + * cpr3_regulator_disable() - disable the CPR3 regulator
  3972. + * @rdev: Regulator device pointer for the cpr3-regulator
  3973. + *
  3974. + * This function is passed as a callback function into the regulator ops that
  3975. + * are registered for each cpr3-regulator device.
  3976. + *
  3977. + * Return: 0 on success, errno on failure
  3978. + */
  3979. +static int cpr3_regulator_disable(struct regulator_dev *rdev)
  3980. +{
  3981. + struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
  3982. + struct cpr3_controller *ctrl = vreg->thread->ctrl;
  3983. + int rc, rc2;
  3984. +
  3985. + if (vreg->vreg_enabled == false)
  3986. + return 0;
  3987. +
  3988. + mutex_lock(&ctrl->lock);
  3989. + rc = regulator_disable(ctrl->vdd_regulator);
  3990. + if (rc) {
  3991. + cpr3_err(vreg, "regulator_disable(vdd) failed, rc=%d\n", rc);
  3992. + goto done;
  3993. + }
  3994. +
  3995. + vreg->vreg_enabled = false;
  3996. + rc = cpr3_regulator_update_ctrl_state(ctrl);
  3997. + if (rc) {
  3998. + cpr3_err(vreg, "could not update CPR state, rc=%d\n", rc);
  3999. + rc2 = regulator_enable(ctrl->vdd_regulator);
  4000. + vreg->vreg_enabled = true;
  4001. + goto done;
  4002. + }
  4003. +
  4004. + if (ctrl->system_regulator) {
  4005. + rc = regulator_disable(ctrl->system_regulator);
  4006. + if (rc) {
  4007. + cpr3_err(ctrl, "regulator_disable(system) failed, rc=%d\n",
  4008. + rc);
  4009. + goto done;
  4010. + }
  4011. + }
  4012. +
  4013. + cpr3_debug(vreg, "Disabled\n");
  4014. +done:
  4015. + mutex_unlock(&ctrl->lock);
  4016. +
  4017. + return rc;
  4018. +}
  4019. +
  4020. +static struct regulator_ops cpr3_regulator_ops = {
  4021. + .enable = cpr3_regulator_enable,
  4022. + .disable = cpr3_regulator_disable,
  4023. + .is_enabled = cpr3_regulator_is_enabled,
  4024. + .set_voltage = cpr3_regulator_set_voltage,
  4025. + .get_voltage = cpr3_regulator_get_voltage,
  4026. + .list_voltage = cpr3_regulator_list_voltage,
  4027. +};
  4028. +
  4029. +/**
  4030. + * cpr3_print_result() - print CPR measurement results to the kernel log for
  4031. + * debugging purposes
  4032. + * @thread: Pointer to the CPR3 thread
  4033. + *
  4034. + * Return: None
  4035. + */
  4036. +static void cpr3_print_result(struct cpr3_thread *thread)
  4037. +{
  4038. + struct cpr3_controller *ctrl = thread->ctrl;
  4039. + u32 result[3], busy, step_dn, step_up, error_steps, error, negative;
  4040. + u32 quot_min, quot_max, ro_min, ro_max, step_quot_min, step_quot_max;
  4041. + u32 sensor_min, sensor_max;
  4042. + char *sign;
  4043. +
  4044. + result[0] = cpr3_read(ctrl, CPR3_REG_RESULT0(thread->thread_id));
  4045. + result[1] = cpr3_read(ctrl, CPR3_REG_RESULT1(thread->thread_id));
  4046. + result[2] = cpr3_read(ctrl, CPR3_REG_RESULT2(thread->thread_id));
  4047. +
  4048. + busy = !!(result[0] & CPR3_RESULT0_BUSY_MASK);
  4049. + step_dn = !!(result[0] & CPR3_RESULT0_STEP_DN_MASK);
  4050. + step_up = !!(result[0] & CPR3_RESULT0_STEP_UP_MASK);
  4051. + error_steps = (result[0] & CPR3_RESULT0_ERROR_STEPS_MASK)
  4052. + >> CPR3_RESULT0_ERROR_STEPS_SHIFT;
  4053. + error = (result[0] & CPR3_RESULT0_ERROR_MASK)
  4054. + >> CPR3_RESULT0_ERROR_SHIFT;
  4055. + negative = !!(result[0] & CPR3_RESULT0_NEGATIVE_MASK);
  4056. +
  4057. + quot_min = (result[1] & CPR3_RESULT1_QUOT_MIN_MASK)
  4058. + >> CPR3_RESULT1_QUOT_MIN_SHIFT;
  4059. + quot_max = (result[1] & CPR3_RESULT1_QUOT_MAX_MASK)
  4060. + >> CPR3_RESULT1_QUOT_MAX_SHIFT;
  4061. + ro_min = (result[1] & CPR3_RESULT1_RO_MIN_MASK)
  4062. + >> CPR3_RESULT1_RO_MIN_SHIFT;
  4063. + ro_max = (result[1] & CPR3_RESULT1_RO_MAX_MASK)
  4064. + >> CPR3_RESULT1_RO_MAX_SHIFT;
  4065. +
  4066. + step_quot_min = (result[2] & CPR3_RESULT2_STEP_QUOT_MIN_MASK)
  4067. + >> CPR3_RESULT2_STEP_QUOT_MIN_SHIFT;
  4068. + step_quot_max = (result[2] & CPR3_RESULT2_STEP_QUOT_MAX_MASK)
  4069. + >> CPR3_RESULT2_STEP_QUOT_MAX_SHIFT;
  4070. + sensor_min = (result[2] & CPR3_RESULT2_SENSOR_MIN_MASK)
  4071. + >> CPR3_RESULT2_SENSOR_MIN_SHIFT;
  4072. + sensor_max = (result[2] & CPR3_RESULT2_SENSOR_MAX_MASK)
  4073. + >> CPR3_RESULT2_SENSOR_MAX_SHIFT;
  4074. +
  4075. + sign = negative ? "-" : "";
  4076. + cpr3_debug(ctrl, "thread %u: busy=%u, step_dn=%u, step_up=%u, error_steps=%s%u, error=%s%u\n",
  4077. + thread->thread_id, busy, step_dn, step_up, sign, error_steps,
  4078. + sign, error);
  4079. + cpr3_debug(ctrl, "thread %u: quot_min=%u, quot_max=%u, ro_min=%u, ro_max=%u\n",
  4080. + thread->thread_id, quot_min, quot_max, ro_min, ro_max);
  4081. + cpr3_debug(ctrl, "thread %u: step_quot_min=%u, step_quot_max=%u, sensor_min=%u, sensor_max=%u\n",
  4082. + thread->thread_id, step_quot_min, step_quot_max, sensor_min,
  4083. + sensor_max);
  4084. +}
  4085. +
  4086. +/**
  4087. + * cpr3_thread_busy() - returns if the specified CPR3 thread is busy taking
  4088. + * a measurement
  4089. + * @thread: Pointer to the CPR3 thread
  4090. + *
  4091. + * Return: CPR3 busy status
  4092. + */
  4093. +static bool cpr3_thread_busy(struct cpr3_thread *thread)
  4094. +{
  4095. + u32 result;
  4096. +
  4097. + result = cpr3_read(thread->ctrl, CPR3_REG_RESULT0(thread->thread_id));
  4098. +
  4099. + return !!(result & CPR3_RESULT0_BUSY_MASK);
  4100. +}
  4101. +
  4102. +/**
  4103. + * cpr3_irq_handler() - CPR interrupt handler callback function used for
  4104. + * software closed-loop operation
  4105. + * @irq: CPR interrupt number
  4106. + * @data: Private data corresponding to the CPR3 controller
  4107. + * pointer
  4108. + *
  4109. + * This function increases or decreases the vdd supply voltage based upon the
  4110. + * CPR controller recommendation.
  4111. + *
  4112. + * Return: IRQ_HANDLED
  4113. + */
  4114. +static irqreturn_t cpr3_irq_handler(int irq, void *data)
  4115. +{
  4116. + struct cpr3_controller *ctrl = data;
  4117. + struct cpr3_corner *aggr = &ctrl->aggr_corner;
  4118. + u32 cont = CPR3_CONT_CMD_NACK;
  4119. + u32 reg_last_measurement = 0;
  4120. + struct cpr3_regulator *vreg;
  4121. + struct cpr3_corner *corner;
  4122. + unsigned long flags;
  4123. + int i, j, new_volt, last_volt, dynamic_floor_volt, rc;
  4124. + u32 irq_en, status, cpr_status, ctl;
  4125. + bool up, down;
  4126. +
  4127. + mutex_lock(&ctrl->lock);
  4128. +
  4129. + if (!ctrl->cpr_enabled) {
  4130. + cpr3_debug(ctrl, "CPR interrupt received but CPR is disabled\n");
  4131. + mutex_unlock(&ctrl->lock);
  4132. + return IRQ_HANDLED;
  4133. + } else if (ctrl->use_hw_closed_loop) {
  4134. + cpr3_debug(ctrl, "CPR interrupt received but CPR is using HW closed-loop\n");
  4135. + goto done;
  4136. + }
  4137. +
  4138. + /*
  4139. + * CPR IRQ status checking and CPR controller disabling must happen
  4140. + * atomically and without invening delay in order to avoid an interrupt
  4141. + * storm caused by the handler racing with the CPR controller.
  4142. + */
  4143. + local_irq_save(flags);
  4144. + preempt_disable();
  4145. +
  4146. + status = cpr3_read(ctrl, CPR3_REG_IRQ_STATUS);
  4147. + up = status & CPR3_IRQ_UP;
  4148. + down = status & CPR3_IRQ_DOWN;
  4149. +
  4150. + if (!up && !down) {
  4151. + /*
  4152. + * Toggle the CPR controller off and then back on since the
  4153. + * hardware and software states are out of sync. This condition
  4154. + * occurs after an aging measurement completes as the CPR IRQ
  4155. + * physically triggers during the aging measurement but the
  4156. + * handler is stuck waiting on the mutex lock.
  4157. + */
  4158. + cpr3_ctrl_loop_disable(ctrl);
  4159. +
  4160. + local_irq_restore(flags);
  4161. + preempt_enable();
  4162. +
  4163. + /* Wait for the loop disable write to complete */
  4164. + mb();
  4165. +
  4166. + /* Wait for BUSY=1 and LOOP_EN=0 in CPR controller registers. */
  4167. + for (i = 0; i < CPR3_REGISTER_WRITE_DELAY_US / 10; i++) {
  4168. + cpr_status = cpr3_read(ctrl, CPR3_REG_CPR_STATUS);
  4169. + ctl = cpr3_read(ctrl, CPR3_REG_CPR_CTL);
  4170. + if (cpr_status & CPR3_CPR_STATUS_BUSY_MASK
  4171. + && (ctl & CPR3_CPR_CTL_LOOP_EN_MASK)
  4172. + == CPR3_CPR_CTL_LOOP_DISABLE)
  4173. + break;
  4174. + udelay(10);
  4175. + }
  4176. + if (i == CPR3_REGISTER_WRITE_DELAY_US / 10)
  4177. + cpr3_debug(ctrl, "CPR controller not disabled after %d us\n",
  4178. + CPR3_REGISTER_WRITE_DELAY_US);
  4179. +
  4180. + /* Clear interrupt status */
  4181. + cpr3_write(ctrl, CPR3_REG_IRQ_CLEAR,
  4182. + CPR3_IRQ_UP | CPR3_IRQ_DOWN);
  4183. +
  4184. + /* Wait for the interrupt clearing write to complete */
  4185. + mb();
  4186. +
  4187. + /* Wait for IRQ_STATUS register to be cleared. */
  4188. + for (i = 0; i < CPR3_REGISTER_WRITE_DELAY_US / 10; i++) {
  4189. + status = cpr3_read(ctrl, CPR3_REG_IRQ_STATUS);
  4190. + if (!(status & (CPR3_IRQ_UP | CPR3_IRQ_DOWN)))
  4191. + break;
  4192. + udelay(10);
  4193. + }
  4194. + if (i == CPR3_REGISTER_WRITE_DELAY_US / 10)
  4195. + cpr3_debug(ctrl, "CPR interrupts not cleared after %d us\n",
  4196. + CPR3_REGISTER_WRITE_DELAY_US);
  4197. +
  4198. + cpr3_ctrl_loop_enable(ctrl);
  4199. +
  4200. + cpr3_debug(ctrl, "CPR interrupt received but no up or down status bit is set\n");
  4201. +
  4202. + mutex_unlock(&ctrl->lock);
  4203. + return IRQ_HANDLED;
  4204. + } else if (up && down) {
  4205. + cpr3_debug(ctrl, "both up and down status bits set\n");
  4206. + /* The up flag takes precedence over the down flag. */
  4207. + down = false;
  4208. + }
  4209. +
  4210. + if (ctrl->supports_hw_closed_loop)
  4211. + reg_last_measurement
  4212. + = cpr3_read(ctrl, CPR3_REG_LAST_MEASUREMENT);
  4213. + dynamic_floor_volt = cpr3_regulator_get_dynamic_floor_volt(ctrl,
  4214. + reg_last_measurement);
  4215. +
  4216. + local_irq_restore(flags);
  4217. + preempt_enable();
  4218. +
  4219. + irq_en = aggr->irq_en;
  4220. + last_volt = aggr->last_volt;
  4221. +
  4222. + for (i = 0; i < ctrl->thread_count; i++) {
  4223. + if (cpr3_thread_busy(&ctrl->thread[i])) {
  4224. + cpr3_debug(ctrl, "CPR thread %u busy when it should be waiting for SW cont\n",
  4225. + ctrl->thread[i].thread_id);
  4226. + goto done;
  4227. + }
  4228. + }
  4229. +
  4230. + new_volt = up ? last_volt + ctrl->step_volt
  4231. + : last_volt - ctrl->step_volt;
  4232. +
  4233. + /* Re-enable UP/DOWN interrupt when its opposite is received. */
  4234. + irq_en |= up ? CPR3_IRQ_DOWN : CPR3_IRQ_UP;
  4235. +
  4236. + if (new_volt > aggr->ceiling_volt) {
  4237. + new_volt = aggr->ceiling_volt;
  4238. + irq_en &= ~CPR3_IRQ_UP;
  4239. + cpr3_debug(ctrl, "limiting to ceiling=%d uV\n",
  4240. + aggr->ceiling_volt);
  4241. + } else if (new_volt < aggr->floor_volt) {
  4242. + new_volt = aggr->floor_volt;
  4243. + irq_en &= ~CPR3_IRQ_DOWN;
  4244. + cpr3_debug(ctrl, "limiting to floor=%d uV\n", aggr->floor_volt);
  4245. + }
  4246. +
  4247. + if (down && new_volt < dynamic_floor_volt) {
  4248. + /*
  4249. + * The vdd-supply voltage should not be decreased below the
  4250. + * dynamic floor voltage. However, it is not necessary (and
  4251. + * counter productive) to force the voltage up to this level
  4252. + * if it happened to be below it since the closed-loop voltage
  4253. + * must have gotten there in a safe manner while the power
  4254. + * domains for the CPR3 regulator imposing the dynamic floor
  4255. + * were not bypassed.
  4256. + */
  4257. + new_volt = last_volt;
  4258. + irq_en &= ~CPR3_IRQ_DOWN;
  4259. + cpr3_debug(ctrl, "limiting to dynamic floor=%d uV\n",
  4260. + dynamic_floor_volt);
  4261. + }
  4262. +
  4263. + for (i = 0; i < ctrl->thread_count; i++)
  4264. + cpr3_print_result(&ctrl->thread[i]);
  4265. +
  4266. + cpr3_debug(ctrl, "%s: new_volt=%d uV, last_volt=%d uV\n",
  4267. + up ? "UP" : "DN", new_volt, last_volt);
  4268. +
  4269. + if (ctrl->proc_clock_throttle && last_volt == aggr->ceiling_volt
  4270. + && new_volt < last_volt)
  4271. + cpr3_write(ctrl, CPR3_REG_PD_THROTTLE,
  4272. + ctrl->proc_clock_throttle);
  4273. +
  4274. + if (new_volt != last_volt) {
  4275. + rc = cpr3_regulator_scale_vdd_voltage(ctrl, new_volt,
  4276. + last_volt,
  4277. + aggr);
  4278. + if (rc) {
  4279. + cpr3_err(ctrl, "scale_vdd() failed to set vdd=%d uV, rc=%d\n",
  4280. + new_volt, rc);
  4281. + goto done;
  4282. + }
  4283. + cont = CPR3_CONT_CMD_ACK;
  4284. +
  4285. + /*
  4286. + * Update the closed-loop voltage for all regulators managed
  4287. + * by this CPR controller.
  4288. + */
  4289. + for (i = 0; i < ctrl->thread_count; i++) {
  4290. + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
  4291. + vreg = &ctrl->thread[i].vreg[j];
  4292. + cpr3_update_vreg_closed_loop_volt(vreg,
  4293. + new_volt, reg_last_measurement);
  4294. + }
  4295. + }
  4296. + }
  4297. +
  4298. + if (ctrl->proc_clock_throttle && new_volt == aggr->ceiling_volt)
  4299. + cpr3_write(ctrl, CPR3_REG_PD_THROTTLE,
  4300. + CPR3_PD_THROTTLE_DISABLE);
  4301. +
  4302. + corner = &ctrl->thread[0].vreg[0].corner[
  4303. + ctrl->thread[0].vreg[0].current_corner];
  4304. +
  4305. + if (irq_en != aggr->irq_en) {
  4306. + aggr->irq_en = irq_en;
  4307. + cpr3_write(ctrl, CPR3_REG_IRQ_EN, irq_en);
  4308. + }
  4309. +
  4310. + aggr->last_volt = new_volt;
  4311. +
  4312. +done:
  4313. + /* Clear interrupt status */
  4314. + cpr3_write(ctrl, CPR3_REG_IRQ_CLEAR, CPR3_IRQ_UP | CPR3_IRQ_DOWN);
  4315. +
  4316. + /* ACK or NACK the CPR controller */
  4317. + cpr3_write(ctrl, CPR3_REG_CONT_CMD, cont);
  4318. +
  4319. + mutex_unlock(&ctrl->lock);
  4320. + return IRQ_HANDLED;
  4321. +}
  4322. +
  4323. +/**
  4324. + * cpr3_ceiling_irq_handler() - CPR ceiling reached interrupt handler callback
  4325. + * function used for hardware closed-loop operation
  4326. + * @irq: CPR ceiling interrupt number
  4327. + * @data: Private data corresponding to the CPR3 controller
  4328. + * pointer
  4329. + *
  4330. + * This function disables processor clock throttling and closed-loop operation
  4331. + * when the ceiling voltage is reached.
  4332. + *
  4333. + * Return: IRQ_HANDLED
  4334. + */
  4335. +static irqreturn_t cpr3_ceiling_irq_handler(int irq, void *data)
  4336. +{
  4337. + struct cpr3_controller *ctrl = data;
  4338. + int volt;
  4339. +
  4340. + mutex_lock(&ctrl->lock);
  4341. +
  4342. + if (!ctrl->cpr_enabled) {
  4343. + cpr3_debug(ctrl, "CPR ceiling interrupt received but CPR is disabled\n");
  4344. + goto done;
  4345. + } else if (!ctrl->use_hw_closed_loop) {
  4346. + cpr3_debug(ctrl, "CPR ceiling interrupt received but CPR is using SW closed-loop\n");
  4347. + goto done;
  4348. + }
  4349. +
  4350. + volt = regulator_get_voltage(ctrl->vdd_regulator);
  4351. + if (volt < 0) {
  4352. + cpr3_err(ctrl, "could not get vdd voltage, rc=%d\n", volt);
  4353. + goto done;
  4354. + } else if (volt != ctrl->aggr_corner.ceiling_volt) {
  4355. + cpr3_debug(ctrl, "CPR ceiling interrupt received but vdd voltage: %d uV != ceiling voltage: %d uV\n",
  4356. + volt, ctrl->aggr_corner.ceiling_volt);
  4357. + goto done;
  4358. + }
  4359. +
  4360. + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
  4361. + /*
  4362. + * Since the ceiling voltage has been reached, disable processor
  4363. + * clock throttling as well as CPR closed-loop operation.
  4364. + */
  4365. + cpr3_write(ctrl, CPR3_REG_PD_THROTTLE,
  4366. + CPR3_PD_THROTTLE_DISABLE);
  4367. + cpr3_ctrl_loop_disable(ctrl);
  4368. + cpr3_debug(ctrl, "CPR closed-loop and throttling disabled\n");
  4369. + }
  4370. +
  4371. +done:
  4372. + mutex_unlock(&ctrl->lock);
  4373. + return IRQ_HANDLED;
  4374. +}
  4375. +
  4376. +/**
  4377. + * cpr3_regulator_vreg_register() - register a regulator device for a CPR3
  4378. + * regulator
  4379. + * @vreg: Pointer to the CPR3 regulator
  4380. + *
  4381. + * This function initializes all regulator framework related structures and then
  4382. + * calls regulator_register() for the CPR3 regulator.
  4383. + *
  4384. + * Return: 0 on success, errno on failure
  4385. + */
  4386. +static int cpr3_regulator_vreg_register(struct cpr3_regulator *vreg)
  4387. +{
  4388. + struct regulator_config config = {};
  4389. + struct regulator_desc *rdesc;
  4390. + struct regulator_init_data *init_data;
  4391. + int rc;
  4392. +
  4393. + init_data = of_get_regulator_init_data(vreg->thread->ctrl->dev,
  4394. + vreg->of_node, &vreg->rdesc);
  4395. + if (!init_data) {
  4396. + cpr3_err(vreg, "regulator init data is missing\n");
  4397. + return -EINVAL;
  4398. + }
  4399. +
  4400. + init_data->constraints.input_uV = init_data->constraints.max_uV;
  4401. + rdesc = &vreg->rdesc;
  4402. + init_data->constraints.valid_ops_mask |=
  4403. + REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS;
  4404. + rdesc->ops = &cpr3_regulator_ops;
  4405. +
  4406. + rdesc->n_voltages = vreg->corner_count;
  4407. + rdesc->name = init_data->constraints.name;
  4408. + rdesc->owner = THIS_MODULE;
  4409. + rdesc->type = REGULATOR_VOLTAGE;
  4410. +
  4411. + config.dev = vreg->thread->ctrl->dev;
  4412. + config.driver_data = vreg;
  4413. + config.init_data = init_data;
  4414. + config.of_node = vreg->of_node;
  4415. +
  4416. + vreg->rdev = regulator_register(vreg->thread->ctrl->dev, rdesc, &config);
  4417. + if (IS_ERR(vreg->rdev)) {
  4418. + rc = PTR_ERR(vreg->rdev);
  4419. + cpr3_err(vreg, "regulator_register failed, rc=%d\n", rc);
  4420. + return rc;
  4421. + }
  4422. +
  4423. + return 0;
  4424. +}
  4425. +
  4426. +static int debugfs_int_set(void *data, u64 val)
  4427. +{
  4428. + *(int *)data = val;
  4429. + return 0;
  4430. +}
  4431. +
  4432. +static int debugfs_int_get(void *data, u64 *val)
  4433. +{
  4434. + *val = *(int *)data;
  4435. + return 0;
  4436. +}
  4437. +DEFINE_SIMPLE_ATTRIBUTE(fops_int, debugfs_int_get, debugfs_int_set, "%lld\n");
  4438. +DEFINE_SIMPLE_ATTRIBUTE(fops_int_ro, debugfs_int_get, NULL, "%lld\n");
  4439. +DEFINE_SIMPLE_ATTRIBUTE(fops_int_wo, NULL, debugfs_int_set, "%lld\n");
  4440. +
  4441. +/**
  4442. + * debugfs_create_int - create a debugfs file that is used to read and write a
  4443. + * signed int value
  4444. + * @name: Pointer to a string containing the name of the file to
  4445. + * create
  4446. + * @mode: The permissions that the file should have
  4447. + * @parent: Pointer to the parent dentry for this file. This should
  4448. + * be a directory dentry if set. If this parameter is
  4449. + * %NULL, then the file will be created in the root of the
  4450. + * debugfs filesystem.
  4451. + * @value: Pointer to the variable that the file should read to and
  4452. + * write from
  4453. + *
  4454. + * This function creates a file in debugfs with the given name that
  4455. + * contains the value of the variable @value. If the @mode variable is so
  4456. + * set, it can be read from, and written to.
  4457. + *
  4458. + * This function will return a pointer to a dentry if it succeeds. This
  4459. + * pointer must be passed to the debugfs_remove() function when the file is
  4460. + * to be removed. If an error occurs, %NULL will be returned.
  4461. + */
  4462. +static struct dentry *debugfs_create_int(const char *name, umode_t mode,
  4463. + struct dentry *parent, int *value)
  4464. +{
  4465. + /* if there are no write bits set, make read only */
  4466. + if (!(mode & S_IWUGO))
  4467. + return debugfs_create_file(name, mode, parent, value,
  4468. + &fops_int_ro);
  4469. + /* if there are no read bits set, make write only */
  4470. + if (!(mode & S_IRUGO))
  4471. + return debugfs_create_file(name, mode, parent, value,
  4472. + &fops_int_wo);
  4473. +
  4474. + return debugfs_create_file(name, mode, parent, value, &fops_int);
  4475. +}
  4476. +
  4477. +static int debugfs_bool_get(void *data, u64 *val)
  4478. +{
  4479. + *val = *(bool *)data;
  4480. + return 0;
  4481. +}
  4482. +DEFINE_SIMPLE_ATTRIBUTE(fops_bool_ro, debugfs_bool_get, NULL, "%lld\n");
  4483. +
  4484. +/**
  4485. + * struct cpr3_debug_corner_info - data structure used by the
  4486. + * cpr3_debugfs_create_corner_int function
  4487. + * @vreg: Pointer to the CPR3 regulator
  4488. + * @index: Pointer to the corner array index
  4489. + * @member_offset: Offset in bytes from the beginning of struct cpr3_corner
  4490. + * to the beginning of the value to be read from
  4491. + * @corner: Pointer to the CPR3 corner array
  4492. + */
  4493. +struct cpr3_debug_corner_info {
  4494. + struct cpr3_regulator *vreg;
  4495. + int *index;
  4496. + size_t member_offset;
  4497. + struct cpr3_corner *corner;
  4498. +};
  4499. +
  4500. +static int cpr3_debug_corner_int_get(void *data, u64 *val)
  4501. +{
  4502. + struct cpr3_debug_corner_info *info = data;
  4503. + struct cpr3_controller *ctrl = info->vreg->thread->ctrl;
  4504. + int i;
  4505. +
  4506. + mutex_lock(&ctrl->lock);
  4507. +
  4508. + i = *info->index;
  4509. + if (i < 0)
  4510. + i = 0;
  4511. +
  4512. + *val = *(int *)((char *)&info->vreg->corner[i] + info->member_offset);
  4513. +
  4514. + mutex_unlock(&ctrl->lock);
  4515. +
  4516. + return 0;
  4517. +}
  4518. +DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_corner_int_fops, cpr3_debug_corner_int_get,
  4519. + NULL, "%lld\n");
  4520. +
  4521. +/**
  4522. + * cpr3_debugfs_create_corner_int - create a debugfs file that is used to read
  4523. + * a signed int value out of a CPR3 regulator's corner array
  4524. + * @vreg: Pointer to the CPR3 regulator
  4525. + * @name: Pointer to a string containing the name of the file to
  4526. + * create
  4527. + * @mode: The permissions that the file should have
  4528. + * @parent: Pointer to the parent dentry for this file. This should
  4529. + * be a directory dentry if set. If this parameter is
  4530. + * %NULL, then the file will be created in the root of the
  4531. + * debugfs filesystem.
  4532. + * @index: Pointer to the corner array index
  4533. + * @member_offset: Offset in bytes from the beginning of struct cpr3_corner
  4534. + * to the beginning of the value to be read from
  4535. + *
  4536. + * This function creates a file in debugfs with the given name that
  4537. + * contains the value of the int type variable vreg->corner[index].member
  4538. + * where member_offset == offsetof(struct cpr3_corner, member).
  4539. + */
  4540. +static struct dentry *cpr3_debugfs_create_corner_int(
  4541. + struct cpr3_regulator *vreg, const char *name, umode_t mode,
  4542. + struct dentry *parent, int *index, size_t member_offset)
  4543. +{
  4544. + struct cpr3_debug_corner_info *info;
  4545. +
  4546. + info = devm_kzalloc(vreg->thread->ctrl->dev, sizeof(*info), GFP_KERNEL);
  4547. + if (!info)
  4548. + return NULL;
  4549. +
  4550. + info->vreg = vreg;
  4551. + info->index = index;
  4552. + info->member_offset = member_offset;
  4553. +
  4554. + return debugfs_create_file(name, mode, parent, info,
  4555. + &cpr3_debug_corner_int_fops);
  4556. +}
  4557. +
  4558. +static int cpr3_debug_quot_open(struct inode *inode, struct file *file)
  4559. +{
  4560. + struct cpr3_debug_corner_info *info = inode->i_private;
  4561. + struct cpr3_thread *thread = info->vreg->thread;
  4562. + int size, i, pos;
  4563. + u32 *quot;
  4564. + char *buf;
  4565. +
  4566. + /*
  4567. + * Max size:
  4568. + * - 10 digits + ' ' or '\n' = 11 bytes per number
  4569. + * - terminating '\0'
  4570. + */
  4571. + size = CPR3_RO_COUNT * 11;
  4572. + buf = kzalloc(size + 1, GFP_KERNEL);
  4573. + if (!buf)
  4574. + return -ENOMEM;
  4575. +
  4576. + file->private_data = buf;
  4577. +
  4578. + mutex_lock(&thread->ctrl->lock);
  4579. +
  4580. + quot = info->corner[*info->index].target_quot;
  4581. +
  4582. + for (i = 0, pos = 0; i < CPR3_RO_COUNT; i++)
  4583. + pos += scnprintf(buf + pos, size - pos, "%u%c",
  4584. + quot[i], i < CPR3_RO_COUNT - 1 ? ' ' : '\n');
  4585. +
  4586. + mutex_unlock(&thread->ctrl->lock);
  4587. +
  4588. + return nonseekable_open(inode, file);
  4589. +}
  4590. +
  4591. +static ssize_t cpr3_debug_quot_read(struct file *file, char __user *buf,
  4592. + size_t len, loff_t *ppos)
  4593. +{
  4594. + return simple_read_from_buffer(buf, len, ppos, file->private_data,
  4595. + strlen(file->private_data));
  4596. +}
  4597. +
  4598. +static int cpr3_debug_quot_release(struct inode *inode, struct file *file)
  4599. +{
  4600. + kfree(file->private_data);
  4601. +
  4602. + return 0;
  4603. +}
  4604. +
  4605. +static const struct file_operations cpr3_debug_quot_fops = {
  4606. + .owner = THIS_MODULE,
  4607. + .open = cpr3_debug_quot_open,
  4608. + .release = cpr3_debug_quot_release,
  4609. + .read = cpr3_debug_quot_read,
  4610. +};
  4611. +
  4612. +/**
  4613. + * cpr3_regulator_debugfs_corner_add() - add debugfs files to expose
  4614. + * configuration data for the CPR corner
  4615. + * @vreg: Pointer to the CPR3 regulator
  4616. + * @corner_dir: Pointer to the parent corner dentry for the new files
  4617. + * @index: Pointer to the corner array index
  4618. + *
  4619. + * Return: none
  4620. + */
  4621. +static void cpr3_regulator_debugfs_corner_add(struct cpr3_regulator *vreg,
  4622. + struct dentry *corner_dir, int *index)
  4623. +{
  4624. + struct cpr3_debug_corner_info *info;
  4625. + struct dentry *temp;
  4626. +
  4627. + temp = cpr3_debugfs_create_corner_int(vreg, "floor_volt", S_IRUGO,
  4628. + corner_dir, index, offsetof(struct cpr3_corner, floor_volt));
  4629. + if (IS_ERR_OR_NULL(temp)) {
  4630. + cpr3_err(vreg, "floor_volt debugfs file creation failed\n");
  4631. + return;
  4632. + }
  4633. +
  4634. + temp = cpr3_debugfs_create_corner_int(vreg, "ceiling_volt", S_IRUGO,
  4635. + corner_dir, index, offsetof(struct cpr3_corner, ceiling_volt));
  4636. + if (IS_ERR_OR_NULL(temp)) {
  4637. + cpr3_err(vreg, "ceiling_volt debugfs file creation failed\n");
  4638. + return;
  4639. + }
  4640. +
  4641. + temp = cpr3_debugfs_create_corner_int(vreg, "open_loop_volt", S_IRUGO,
  4642. + corner_dir, index,
  4643. + offsetof(struct cpr3_corner, open_loop_volt));
  4644. + if (IS_ERR_OR_NULL(temp)) {
  4645. + cpr3_err(vreg, "open_loop_volt debugfs file creation failed\n");
  4646. + return;
  4647. + }
  4648. +
  4649. + temp = cpr3_debugfs_create_corner_int(vreg, "last_volt", S_IRUGO,
  4650. + corner_dir, index, offsetof(struct cpr3_corner, last_volt));
  4651. + if (IS_ERR_OR_NULL(temp)) {
  4652. + cpr3_err(vreg, "last_volt debugfs file creation failed\n");
  4653. + return;
  4654. + }
  4655. +
  4656. + info = devm_kzalloc(vreg->thread->ctrl->dev, sizeof(*info), GFP_KERNEL);
  4657. + if (!info)
  4658. + return;
  4659. +
  4660. + info->vreg = vreg;
  4661. + info->index = index;
  4662. + info->corner = vreg->corner;
  4663. +
  4664. + temp = debugfs_create_file("target_quots", S_IRUGO, corner_dir,
  4665. + info, &cpr3_debug_quot_fops);
  4666. + if (IS_ERR_OR_NULL(temp)) {
  4667. + cpr3_err(vreg, "target_quots debugfs file creation failed\n");
  4668. + return;
  4669. + }
  4670. +}
  4671. +
  4672. +/**
  4673. + * cpr3_debug_corner_index_set() - debugfs callback used to change the
  4674. + * value of the CPR3 regulator debug_corner index
  4675. + * @data: Pointer to private data which is equal to the CPR3
  4676. + * regulator pointer
  4677. + * @val: New value for debug_corner
  4678. + *
  4679. + * Return: 0 on success, errno on failure
  4680. + */
  4681. +static int cpr3_debug_corner_index_set(void *data, u64 val)
  4682. +{
  4683. + struct cpr3_regulator *vreg = data;
  4684. +
  4685. + if (val < CPR3_CORNER_OFFSET || val > vreg->corner_count) {
  4686. + cpr3_err(vreg, "invalid corner index %llu; allowed values: %d-%d\n",
  4687. + val, CPR3_CORNER_OFFSET, vreg->corner_count);
  4688. + return -EINVAL;
  4689. + }
  4690. +
  4691. + mutex_lock(&vreg->thread->ctrl->lock);
  4692. + vreg->debug_corner = val - CPR3_CORNER_OFFSET;
  4693. + mutex_unlock(&vreg->thread->ctrl->lock);
  4694. +
  4695. + return 0;
  4696. +}
  4697. +
  4698. +/**
  4699. + * cpr3_debug_corner_index_get() - debugfs callback used to retrieve
  4700. + * the value of the CPR3 regulator debug_corner index
  4701. + * @data: Pointer to private data which is equal to the CPR3
  4702. + * regulator pointer
  4703. + * @val: Output parameter written with the value of
  4704. + * debug_corner
  4705. + *
  4706. + * Return: 0 on success, errno on failure
  4707. + */
  4708. +static int cpr3_debug_corner_index_get(void *data, u64 *val)
  4709. +{
  4710. + struct cpr3_regulator *vreg = data;
  4711. +
  4712. + *val = vreg->debug_corner + CPR3_CORNER_OFFSET;
  4713. +
  4714. + return 0;
  4715. +}
  4716. +DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_corner_index_fops,
  4717. + cpr3_debug_corner_index_get,
  4718. + cpr3_debug_corner_index_set,
  4719. + "%llu\n");
  4720. +
  4721. +/**
  4722. + * cpr3_debug_current_corner_index_get() - debugfs callback used to retrieve
  4723. + * the value of the CPR3 regulator current_corner index
  4724. + * @data: Pointer to private data which is equal to the CPR3
  4725. + * regulator pointer
  4726. + * @val: Output parameter written with the value of
  4727. + * current_corner
  4728. + *
  4729. + * Return: 0 on success, errno on failure
  4730. + */
  4731. +static int cpr3_debug_current_corner_index_get(void *data, u64 *val)
  4732. +{
  4733. + struct cpr3_regulator *vreg = data;
  4734. +
  4735. + *val = vreg->current_corner + CPR3_CORNER_OFFSET;
  4736. +
  4737. + return 0;
  4738. +}
  4739. +DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_current_corner_index_fops,
  4740. + cpr3_debug_current_corner_index_get,
  4741. + NULL, "%llu\n");
  4742. +
  4743. +/**
  4744. + * cpr3_regulator_debugfs_vreg_add() - add debugfs files to expose configuration
  4745. + * data for the CPR3 regulator
  4746. + * @vreg: Pointer to the CPR3 regulator
  4747. + * @thread_dir CPR3 thread debugfs directory handle
  4748. + *
  4749. + * Return: none
  4750. + */
  4751. +static void cpr3_regulator_debugfs_vreg_add(struct cpr3_regulator *vreg,
  4752. + struct dentry *thread_dir)
  4753. +{
  4754. + struct dentry *temp, *corner_dir, *vreg_dir;
  4755. +
  4756. + vreg_dir = debugfs_create_dir(vreg->name, thread_dir);
  4757. + if (IS_ERR_OR_NULL(vreg_dir)) {
  4758. + cpr3_err(vreg, "%s debugfs directory creation failed\n",
  4759. + vreg->name);
  4760. + return;
  4761. + }
  4762. +
  4763. + temp = debugfs_create_int("speed_bin_fuse", S_IRUGO, vreg_dir,
  4764. + &vreg->speed_bin_fuse);
  4765. + if (IS_ERR_OR_NULL(temp)) {
  4766. + cpr3_err(vreg, "speed_bin_fuse debugfs file creation failed\n");
  4767. + return;
  4768. + }
  4769. +
  4770. + temp = debugfs_create_int("cpr_rev_fuse", S_IRUGO, vreg_dir,
  4771. + &vreg->cpr_rev_fuse);
  4772. + if (IS_ERR_OR_NULL(temp)) {
  4773. + cpr3_err(vreg, "cpr_rev_fuse debugfs file creation failed\n");
  4774. + return;
  4775. + }
  4776. +
  4777. + temp = debugfs_create_int("fuse_combo", S_IRUGO, vreg_dir,
  4778. + &vreg->fuse_combo);
  4779. + if (IS_ERR_OR_NULL(temp)) {
  4780. + cpr3_err(vreg, "fuse_combo debugfs file creation failed\n");
  4781. + return;
  4782. + }
  4783. +
  4784. + temp = debugfs_create_int("corner_count", S_IRUGO, vreg_dir,
  4785. + &vreg->corner_count);
  4786. + if (IS_ERR_OR_NULL(temp)) {
  4787. + cpr3_err(vreg, "corner_count debugfs file creation failed\n");
  4788. + return;
  4789. + }
  4790. +
  4791. + corner_dir = debugfs_create_dir("corner", vreg_dir);
  4792. + if (IS_ERR_OR_NULL(corner_dir)) {
  4793. + cpr3_err(vreg, "corner debugfs directory creation failed\n");
  4794. + return;
  4795. + }
  4796. +
  4797. + temp = debugfs_create_file("index", S_IRUGO | S_IWUSR, corner_dir,
  4798. + vreg, &cpr3_debug_corner_index_fops);
  4799. + if (IS_ERR_OR_NULL(temp)) {
  4800. + cpr3_err(vreg, "index debugfs file creation failed\n");
  4801. + return;
  4802. + }
  4803. +
  4804. + cpr3_regulator_debugfs_corner_add(vreg, corner_dir,
  4805. + &vreg->debug_corner);
  4806. +
  4807. + corner_dir = debugfs_create_dir("current_corner", vreg_dir);
  4808. + if (IS_ERR_OR_NULL(corner_dir)) {
  4809. + cpr3_err(vreg, "current_corner debugfs directory creation failed\n");
  4810. + return;
  4811. + }
  4812. +
  4813. + temp = debugfs_create_file("index", S_IRUGO, corner_dir,
  4814. + vreg, &cpr3_debug_current_corner_index_fops);
  4815. + if (IS_ERR_OR_NULL(temp)) {
  4816. + cpr3_err(vreg, "index debugfs file creation failed\n");
  4817. + return;
  4818. + }
  4819. +
  4820. + cpr3_regulator_debugfs_corner_add(vreg, corner_dir,
  4821. + &vreg->current_corner);
  4822. +}
  4823. +
  4824. +/**
  4825. + * cpr3_regulator_debugfs_thread_add() - add debugfs files to expose
  4826. + * configuration data for the CPR thread
  4827. + * @thread: Pointer to the CPR3 thread
  4828. + *
  4829. + * Return: none
  4830. + */
  4831. +static void cpr3_regulator_debugfs_thread_add(struct cpr3_thread *thread)
  4832. +{
  4833. + struct cpr3_controller *ctrl = thread->ctrl;
  4834. + struct dentry *aggr_dir, *temp, *thread_dir;
  4835. + struct cpr3_debug_corner_info *info;
  4836. + char buf[20];
  4837. + int *index;
  4838. + int i;
  4839. +
  4840. + scnprintf(buf, sizeof(buf), "thread%u", thread->thread_id);
  4841. + thread_dir = debugfs_create_dir(buf, thread->ctrl->debugfs);
  4842. + if (IS_ERR_OR_NULL(thread_dir)) {
  4843. + cpr3_err(ctrl, "thread %u %s debugfs directory creation failed\n",
  4844. + thread->thread_id, buf);
  4845. + return;
  4846. + }
  4847. +
  4848. + aggr_dir = debugfs_create_dir("max_aggregated_params", thread_dir);
  4849. + if (IS_ERR_OR_NULL(aggr_dir)) {
  4850. + cpr3_err(ctrl, "thread %u max_aggregated_params debugfs directory creation failed\n",
  4851. + thread->thread_id);
  4852. + return;
  4853. + }
  4854. +
  4855. + temp = debugfs_create_int("floor_volt", S_IRUGO, aggr_dir,
  4856. + &thread->aggr_corner.floor_volt);
  4857. + if (IS_ERR_OR_NULL(temp)) {
  4858. + cpr3_err(ctrl, "thread %u aggr floor_volt debugfs file creation failed\n",
  4859. + thread->thread_id);
  4860. + return;
  4861. + }
  4862. +
  4863. + temp = debugfs_create_int("ceiling_volt", S_IRUGO, aggr_dir,
  4864. + &thread->aggr_corner.ceiling_volt);
  4865. + if (IS_ERR_OR_NULL(temp)) {
  4866. + cpr3_err(ctrl, "thread %u aggr ceiling_volt debugfs file creation failed\n",
  4867. + thread->thread_id);
  4868. + return;
  4869. + }
  4870. +
  4871. + temp = debugfs_create_int("open_loop_volt", S_IRUGO, aggr_dir,
  4872. + &thread->aggr_corner.open_loop_volt);
  4873. + if (IS_ERR_OR_NULL(temp)) {
  4874. + cpr3_err(ctrl, "thread %u aggr open_loop_volt debugfs file creation failed\n",
  4875. + thread->thread_id);
  4876. + return;
  4877. + }
  4878. +
  4879. + temp = debugfs_create_int("last_volt", S_IRUGO, aggr_dir,
  4880. + &thread->aggr_corner.last_volt);
  4881. + if (IS_ERR_OR_NULL(temp)) {
  4882. + cpr3_err(ctrl, "thread %u aggr last_volt debugfs file creation failed\n",
  4883. + thread->thread_id);
  4884. + return;
  4885. + }
  4886. +
  4887. + info = devm_kzalloc(thread->ctrl->dev, sizeof(*info), GFP_KERNEL);
  4888. + index = devm_kzalloc(thread->ctrl->dev, sizeof(*index), GFP_KERNEL);
  4889. + if (!info || !index)
  4890. + return;
  4891. + *index = 0;
  4892. + info->vreg = &thread->vreg[0];
  4893. + info->index = index;
  4894. + info->corner = &thread->aggr_corner;
  4895. +
  4896. + temp = debugfs_create_file("target_quots", S_IRUGO, aggr_dir,
  4897. + info, &cpr3_debug_quot_fops);
  4898. + if (IS_ERR_OR_NULL(temp)) {
  4899. + cpr3_err(ctrl, "thread %u target_quots debugfs file creation failed\n",
  4900. + thread->thread_id);
  4901. + return;
  4902. + }
  4903. +
  4904. + for (i = 0; i < thread->vreg_count; i++)
  4905. + cpr3_regulator_debugfs_vreg_add(&thread->vreg[i], thread_dir);
  4906. +}
  4907. +
  4908. +/**
  4909. + * cpr3_debug_closed_loop_enable_set() - debugfs callback used to change the
  4910. + * value of the CPR controller cpr_allowed_sw flag which enables or
  4911. + * disables closed-loop operation
  4912. + * @data: Pointer to private data which is equal to the CPR
  4913. + * controller pointer
  4914. + * @val: New value for cpr_allowed_sw
  4915. + *
  4916. + * Return: 0 on success, errno on failure
  4917. + */
  4918. +static int cpr3_debug_closed_loop_enable_set(void *data, u64 val)
  4919. +{
  4920. + struct cpr3_controller *ctrl = data;
  4921. + bool enable = !!val;
  4922. + int rc;
  4923. +
  4924. + mutex_lock(&ctrl->lock);
  4925. +
  4926. + if (ctrl->cpr_allowed_sw == enable)
  4927. + goto done;
  4928. +
  4929. + if (enable && !ctrl->cpr_allowed_hw) {
  4930. + cpr3_err(ctrl, "CPR closed-loop operation is not allowed\n");
  4931. + goto done;
  4932. + }
  4933. +
  4934. + ctrl->cpr_allowed_sw = enable;
  4935. +
  4936. + rc = cpr3_regulator_update_ctrl_state(ctrl);
  4937. + if (rc) {
  4938. + cpr3_err(ctrl, "could not change CPR enable state=%u, rc=%d\n",
  4939. + enable, rc);
  4940. + goto done;
  4941. + }
  4942. +
  4943. + if (ctrl->proc_clock_throttle && !ctrl->cpr_enabled) {
  4944. + rc = cpr3_clock_enable(ctrl);
  4945. + if (rc) {
  4946. + cpr3_err(ctrl, "clock enable failed, rc=%d\n",
  4947. + rc);
  4948. + goto done;
  4949. + }
  4950. + ctrl->cpr_enabled = true;
  4951. +
  4952. + cpr3_write(ctrl, CPR3_REG_PD_THROTTLE,
  4953. + CPR3_PD_THROTTLE_DISABLE);
  4954. +
  4955. + cpr3_clock_disable(ctrl);
  4956. + ctrl->cpr_enabled = false;
  4957. + }
  4958. +
  4959. + cpr3_debug(ctrl, "closed-loop=%s\n", enable ? "enabled" : "disabled");
  4960. +done:
  4961. + mutex_unlock(&ctrl->lock);
  4962. + return 0;
  4963. +}
  4964. +
  4965. +/**
  4966. + * cpr3_debug_closed_loop_enable_get() - debugfs callback used to retrieve
  4967. + * the value of the CPR controller cpr_allowed_sw flag which
  4968. + * indicates if closed-loop operation is enabled
  4969. + * @data: Pointer to private data which is equal to the CPR
  4970. + * controller pointer
  4971. + * @val: Output parameter written with the value of
  4972. + * cpr_allowed_sw
  4973. + *
  4974. + * Return: 0 on success, errno on failure
  4975. + */
  4976. +static int cpr3_debug_closed_loop_enable_get(void *data, u64 *val)
  4977. +{
  4978. + struct cpr3_controller *ctrl = data;
  4979. +
  4980. + *val = ctrl->cpr_allowed_sw;
  4981. +
  4982. + return 0;
  4983. +}
  4984. +DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_closed_loop_enable_fops,
  4985. + cpr3_debug_closed_loop_enable_get,
  4986. + cpr3_debug_closed_loop_enable_set,
  4987. + "%llu\n");
  4988. +
  4989. +/**
  4990. + * cpr3_debug_hw_closed_loop_enable_set() - debugfs callback used to change the
  4991. + * value of the CPR controller use_hw_closed_loop flag which
  4992. + * switches between software closed-loop and hardware closed-loop
  4993. + * operation for CPR3 and CPR4 controllers and between open-loop
  4994. + * and full hardware closed-loop operation for CPRh controllers.
  4995. + * @data: Pointer to private data which is equal to the CPR
  4996. + * controller pointer
  4997. + * @val: New value for use_hw_closed_loop
  4998. + *
  4999. + * Return: 0 on success, errno on failure
  5000. + */
  5001. +static int cpr3_debug_hw_closed_loop_enable_set(void *data, u64 val)
  5002. +{
  5003. + struct cpr3_controller *ctrl = data;
  5004. + bool use_hw_closed_loop = !!val;
  5005. + struct cpr3_regulator *vreg;
  5006. + bool cpr_enabled;
  5007. + int i, j, k, rc;
  5008. +
  5009. + mutex_lock(&ctrl->lock);
  5010. +
  5011. + if (ctrl->use_hw_closed_loop == use_hw_closed_loop)
  5012. + goto done;
  5013. +
  5014. + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
  5015. + rc = cpr3_ctrl_clear_cpr4_config(ctrl);
  5016. + if (rc) {
  5017. + cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
  5018. + rc);
  5019. + goto done;
  5020. + }
  5021. + }
  5022. +
  5023. + cpr3_ctrl_loop_disable(ctrl);
  5024. +
  5025. + ctrl->use_hw_closed_loop = use_hw_closed_loop;
  5026. +
  5027. + cpr_enabled = ctrl->cpr_enabled;
  5028. +
  5029. + /* Ensure that CPR clocks are enabled before writing to registers. */
  5030. + if (!cpr_enabled) {
  5031. + rc = cpr3_clock_enable(ctrl);
  5032. + if (rc) {
  5033. + cpr3_err(ctrl, "clock enable failed, rc=%d\n", rc);
  5034. + goto done;
  5035. + }
  5036. + ctrl->cpr_enabled = true;
  5037. + }
  5038. +
  5039. + if (ctrl->use_hw_closed_loop)
  5040. + cpr3_write(ctrl, CPR3_REG_IRQ_EN, 0);
  5041. +
  5042. + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
  5043. + cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
  5044. + CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK,
  5045. + ctrl->use_hw_closed_loop
  5046. + ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE
  5047. + : CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE);
  5048. + } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
  5049. + cpr3_write(ctrl, CPR3_REG_HW_CLOSED_LOOP,
  5050. + ctrl->use_hw_closed_loop
  5051. + ? CPR3_HW_CLOSED_LOOP_ENABLE
  5052. + : CPR3_HW_CLOSED_LOOP_DISABLE);
  5053. + }
  5054. +
  5055. + /* Turn off CPR clocks if they were off before this function call. */
  5056. + if (!cpr_enabled) {
  5057. + cpr3_clock_disable(ctrl);
  5058. + ctrl->cpr_enabled = false;
  5059. + }
  5060. +
  5061. + if (ctrl->use_hw_closed_loop && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
  5062. + rc = regulator_enable(ctrl->vdd_limit_regulator);
  5063. + if (rc) {
  5064. + cpr3_err(ctrl, "CPR limit regulator enable failed, rc=%d\n",
  5065. + rc);
  5066. + goto done;
  5067. + }
  5068. + } else if (!ctrl->use_hw_closed_loop
  5069. + && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
  5070. + rc = regulator_disable(ctrl->vdd_limit_regulator);
  5071. + if (rc) {
  5072. + cpr3_err(ctrl, "CPR limit regulator disable failed, rc=%d\n",
  5073. + rc);
  5074. + goto done;
  5075. + }
  5076. + }
  5077. +
  5078. + /*
  5079. + * Due to APM and mem-acc floor restriction constraints,
  5080. + * the closed-loop voltage may be different when using
  5081. + * software closed-loop vs hardware closed-loop. Therefore,
  5082. + * reset the cached closed-loop voltage for all corners to the
  5083. + * corresponding open-loop voltage when switching between
  5084. + * SW and HW closed-loop mode.
  5085. + */
  5086. + for (i = 0; i < ctrl->thread_count; i++) {
  5087. + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
  5088. + vreg = &ctrl->thread[i].vreg[j];
  5089. + for (k = 0; k < vreg->corner_count; k++)
  5090. + vreg->corner[k].last_volt
  5091. + = vreg->corner[k].open_loop_volt;
  5092. + }
  5093. + }
  5094. +
  5095. + /* Skip last_volt caching */
  5096. + ctrl->last_corner_was_closed_loop = false;
  5097. +
  5098. + rc = cpr3_regulator_update_ctrl_state(ctrl);
  5099. + if (rc) {
  5100. + cpr3_err(ctrl, "could not change CPR HW closed-loop enable state=%u, rc=%d\n",
  5101. + use_hw_closed_loop, rc);
  5102. + goto done;
  5103. + }
  5104. +
  5105. + cpr3_debug(ctrl, "CPR mode=%s\n",
  5106. + use_hw_closed_loop ?
  5107. + "HW closed-loop" : "SW closed-loop");
  5108. +done:
  5109. + mutex_unlock(&ctrl->lock);
  5110. + return 0;
  5111. +}
  5112. +
  5113. +/**
  5114. + * cpr3_debug_hw_closed_loop_enable_get() - debugfs callback used to retrieve
  5115. + * the value of the CPR controller use_hw_closed_loop flag which
  5116. + * indicates if hardware closed-loop operation is being used in
  5117. + * place of software closed-loop operation
  5118. + * @data: Pointer to private data which is equal to the CPR
  5119. + * controller pointer
  5120. + * @val: Output parameter written with the value of
  5121. + * use_hw_closed_loop
  5122. + *
  5123. + * Return: 0 on success, errno on failure
  5124. + */
  5125. +static int cpr3_debug_hw_closed_loop_enable_get(void *data, u64 *val)
  5126. +{
  5127. + struct cpr3_controller *ctrl = data;
  5128. +
  5129. + *val = ctrl->use_hw_closed_loop;
  5130. +
  5131. + return 0;
  5132. +}
  5133. +DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_hw_closed_loop_enable_fops,
  5134. + cpr3_debug_hw_closed_loop_enable_get,
  5135. + cpr3_debug_hw_closed_loop_enable_set,
  5136. + "%llu\n");
  5137. +
  5138. +/**
  5139. + * cpr3_debug_trigger_aging_measurement_set() - debugfs callback used to trigger
  5140. + * another CPR measurement
  5141. + * @data: Pointer to private data which is equal to the CPR
  5142. + * controller pointer
  5143. + * @val: Unused
  5144. + *
  5145. + * Return: 0 on success, errno on failure
  5146. + */
  5147. +static int cpr3_debug_trigger_aging_measurement_set(void *data, u64 val)
  5148. +{
  5149. + struct cpr3_controller *ctrl = data;
  5150. + int rc;
  5151. +
  5152. + mutex_lock(&ctrl->lock);
  5153. +
  5154. + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
  5155. + rc = cpr3_ctrl_clear_cpr4_config(ctrl);
  5156. + if (rc) {
  5157. + cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
  5158. + rc);
  5159. + goto done;
  5160. + }
  5161. + }
  5162. +
  5163. + cpr3_ctrl_loop_disable(ctrl);
  5164. +
  5165. + cpr3_regulator_set_aging_ref_adjustment(ctrl, INT_MAX);
  5166. + ctrl->aging_required = true;
  5167. + ctrl->aging_succeeded = false;
  5168. + ctrl->aging_failed = false;
  5169. +
  5170. + rc = cpr3_regulator_update_ctrl_state(ctrl);
  5171. + if (rc) {
  5172. + cpr3_err(ctrl, "could not update the CPR controller state, rc=%d\n",
  5173. + rc);
  5174. + goto done;
  5175. + }
  5176. +
  5177. +done:
  5178. + mutex_unlock(&ctrl->lock);
  5179. + return 0;
  5180. +}
  5181. +DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_trigger_aging_measurement_fops,
  5182. + NULL,
  5183. + cpr3_debug_trigger_aging_measurement_set,
  5184. + "%llu\n");
  5185. +
  5186. +/**
  5187. + * cpr3_regulator_debugfs_ctrl_add() - add debugfs files to expose configuration
  5188. + * data for the CPR controller
  5189. + * @ctrl: Pointer to the CPR3 controller
  5190. + *
  5191. + * Return: none
  5192. + */
  5193. +static void cpr3_regulator_debugfs_ctrl_add(struct cpr3_controller *ctrl)
  5194. +{
  5195. + struct dentry *temp, *aggr_dir;
  5196. + int i;
  5197. +
  5198. + /* Add cpr3-regulator base directory if it isn't present already. */
  5199. + if (cpr3_debugfs_base == NULL) {
  5200. + cpr3_debugfs_base = debugfs_create_dir("cpr3-regulator", NULL);
  5201. + if (IS_ERR_OR_NULL(cpr3_debugfs_base)) {
  5202. + cpr3_err(ctrl, "cpr3-regulator debugfs base directory creation failed\n");
  5203. + cpr3_debugfs_base = NULL;
  5204. + return;
  5205. + }
  5206. + }
  5207. +
  5208. + ctrl->debugfs = debugfs_create_dir(ctrl->name, cpr3_debugfs_base);
  5209. + if (IS_ERR_OR_NULL(ctrl->debugfs)) {
  5210. + cpr3_err(ctrl, "cpr3-regulator controller debugfs directory creation failed\n");
  5211. + return;
  5212. + }
  5213. +
  5214. + temp = debugfs_create_file("cpr_closed_loop_enable", S_IRUGO | S_IWUSR,
  5215. + ctrl->debugfs, ctrl,
  5216. + &cpr3_debug_closed_loop_enable_fops);
  5217. + if (IS_ERR_OR_NULL(temp)) {
  5218. + cpr3_err(ctrl, "cpr_closed_loop_enable debugfs file creation failed\n");
  5219. + return;
  5220. + }
  5221. +
  5222. + if (ctrl->supports_hw_closed_loop) {
  5223. + temp = debugfs_create_file("use_hw_closed_loop",
  5224. + S_IRUGO | S_IWUSR, ctrl->debugfs, ctrl,
  5225. + &cpr3_debug_hw_closed_loop_enable_fops);
  5226. + if (IS_ERR_OR_NULL(temp)) {
  5227. + cpr3_err(ctrl, "use_hw_closed_loop debugfs file creation failed\n");
  5228. + return;
  5229. + }
  5230. + }
  5231. +
  5232. + temp = debugfs_create_int("thread_count", S_IRUGO, ctrl->debugfs,
  5233. + &ctrl->thread_count);
  5234. + if (IS_ERR_OR_NULL(temp)) {
  5235. + cpr3_err(ctrl, "thread_count debugfs file creation failed\n");
  5236. + return;
  5237. + }
  5238. +
  5239. + if (ctrl->apm) {
  5240. + temp = debugfs_create_int("apm_threshold_volt", S_IRUGO,
  5241. + ctrl->debugfs, &ctrl->apm_threshold_volt);
  5242. + if (IS_ERR_OR_NULL(temp)) {
  5243. + cpr3_err(ctrl, "apm_threshold_volt debugfs file creation failed\n");
  5244. + return;
  5245. + }
  5246. + }
  5247. +
  5248. + if (ctrl->aging_required || ctrl->aging_succeeded
  5249. + || ctrl->aging_failed) {
  5250. + temp = debugfs_create_int("aging_adj_volt", S_IRUGO,
  5251. + ctrl->debugfs, &ctrl->aging_ref_adjust_volt);
  5252. + if (IS_ERR_OR_NULL(temp)) {
  5253. + cpr3_err(ctrl, "aging_adj_volt debugfs file creation failed\n");
  5254. + return;
  5255. + }
  5256. +
  5257. + temp = debugfs_create_file("aging_succeeded", S_IRUGO,
  5258. + ctrl->debugfs, &ctrl->aging_succeeded, &fops_bool_ro);
  5259. + if (IS_ERR_OR_NULL(temp)) {
  5260. + cpr3_err(ctrl, "aging_succeeded debugfs file creation failed\n");
  5261. + return;
  5262. + }
  5263. +
  5264. + temp = debugfs_create_file("aging_failed", S_IRUGO,
  5265. + ctrl->debugfs, &ctrl->aging_failed, &fops_bool_ro);
  5266. + if (IS_ERR_OR_NULL(temp)) {
  5267. + cpr3_err(ctrl, "aging_failed debugfs file creation failed\n");
  5268. + return;
  5269. + }
  5270. +
  5271. + temp = debugfs_create_file("aging_trigger", S_IWUSR,
  5272. + ctrl->debugfs, ctrl,
  5273. + &cpr3_debug_trigger_aging_measurement_fops);
  5274. + if (IS_ERR_OR_NULL(temp)) {
  5275. + cpr3_err(ctrl, "aging_trigger debugfs file creation failed\n");
  5276. + return;
  5277. + }
  5278. + }
  5279. +
  5280. + aggr_dir = debugfs_create_dir("max_aggregated_voltages", ctrl->debugfs);
  5281. + if (IS_ERR_OR_NULL(aggr_dir)) {
  5282. + cpr3_err(ctrl, "max_aggregated_voltages debugfs directory creation failed\n");
  5283. + return;
  5284. + }
  5285. +
  5286. + temp = debugfs_create_int("floor_volt", S_IRUGO, aggr_dir,
  5287. + &ctrl->aggr_corner.floor_volt);
  5288. + if (IS_ERR_OR_NULL(temp)) {
  5289. + cpr3_err(ctrl, "aggr floor_volt debugfs file creation failed\n");
  5290. + return;
  5291. + }
  5292. +
  5293. + temp = debugfs_create_int("ceiling_volt", S_IRUGO, aggr_dir,
  5294. + &ctrl->aggr_corner.ceiling_volt);
  5295. + if (IS_ERR_OR_NULL(temp)) {
  5296. + cpr3_err(ctrl, "aggr ceiling_volt debugfs file creation failed\n");
  5297. + return;
  5298. + }
  5299. +
  5300. + temp = debugfs_create_int("open_loop_volt", S_IRUGO, aggr_dir,
  5301. + &ctrl->aggr_corner.open_loop_volt);
  5302. + if (IS_ERR_OR_NULL(temp)) {
  5303. + cpr3_err(ctrl, "aggr open_loop_volt debugfs file creation failed\n");
  5304. + return;
  5305. + }
  5306. +
  5307. + temp = debugfs_create_int("last_volt", S_IRUGO, aggr_dir,
  5308. + &ctrl->aggr_corner.last_volt);
  5309. + if (IS_ERR_OR_NULL(temp)) {
  5310. + cpr3_err(ctrl, "aggr last_volt debugfs file creation failed\n");
  5311. + return;
  5312. + }
  5313. +
  5314. + for (i = 0; i < ctrl->thread_count; i++)
  5315. + cpr3_regulator_debugfs_thread_add(&ctrl->thread[i]);
  5316. +}
  5317. +
  5318. +/**
  5319. + * cpr3_regulator_debugfs_ctrl_remove() - remove debugfs files for the CPR
  5320. + * controller
  5321. + * @ctrl: Pointer to the CPR3 controller
  5322. + *
  5323. + * Note, this function must be called after the controller has been removed from
  5324. + * cpr3_controller_list and while the cpr3_controller_list_mutex lock is held.
  5325. + *
  5326. + * Return: none
  5327. + */
  5328. +static void cpr3_regulator_debugfs_ctrl_remove(struct cpr3_controller *ctrl)
  5329. +{
  5330. + if (list_empty(&cpr3_controller_list)) {
  5331. + debugfs_remove_recursive(cpr3_debugfs_base);
  5332. + cpr3_debugfs_base = NULL;
  5333. + } else {
  5334. + debugfs_remove_recursive(ctrl->debugfs);
  5335. + }
  5336. +}
  5337. +
  5338. +/**
  5339. + * cpr3_regulator_init_ctrl_data() - performs initialization of CPR controller
  5340. + * elements
  5341. + * @ctrl: Pointer to the CPR3 controller
  5342. + *
  5343. + * Return: 0 on success, errno on failure
  5344. + */
  5345. +static int cpr3_regulator_init_ctrl_data(struct cpr3_controller *ctrl)
  5346. +{
  5347. + /* Read the initial vdd voltage from hardware. */
  5348. + ctrl->aggr_corner.last_volt
  5349. + = regulator_get_voltage(ctrl->vdd_regulator);
  5350. + if (ctrl->aggr_corner.last_volt < 0) {
  5351. + cpr3_err(ctrl, "regulator_get_voltage(vdd) failed, rc=%d\n",
  5352. + ctrl->aggr_corner.last_volt);
  5353. + return ctrl->aggr_corner.last_volt;
  5354. + }
  5355. + ctrl->aggr_corner.open_loop_volt = ctrl->aggr_corner.last_volt;
  5356. +
  5357. + return 0;
  5358. +}
  5359. +
  5360. +/**
  5361. + * cpr3_regulator_init_vreg_data() - performs initialization of common CPR3
  5362. + * regulator elements and validate aging configurations
  5363. + * @vreg: Pointer to the CPR3 regulator
  5364. + *
  5365. + * Return: 0 on success, errno on failure
  5366. + */
  5367. +static int cpr3_regulator_init_vreg_data(struct cpr3_regulator *vreg)
  5368. +{
  5369. + int i, j;
  5370. + bool init_aging;
  5371. +
  5372. + vreg->current_corner = CPR3_REGULATOR_CORNER_INVALID;
  5373. + vreg->last_closed_loop_corner = CPR3_REGULATOR_CORNER_INVALID;
  5374. +
  5375. + init_aging = vreg->aging_allowed && vreg->thread->ctrl->aging_required;
  5376. +
  5377. + for (i = 0; i < vreg->corner_count; i++) {
  5378. + vreg->corner[i].last_volt = vreg->corner[i].open_loop_volt;
  5379. + vreg->corner[i].irq_en = CPR3_IRQ_UP | CPR3_IRQ_DOWN;
  5380. +
  5381. + vreg->corner[i].ro_mask = 0;
  5382. + for (j = 0; j < CPR3_RO_COUNT; j++) {
  5383. + if (vreg->corner[i].target_quot[j] == 0)
  5384. + vreg->corner[i].ro_mask |= BIT(j);
  5385. + }
  5386. +
  5387. + if (init_aging) {
  5388. + vreg->corner[i].unaged_floor_volt
  5389. + = vreg->corner[i].floor_volt;
  5390. + vreg->corner[i].unaged_ceiling_volt
  5391. + = vreg->corner[i].ceiling_volt;
  5392. + vreg->corner[i].unaged_open_loop_volt
  5393. + = vreg->corner[i].open_loop_volt;
  5394. + }
  5395. +
  5396. + if (vreg->aging_allowed) {
  5397. + if (vreg->corner[i].unaged_floor_volt <= 0) {
  5398. + cpr3_err(vreg, "invalid unaged_floor_volt[%d] = %d\n",
  5399. + i, vreg->corner[i].unaged_floor_volt);
  5400. + return -EINVAL;
  5401. + }
  5402. + if (vreg->corner[i].unaged_ceiling_volt <= 0) {
  5403. + cpr3_err(vreg, "invalid unaged_ceiling_volt[%d] = %d\n",
  5404. + i, vreg->corner[i].unaged_ceiling_volt);
  5405. + return -EINVAL;
  5406. + }
  5407. + if (vreg->corner[i].unaged_open_loop_volt <= 0) {
  5408. + cpr3_err(vreg, "invalid unaged_open_loop_volt[%d] = %d\n",
  5409. + i, vreg->corner[i].unaged_open_loop_volt);
  5410. + return -EINVAL;
  5411. + }
  5412. + }
  5413. + }
  5414. +
  5415. + if (vreg->aging_allowed && vreg->corner[vreg->aging_corner].ceiling_volt
  5416. + > vreg->thread->ctrl->aging_ref_volt) {
  5417. + cpr3_err(vreg, "aging corner %d ceiling voltage = %d > aging ref voltage = %d uV\n",
  5418. + vreg->aging_corner,
  5419. + vreg->corner[vreg->aging_corner].ceiling_volt,
  5420. + vreg->thread->ctrl->aging_ref_volt);
  5421. + return -EINVAL;
  5422. + }
  5423. +
  5424. + return 0;
  5425. +}
  5426. +
  5427. +/**
  5428. + * cpr3_regulator_suspend() - perform common required CPR3 power down steps
  5429. + * before the system enters suspend
  5430. + * @ctrl: Pointer to the CPR3 controller
  5431. + *
  5432. + * Return: 0 on success, errno on failure
  5433. + */
  5434. +int cpr3_regulator_suspend(struct cpr3_controller *ctrl)
  5435. +{
  5436. + int rc;
  5437. +
  5438. + mutex_lock(&ctrl->lock);
  5439. +
  5440. + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
  5441. + rc = cpr3_ctrl_clear_cpr4_config(ctrl);
  5442. + if (rc) {
  5443. + cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
  5444. + rc);
  5445. + mutex_unlock(&ctrl->lock);
  5446. + return rc;
  5447. + }
  5448. + }
  5449. +
  5450. + cpr3_ctrl_loop_disable(ctrl);
  5451. +
  5452. + rc = cpr3_closed_loop_disable(ctrl);
  5453. + if (rc)
  5454. + cpr3_err(ctrl, "could not disable CPR, rc=%d\n", rc);
  5455. +
  5456. + ctrl->cpr_suspended = true;
  5457. +
  5458. + mutex_unlock(&ctrl->lock);
  5459. + return 0;
  5460. +}
  5461. +
  5462. +/**
  5463. + * cpr3_regulator_resume() - perform common required CPR3 power up steps after
  5464. + * the system resumes from suspend
  5465. + * @ctrl: Pointer to the CPR3 controller
  5466. + *
  5467. + * Return: 0 on success, errno on failure
  5468. + */
  5469. +int cpr3_regulator_resume(struct cpr3_controller *ctrl)
  5470. +{
  5471. + int rc;
  5472. +
  5473. + mutex_lock(&ctrl->lock);
  5474. +
  5475. + ctrl->cpr_suspended = false;
  5476. + rc = cpr3_regulator_update_ctrl_state(ctrl);
  5477. + if (rc)
  5478. + cpr3_err(ctrl, "could not enable CPR, rc=%d\n", rc);
  5479. +
  5480. + mutex_unlock(&ctrl->lock);
  5481. + return 0;
  5482. +}
  5483. +
  5484. +/**
  5485. + * cpr3_regulator_validate_controller() - verify the data passed in via the
  5486. + * cpr3_controller data structure
  5487. + * @ctrl: Pointer to the CPR3 controller
  5488. + *
  5489. + * Return: 0 on success, errno on failure
  5490. + */
  5491. +static int cpr3_regulator_validate_controller(struct cpr3_controller *ctrl)
  5492. +{
  5493. + struct cpr3_thread *thread;
  5494. + struct cpr3_regulator *vreg;
  5495. + int i, j, allow_boost_vreg_count = 0;
  5496. +
  5497. + if (!ctrl->vdd_regulator) {
  5498. + cpr3_err(ctrl, "vdd regulator missing\n");
  5499. + return -EINVAL;
  5500. + } else if (ctrl->sensor_count <= 0
  5501. + || ctrl->sensor_count > CPR3_MAX_SENSOR_COUNT) {
  5502. + cpr3_err(ctrl, "invalid CPR sensor count=%d\n",
  5503. + ctrl->sensor_count);
  5504. + return -EINVAL;
  5505. + } else if (!ctrl->sensor_owner) {
  5506. + cpr3_err(ctrl, "CPR sensor ownership table missing\n");
  5507. + return -EINVAL;
  5508. + }
  5509. +
  5510. + if (ctrl->aging_required) {
  5511. + for (i = 0; i < ctrl->aging_sensor_count; i++) {
  5512. + if (ctrl->aging_sensor[i].sensor_id
  5513. + >= ctrl->sensor_count) {
  5514. + cpr3_err(ctrl, "aging_sensor[%d] id=%u is not in the value range 0-%d",
  5515. + i, ctrl->aging_sensor[i].sensor_id,
  5516. + ctrl->sensor_count - 1);
  5517. + return -EINVAL;
  5518. + }
  5519. + }
  5520. + }
  5521. +
  5522. + for (i = 0; i < ctrl->thread_count; i++) {
  5523. + thread = &ctrl->thread[i];
  5524. + for (j = 0; j < thread->vreg_count; j++) {
  5525. + vreg = &thread->vreg[j];
  5526. + if (vreg->allow_boost)
  5527. + allow_boost_vreg_count++;
  5528. + }
  5529. + }
  5530. +
  5531. + if (allow_boost_vreg_count > 1) {
  5532. + /*
  5533. + * Boost feature is not allowed to be used for more
  5534. + * than one CPR3 regulator of a CPR3 controller.
  5535. + */
  5536. + cpr3_err(ctrl, "Boost feature is enabled for more than one regulator\n");
  5537. + return -EINVAL;
  5538. + }
  5539. +
  5540. + return 0;
  5541. +}
  5542. +
  5543. +/**
  5544. + * cpr3_panic_callback() - panic notification callback function. This function
  5545. + * is invoked when a kernel panic occurs.
  5546. + * @nfb: Notifier block pointer of CPR3 controller
  5547. + * @event: Value passed unmodified to notifier function
  5548. + * @data: Pointer passed unmodified to notifier function
  5549. + *
  5550. + * Return: NOTIFY_OK
  5551. + */
  5552. +static int cpr3_panic_callback(struct notifier_block *nfb,
  5553. + unsigned long event, void *data)
  5554. +{
  5555. + struct cpr3_controller *ctrl = container_of(nfb,
  5556. + struct cpr3_controller, panic_notifier);
  5557. + struct cpr3_panic_regs_info *regs_info = ctrl->panic_regs_info;
  5558. + struct cpr3_reg_info *reg;
  5559. + int i = 0;
  5560. +
  5561. + for (i = 0; i < regs_info->reg_count; i++) {
  5562. + reg = &(regs_info->regs[i]);
  5563. + reg->value = readl_relaxed(reg->virt_addr);
  5564. + pr_err("%s[0x%08x] = 0x%08x\n", reg->name, reg->addr,
  5565. + reg->value);
  5566. + }
  5567. + /*
  5568. + * Barrier to ensure that the information has been updated in the
  5569. + * structure.
  5570. + */
  5571. + mb();
  5572. +
  5573. + return NOTIFY_OK;
  5574. +}
  5575. +
  5576. +/**
  5577. + * cpr3_regulator_register() - register the regulators for a CPR3 controller and
  5578. + * perform CPR hardware initialization
  5579. + * @pdev: Platform device pointer for the CPR3 controller
  5580. + * @ctrl: Pointer to the CPR3 controller
  5581. + *
  5582. + * Return: 0 on success, errno on failure
  5583. + */
  5584. +int cpr3_regulator_register(struct platform_device *pdev,
  5585. + struct cpr3_controller *ctrl)
  5586. +{
  5587. + struct device *dev = &pdev->dev;
  5588. + struct resource *res;
  5589. + int i, j, rc;
  5590. +
  5591. + if (!dev->of_node) {
  5592. + dev_err(dev, "%s: Device tree node is missing\n", __func__);
  5593. + return -EINVAL;
  5594. + }
  5595. +
  5596. + if (!ctrl || !ctrl->name) {
  5597. + dev_err(dev, "%s: CPR controller data is missing\n", __func__);
  5598. + return -EINVAL;
  5599. + }
  5600. +
  5601. + rc = cpr3_regulator_validate_controller(ctrl);
  5602. + if (rc) {
  5603. + cpr3_err(ctrl, "controller validation failed, rc=%d\n", rc);
  5604. + return rc;
  5605. + }
  5606. +
  5607. + mutex_init(&ctrl->lock);
  5608. +
  5609. + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cpr_ctrl");
  5610. + if (!res || !res->start) {
  5611. + cpr3_err(ctrl, "CPR controller address is missing\n");
  5612. + return -ENXIO;
  5613. + }
  5614. + ctrl->cpr_ctrl_base = devm_ioremap(dev, res->start, resource_size(res));
  5615. +
  5616. + if (ctrl->aging_possible_mask) {
  5617. + /*
  5618. + * Aging possible register address is required if an aging
  5619. + * possible mask has been specified.
  5620. + */
  5621. + res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
  5622. + "aging_allowed");
  5623. + if (!res || !res->start) {
  5624. + cpr3_err(ctrl, "CPR aging allowed address is missing\n");
  5625. + return -ENXIO;
  5626. + }
  5627. + ctrl->aging_possible_reg = devm_ioremap(dev, res->start,
  5628. + resource_size(res));
  5629. + }
  5630. +
  5631. + ctrl->irq = platform_get_irq_byname(pdev, "cpr");
  5632. + if (ctrl->irq < 0) {
  5633. + cpr3_err(ctrl, "missing CPR interrupt\n");
  5634. + return ctrl->irq;
  5635. + }
  5636. +
  5637. + if (ctrl->supports_hw_closed_loop) {
  5638. + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
  5639. + ctrl->ceiling_irq = platform_get_irq_byname(pdev,
  5640. + "ceiling");
  5641. + if (ctrl->ceiling_irq < 0) {
  5642. + cpr3_err(ctrl, "missing ceiling interrupt\n");
  5643. + return ctrl->ceiling_irq;
  5644. + }
  5645. + }
  5646. + }
  5647. +
  5648. + rc = cpr3_regulator_init_ctrl_data(ctrl);
  5649. + if (rc) {
  5650. + cpr3_err(ctrl, "CPR controller data initialization failed, rc=%d\n",
  5651. + rc);
  5652. + return rc;
  5653. + }
  5654. +
  5655. + for (i = 0; i < ctrl->thread_count; i++) {
  5656. + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
  5657. + rc = cpr3_regulator_init_vreg_data(
  5658. + &ctrl->thread[i].vreg[j]);
  5659. + if (rc)
  5660. + return rc;
  5661. + cpr3_print_quots(&ctrl->thread[i].vreg[j]);
  5662. + }
  5663. + }
  5664. +
  5665. + /*
  5666. + * Add the maximum possible aging voltage margin until it is possible
  5667. + * to perform an aging measurement.
  5668. + */
  5669. + if (ctrl->aging_required)
  5670. + cpr3_regulator_set_aging_ref_adjustment(ctrl, INT_MAX);
  5671. +
  5672. + rc = cpr3_regulator_init_ctrl(ctrl);
  5673. + if (rc) {
  5674. + cpr3_err(ctrl, "CPR controller initialization failed, rc=%d\n",
  5675. + rc);
  5676. + return rc;
  5677. + }
  5678. +
  5679. + /* Register regulator devices for all threads. */
  5680. + for (i = 0; i < ctrl->thread_count; i++) {
  5681. + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
  5682. + rc = cpr3_regulator_vreg_register(
  5683. + &ctrl->thread[i].vreg[j]);
  5684. + if (rc) {
  5685. + cpr3_err(&ctrl->thread[i].vreg[j], "failed to register regulator, rc=%d\n",
  5686. + rc);
  5687. + goto free_regulators;
  5688. + }
  5689. + }
  5690. + }
  5691. +
  5692. + rc = devm_request_threaded_irq(dev, ctrl->irq, NULL,
  5693. + cpr3_irq_handler,
  5694. + IRQF_ONESHOT |
  5695. + IRQF_TRIGGER_RISING,
  5696. + "cpr3", ctrl);
  5697. + if (rc) {
  5698. + cpr3_err(ctrl, "could not request IRQ %d, rc=%d\n",
  5699. + ctrl->irq, rc);
  5700. + goto free_regulators;
  5701. + }
  5702. +
  5703. + if (ctrl->supports_hw_closed_loop &&
  5704. + ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
  5705. + rc = devm_request_threaded_irq(dev, ctrl->ceiling_irq, NULL,
  5706. + cpr3_ceiling_irq_handler,
  5707. + IRQF_ONESHOT | IRQF_TRIGGER_RISING,
  5708. + "cpr3_ceiling", ctrl);
  5709. + if (rc) {
  5710. + cpr3_err(ctrl, "could not request ceiling IRQ %d, rc=%d\n",
  5711. + ctrl->ceiling_irq, rc);
  5712. + goto free_regulators;
  5713. + }
  5714. + }
  5715. +
  5716. + mutex_lock(&cpr3_controller_list_mutex);
  5717. + cpr3_regulator_debugfs_ctrl_add(ctrl);
  5718. + list_add(&ctrl->list, &cpr3_controller_list);
  5719. + mutex_unlock(&cpr3_controller_list_mutex);
  5720. +
  5721. + if (ctrl->panic_regs_info) {
  5722. + /* Register panic notification call back */
  5723. + ctrl->panic_notifier.notifier_call = cpr3_panic_callback;
  5724. + atomic_notifier_chain_register(&panic_notifier_list,
  5725. + &ctrl->panic_notifier);
  5726. + }
  5727. +
  5728. + return 0;
  5729. +
  5730. +free_regulators:
  5731. + for (i = 0; i < ctrl->thread_count; i++)
  5732. + for (j = 0; j < ctrl->thread[i].vreg_count; j++)
  5733. + if (!IS_ERR_OR_NULL(ctrl->thread[i].vreg[j].rdev))
  5734. + regulator_unregister(
  5735. + ctrl->thread[i].vreg[j].rdev);
  5736. + return rc;
  5737. +}
  5738. +
  5739. +/**
  5740. + * cpr3_open_loop_regulator_register() - register the regulators for a CPR3
  5741. + * controller which will always work in Open loop and
  5742. + * won't support close loop.
  5743. + * @pdev: Platform device pointer for the CPR3 controller
  5744. + * @ctrl: Pointer to the CPR3 controller
  5745. + *
  5746. + * Return: 0 on success, errno on failure
  5747. + */
  5748. +int cpr3_open_loop_regulator_register(struct platform_device *pdev,
  5749. + struct cpr3_controller *ctrl)
  5750. +{
  5751. + struct device *dev = &pdev->dev;
  5752. + struct cpr3_regulator *vreg;
  5753. + int i, j, rc;
  5754. +
  5755. + if (!dev->of_node) {
  5756. + dev_err(dev, "%s: Device tree node is missing\n", __func__);
  5757. + return -EINVAL;
  5758. + }
  5759. +
  5760. + if (!ctrl || !ctrl->name) {
  5761. + dev_err(dev, "%s: CPR controller data is missing\n", __func__);
  5762. + return -EINVAL;
  5763. + }
  5764. +
  5765. + if (!ctrl->vdd_regulator) {
  5766. + cpr3_err(ctrl, "vdd regulator missing\n");
  5767. + return -EINVAL;
  5768. + }
  5769. +
  5770. + mutex_init(&ctrl->lock);
  5771. +
  5772. + rc = cpr3_regulator_init_ctrl_data(ctrl);
  5773. + if (rc) {
  5774. + cpr3_err(ctrl, "CPR controller data initialization failed, rc=%d\n",
  5775. + rc);
  5776. + return rc;
  5777. + }
  5778. +
  5779. + for (i = 0; i < ctrl->thread_count; i++) {
  5780. + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
  5781. + vreg = &ctrl->thread[i].vreg[j];
  5782. + vreg->corner[i].last_volt =
  5783. + vreg->corner[i].open_loop_volt;
  5784. + }
  5785. + }
  5786. +
  5787. + /* Register regulator devices for all threads. */
  5788. + for (i = 0; i < ctrl->thread_count; i++) {
  5789. + for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
  5790. + rc = cpr3_regulator_vreg_register(
  5791. + &ctrl->thread[i].vreg[j]);
  5792. + if (rc) {
  5793. + cpr3_err(&ctrl->thread[i].vreg[j], "failed to register regulator, rc=%d\n",
  5794. + rc);
  5795. + goto free_regulators;
  5796. + }
  5797. + }
  5798. + }
  5799. +
  5800. + mutex_lock(&cpr3_controller_list_mutex);
  5801. + list_add(&ctrl->list, &cpr3_controller_list);
  5802. + mutex_unlock(&cpr3_controller_list_mutex);
  5803. +
  5804. + return 0;
  5805. +
  5806. +free_regulators:
  5807. + for (i = 0; i < ctrl->thread_count; i++)
  5808. + for (j = 0; j < ctrl->thread[i].vreg_count; j++)
  5809. + if (!IS_ERR_OR_NULL(ctrl->thread[i].vreg[j].rdev))
  5810. + regulator_unregister(
  5811. + ctrl->thread[i].vreg[j].rdev);
  5812. + return rc;
  5813. +}
  5814. +
  5815. +/**
  5816. + * cpr3_regulator_unregister() - unregister the regulators for a CPR3 controller
  5817. + * and perform CPR hardware shutdown
  5818. + * @ctrl: Pointer to the CPR3 controller
  5819. + *
  5820. + * Return: 0 on success, errno on failure
  5821. + */
  5822. +int cpr3_regulator_unregister(struct cpr3_controller *ctrl)
  5823. +{
  5824. + int i, j, rc = 0;
  5825. +
  5826. + mutex_lock(&cpr3_controller_list_mutex);
  5827. + list_del(&ctrl->list);
  5828. + cpr3_regulator_debugfs_ctrl_remove(ctrl);
  5829. + mutex_unlock(&cpr3_controller_list_mutex);
  5830. +
  5831. + if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
  5832. + rc = cpr3_ctrl_clear_cpr4_config(ctrl);
  5833. + if (rc)
  5834. + cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
  5835. + rc);
  5836. + }
  5837. +
  5838. + cpr3_ctrl_loop_disable(ctrl);
  5839. +
  5840. + cpr3_closed_loop_disable(ctrl);
  5841. +
  5842. + if (ctrl->vdd_limit_regulator) {
  5843. + regulator_disable(ctrl->vdd_limit_regulator);
  5844. + }
  5845. +
  5846. + for (i = 0; i < ctrl->thread_count; i++)
  5847. + for (j = 0; j < ctrl->thread[i].vreg_count; j++)
  5848. + regulator_unregister(ctrl->thread[i].vreg[j].rdev);
  5849. +
  5850. + if (ctrl->panic_notifier.notifier_call)
  5851. + atomic_notifier_chain_unregister(&panic_notifier_list,
  5852. + &ctrl->panic_notifier);
  5853. +
  5854. + return 0;
  5855. +}
  5856. +
  5857. +/**
  5858. + * cpr3_open_loop_regulator_unregister() - unregister the regulators for a CPR3
  5859. + * open loop controller and perform CPR hardware shutdown
  5860. + * @ctrl: Pointer to the CPR3 controller
  5861. + *
  5862. + * Return: 0 on success, errno on failure
  5863. + */
  5864. +int cpr3_open_loop_regulator_unregister(struct cpr3_controller *ctrl)
  5865. +{
  5866. + int i, j;
  5867. +
  5868. + mutex_lock(&cpr3_controller_list_mutex);
  5869. + list_del(&ctrl->list);
  5870. + mutex_unlock(&cpr3_controller_list_mutex);
  5871. +
  5872. + if (ctrl->vdd_limit_regulator) {
  5873. + regulator_disable(ctrl->vdd_limit_regulator);
  5874. + }
  5875. +
  5876. + for (i = 0; i < ctrl->thread_count; i++)
  5877. + for (j = 0; j < ctrl->thread[i].vreg_count; j++)
  5878. + regulator_unregister(ctrl->thread[i].vreg[j].rdev);
  5879. +
  5880. + if (ctrl->panic_notifier.notifier_call)
  5881. + atomic_notifier_chain_unregister(&panic_notifier_list,
  5882. + &ctrl->panic_notifier);
  5883. +
  5884. + return 0;
  5885. +}
  5886. --- /dev/null
  5887. +++ b/drivers/regulator/cpr3-regulator.h
  5888. @@ -0,0 +1,1211 @@
  5889. +/*
  5890. + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
  5891. + *
  5892. + * This program is free software; you can redistribute it and/or modify
  5893. + * it under the terms of the GNU General Public License version 2 and
  5894. + * only version 2 as published by the Free Software Foundation.
  5895. + *
  5896. + * This program is distributed in the hope that it will be useful,
  5897. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5898. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  5899. + * GNU General Public License for more details.
  5900. + */
  5901. +
  5902. +#ifndef __REGULATOR_CPR3_REGULATOR_H__
  5903. +#define __REGULATOR_CPR3_REGULATOR_H__
  5904. +
  5905. +#include <linux/clk.h>
  5906. +#include <linux/mutex.h>
  5907. +#include <linux/of.h>
  5908. +#include <linux/platform_device.h>
  5909. +#include <linux/types.h>
  5910. +#include <linux/power/qcom/apm.h>
  5911. +#include <linux/regulator/driver.h>
  5912. +
  5913. +struct cpr3_controller;
  5914. +struct cpr3_thread;
  5915. +
  5916. +/**
  5917. + * struct cpr3_fuse_param - defines one contiguous segment of a fuse parameter
  5918. + * that is contained within a given row.
  5919. + * @row: Fuse row number
  5920. + * @bit_start: The first bit within the row of the fuse parameter segment
  5921. + * @bit_end: The last bit within the row of the fuse parameter segment
  5922. + *
  5923. + * Each fuse row is 64 bits in length. bit_start and bit_end may take values
  5924. + * from 0 to 63. bit_start must be less than or equal to bit_end.
  5925. + */
  5926. +struct cpr3_fuse_param {
  5927. + unsigned row;
  5928. + unsigned bit_start;
  5929. + unsigned bit_end;
  5930. +};
  5931. +
  5932. +/* Each CPR3 sensor has 16 ring oscillators */
  5933. +#define CPR3_RO_COUNT 16
  5934. +
  5935. +/* The maximum number of sensors that can be present on a single CPR loop. */
  5936. +#define CPR3_MAX_SENSOR_COUNT 256
  5937. +
  5938. +/* This constant is used when allocating array printing buffers. */
  5939. +#define MAX_CHARS_PER_INT 10
  5940. +
  5941. +/**
  5942. + * struct cpr4_sdelta - CPR4 controller specific data structure for the sdelta
  5943. + * adjustment table which is used to adjust the VDD supply
  5944. + * voltage automatically based upon the temperature and/or
  5945. + * the number of online CPU cores.
  5946. + * @allow_core_count_adj: Core count adjustments are allowed.
  5947. + * @allow_temp_adj: Temperature based adjustments are allowed.
  5948. + * @max_core_count: Maximum number of cores considered for core count
  5949. + * adjustment logic.
  5950. + * @temp_band_count: Number of temperature bands considered for temperature
  5951. + * based adjustment logic.
  5952. + * @cap_volt: CAP in uV to apply to SDELTA margins with multiple
  5953. + * cpr3-regulators defined for single controller.
  5954. + * @table: SDELTA table with per-online-core and temperature based
  5955. + * adjustments of size (max_core_count * temp_band_count)
  5956. + * Outer: core count
  5957. + * Inner: temperature band
  5958. + * Each element has units of VDD supply steps. Positive
  5959. + * values correspond to a reduction in voltage and negative
  5960. + * value correspond to an increase (this follows the SDELTA
  5961. + * register semantics).
  5962. + * @allow_boost: Voltage boost allowed.
  5963. + * @boost_num_cores: The number of online cores at which the boost voltage
  5964. + * adjustments will be applied
  5965. + * @boost_table: SDELTA table with boost voltage adjustments of size
  5966. + * temp_band_count. Each element has units of VDD supply
  5967. + * steps. Positive values correspond to a reduction in
  5968. + * voltage and negative value correspond to an increase
  5969. + * (this follows the SDELTA register semantics).
  5970. + */
  5971. +struct cpr4_sdelta {
  5972. + bool allow_core_count_adj;
  5973. + bool allow_temp_adj;
  5974. + int max_core_count;
  5975. + int temp_band_count;
  5976. + int cap_volt;
  5977. + int *table;
  5978. + bool allow_boost;
  5979. + int boost_num_cores;
  5980. + int *boost_table;
  5981. +};
  5982. +
  5983. +/**
  5984. + * struct cpr3_corner - CPR3 virtual voltage corner data structure
  5985. + * @floor_volt: CPR closed-loop floor voltage in microvolts
  5986. + * @ceiling_volt: CPR closed-loop ceiling voltage in microvolts
  5987. + * @open_loop_volt: CPR open-loop voltage (i.e. initial voltage) in
  5988. + * microvolts
  5989. + * @last_volt: Last known settled CPR closed-loop voltage which is used
  5990. + * when switching to a new corner
  5991. + * @abs_ceiling_volt: The absolute CPR closed-loop ceiling voltage in
  5992. + * microvolts. This is used to limit the ceiling_volt
  5993. + * value when it is increased as a result of aging
  5994. + * adjustment.
  5995. + * @unaged_floor_volt: The CPR closed-loop floor voltage in microvolts before
  5996. + * any aging adjustment is performed
  5997. + * @unaged_ceiling_volt: The CPR closed-loop ceiling voltage in microvolts
  5998. + * before any aging adjustment is performed
  5999. + * @unaged_open_loop_volt: The CPR open-loop voltage (i.e. initial voltage) in
  6000. + * microvolts before any aging adjusment is performed
  6001. + * @system_volt: The system-supply voltage in microvolts or corners or
  6002. + * levels
  6003. + * @mem_acc_volt: The mem-acc-supply voltage in corners
  6004. + * @proc_freq: Processor frequency in Hertz. For CPR rev. 3 and 4
  6005. + * conrollers, this field is only used by platform specific
  6006. + * CPR3 driver for interpolation. For CPRh-compliant
  6007. + * controllers, this frequency is also utilized by the
  6008. + * clock driver to determine the corner to CPU clock
  6009. + * frequency mappings.
  6010. + * @cpr_fuse_corner: Fused corner index associated with this virtual corner
  6011. + * (only used by platform specific CPR3 driver for
  6012. + * mapping purposes)
  6013. + * @target_quot: Array of target quotient values to use for each ring
  6014. + * oscillator (RO) for this corner. A value of 0 should be
  6015. + * specified as the target quotient for each RO that is
  6016. + * unused by this corner.
  6017. + * @ro_scale: Array of CPR ring oscillator (RO) scaling factors. The
  6018. + * scaling factor for each RO is defined from RO0 to RO15
  6019. + * with units of QUOT/V. A value of 0 may be specified for
  6020. + * an RO that is unused.
  6021. + * @ro_mask: Bitmap where each of the 16 LSBs indicate if the
  6022. + * corresponding ROs should be masked for this corner
  6023. + * @irq_en: Bitmap of the CPR interrupts to enable for this corner
  6024. + * @aging_derate: The amount to derate the aging voltage adjustment
  6025. + * determined for the reference corner in units of uV/mV.
  6026. + * E.g. a value of 900 would imply that the adjustment for
  6027. + * this corner should be 90% (900/1000) of that for the
  6028. + * reference corner.
  6029. + * @use_open_loop: Boolean indicating that open-loop (i.e CPR disabled) as
  6030. + * opposed to closed-loop operation must be used for this
  6031. + * corner on CPRh controllers.
  6032. + * @sdelta: The CPR4 controller specific data for this corner. This
  6033. + * field is applicable for CPR4 controllers.
  6034. + *
  6035. + * The value of last_volt is initialized inside of the cpr3_regulator_register()
  6036. + * call with the open_loop_volt value. It can later be updated to the settled
  6037. + * VDD supply voltage. The values for unaged_floor_volt, unaged_ceiling_volt,
  6038. + * and unaged_open_loop_volt are initialized inside of cpr3_regulator_register()
  6039. + * if ctrl->aging_required == true. These three values must be pre-initialized
  6040. + * if cpr3_regulator_register() is called with ctrl->aging_required == false and
  6041. + * ctrl->aging_succeeded == true.
  6042. + *
  6043. + * The values of ro_mask and irq_en are initialized inside of the
  6044. + * cpr3_regulator_register() call.
  6045. + */
  6046. +struct cpr3_corner {
  6047. + int floor_volt;
  6048. + int ceiling_volt;
  6049. + int cold_temp_open_loop_volt;
  6050. + int normal_temp_open_loop_volt;
  6051. + int open_loop_volt;
  6052. + int last_volt;
  6053. + int abs_ceiling_volt;
  6054. + int unaged_floor_volt;
  6055. + int unaged_ceiling_volt;
  6056. + int unaged_open_loop_volt;
  6057. + int system_volt;
  6058. + int mem_acc_volt;
  6059. + u32 proc_freq;
  6060. + int cpr_fuse_corner;
  6061. + u32 target_quot[CPR3_RO_COUNT];
  6062. + u32 ro_scale[CPR3_RO_COUNT];
  6063. + u32 ro_mask;
  6064. + u32 irq_en;
  6065. + int aging_derate;
  6066. + bool use_open_loop;
  6067. + struct cpr4_sdelta *sdelta;
  6068. +};
  6069. +
  6070. +/**
  6071. + * struct cprh_corner_band - CPRh controller specific data structure which
  6072. + * encapsulates the range of corners and the SDELTA
  6073. + * adjustment table to be applied to the corners within
  6074. + * the min and max bounds of the corner band.
  6075. + * @corner: Corner number which defines the corner band boundary
  6076. + * @sdelta: The SDELTA adjustment table which contains core-count
  6077. + * and temp based margin adjustments that are applicable
  6078. + * to the corner band.
  6079. + */
  6080. +struct cprh_corner_band {
  6081. + int corner;
  6082. + struct cpr4_sdelta *sdelta;
  6083. +};
  6084. +
  6085. +/**
  6086. + * struct cpr3_fuse_parameters - CPR4 fuse specific data structure which has
  6087. + * the required fuse parameters need for Close Loop CPR
  6088. + * @(*apss_ro_sel_param)[2]: Pointer to RO select fuse details
  6089. + * @(*apss_init_voltage_param)[2]: Pointer to Target voltage fuse details
  6090. + * @(*apss_target_quot_param)[2]: Pointer to Target quot fuse details
  6091. + * @(*apss_quot_offset_param)[2]: Pointer to quot offset fuse details
  6092. + * @cpr_fusing_rev_param: Pointer to CPR revision fuse details
  6093. + * @apss_speed_bin_param: Pointer to Speed bin fuse details
  6094. + * @cpr_boost_fuse_cfg_param: Pointer to Boost fuse cfg details
  6095. + * @apss_boost_fuse_volt_param: Pointer to Boost fuse volt details
  6096. + * @misc_fuse_volt_adj_param: Pointer to Misc fuse volt fuse details
  6097. + */
  6098. +struct cpr3_fuse_parameters {
  6099. + struct cpr3_fuse_param (*apss_ro_sel_param)[2];
  6100. + struct cpr3_fuse_param (*apss_init_voltage_param)[2];
  6101. + struct cpr3_fuse_param (*apss_target_quot_param)[2];
  6102. + struct cpr3_fuse_param (*apss_quot_offset_param)[2];
  6103. + struct cpr3_fuse_param *cpr_fusing_rev_param;
  6104. + struct cpr3_fuse_param *apss_speed_bin_param;
  6105. + struct cpr3_fuse_param *cpr_boost_fuse_cfg_param;
  6106. + struct cpr3_fuse_param *apss_boost_fuse_volt_param;
  6107. + struct cpr3_fuse_param *misc_fuse_volt_adj_param;
  6108. +};
  6109. +
  6110. +struct cpr4_mem_acc_func {
  6111. + void (*set_mem_acc)(struct regulator_dev *);
  6112. + void (*clear_mem_acc)(struct regulator_dev *);
  6113. +};
  6114. +
  6115. +/**
  6116. + * struct cpr4_reg_data - CPR4 regulator specific data structure which is
  6117. + * target specific
  6118. + * @cpr_valid_fuse_count: Number of valid fuse corners
  6119. + * @fuse_ref_volt: Pointer to fuse reference voltage
  6120. + * @fuse_step_volt: CPR step voltage available in fuse
  6121. + * @cpr_clk_rate: CPR clock rate
  6122. + * @boost_fuse_ref_volt: Boost fuse reference voltage
  6123. + * @boost_ceiling_volt: Boost ceiling voltage
  6124. + * @boost_floor_volt: Boost floor voltage
  6125. + * @cpr3_fuse_params: Pointer to CPR fuse parameters
  6126. + * @mem_acc_funcs: Pointer to MEM ACC set/clear functions
  6127. + **/
  6128. +struct cpr4_reg_data {
  6129. + u32 cpr_valid_fuse_count;
  6130. + int *fuse_ref_volt;
  6131. + u32 fuse_step_volt;
  6132. + u32 cpr_clk_rate;
  6133. + int boost_fuse_ref_volt;
  6134. + int boost_ceiling_volt;
  6135. + int boost_floor_volt;
  6136. + struct cpr3_fuse_parameters *cpr3_fuse_params;
  6137. + struct cpr4_mem_acc_func *mem_acc_funcs;
  6138. +};
  6139. +/**
  6140. + * struct cpr3_reg_data - CPR3 regulator specific data structure which is
  6141. + * target specific
  6142. + * @cpr_valid_fuse_count: Number of valid fuse corners
  6143. + * @(*init_voltage_param)[2]: Pointer to Target voltage fuse details
  6144. + * @fuse_ref_volt: Pointer to fuse reference voltage
  6145. + * @fuse_step_volt: CPR step voltage available in fuse
  6146. + * @cpr_clk_rate: CPR clock rate
  6147. + * @cpr3_fuse_params: Pointer to CPR fuse parameters
  6148. + **/
  6149. +struct cpr3_reg_data {
  6150. + u32 cpr_valid_fuse_count;
  6151. + struct cpr3_fuse_param (*init_voltage_param)[2];
  6152. + int *fuse_ref_volt;
  6153. + u32 fuse_step_volt;
  6154. + u32 cpr_clk_rate;
  6155. +};
  6156. +
  6157. +/**
  6158. + * struct cpr3_regulator - CPR3 logical regulator instance associated with a
  6159. + * given CPR3 hardware thread
  6160. + * @of_node: Device node associated with the device tree child node
  6161. + * of this CPR3 regulator
  6162. + * @thread: Pointer to the CPR3 thread which manages this CPR3
  6163. + * regulator
  6164. + * @name: Unique name for this CPR3 regulator which is filled
  6165. + * using the device tree regulator-name property
  6166. + * @rdesc: Regulator description for this CPR3 regulator
  6167. + * @rdev: Regulator device pointer for the regulator registered
  6168. + * for this CPR3 regulator
  6169. + * @mem_acc_regulator: Pointer to the optional mem-acc supply regulator used
  6170. + * to manage memory circuitry settings based upon CPR3
  6171. + * regulator output voltage.
  6172. + * @corner: Array of all corners supported by this CPR3 regulator
  6173. + * @corner_count: The number of elements in the corner array
  6174. + * @corner_band: Array of all corner bands supported by CPRh compatible
  6175. + * controllers
  6176. + * @cpr4_regulator_data Target specific cpr4 regulator data
  6177. + * @cpr3_regulator_data Target specific cpr3 regulator data
  6178. + * @corner_band_count: The number of elements in the corner band array
  6179. + * @platform_fuses: Pointer to platform specific CPR fuse data (only used by
  6180. + * platform specific CPR3 driver)
  6181. + * @speed_bin_fuse: Value read from the speed bin fuse parameter
  6182. + * @speed_bins_supported: The number of speed bins supported by the device tree
  6183. + * configuration for this CPR3 regulator
  6184. + * @cpr_rev_fuse: Value read from the CPR fusing revision fuse parameter
  6185. + * @fuse_combo: Platform specific enum value identifying the specific
  6186. + * combination of fuse values found on a given chip
  6187. + * @fuse_combos_supported: The number of fuse combinations supported by the
  6188. + * device tree configuration for this CPR3 regulator
  6189. + * @fuse_corner_count: Number of corners defined by fuse parameters
  6190. + * @fuse_corner_map: Array of length fuse_corner_count which specifies the
  6191. + * highest corner associated with each fuse corner. Note
  6192. + * that each element must correspond to a valid corner
  6193. + * and that element values must be strictly increasing.
  6194. + * Also, it is acceptable for the lowest fuse corner to map
  6195. + * to a corner other than the lowest. Likewise, it is
  6196. + * acceptable for the highest fuse corner to map to a
  6197. + * corner other than the highest.
  6198. + * @fuse_combo_corner_sum: The sum of the corner counts across all fuse combos
  6199. + * @fuse_combo_offset: The device tree property array offset for the selected
  6200. + * fuse combo
  6201. + * @speed_bin_corner_sum: The sum of the corner counts across all speed bins
  6202. + * This may be specified as 0 if per speed bin parsing
  6203. + * support is not required.
  6204. + * @speed_bin_offset: The device tree property array offset for the selected
  6205. + * speed bin
  6206. + * @fuse_combo_corner_band_sum: The sum of the corner band counts across all
  6207. + * fuse combos
  6208. + * @fuse_combo_corner_band_offset: The device tree property array offset for
  6209. + * the corner band count corresponding to the selected
  6210. + * fuse combo
  6211. + * @speed_bin_corner_band_sum: The sum of the corner band counts across all
  6212. + * speed bins. This may be specified as 0 if per speed bin
  6213. + * parsing support is not required
  6214. + * @speed_bin_corner_band_offset: The device tree property array offset for the
  6215. + * corner band count corresponding to the selected speed
  6216. + * bin
  6217. + * @pd_bypass_mask: Bit mask of power domains associated with this CPR3
  6218. + * regulator
  6219. + * @dynamic_floor_corner: Index identifying the voltage corner for the CPR3
  6220. + * regulator whose last_volt value should be used as the
  6221. + * global CPR floor voltage if all of the power domains
  6222. + * associated with this CPR3 regulator are bypassed
  6223. + * @uses_dynamic_floor: Boolean flag indicating that dynamic_floor_corner should
  6224. + * be utilized for the CPR3 regulator
  6225. + * @current_corner: Index identifying the currently selected voltage corner
  6226. + * for the CPR3 regulator or less than 0 if no corner has
  6227. + * been requested
  6228. + * @last_closed_loop_corner: Index identifying the last voltage corner for the
  6229. + * CPR3 regulator which was configured when operating in
  6230. + * CPR closed-loop mode or less than 0 if no corner has
  6231. + * been requested. CPR registers are only written to when
  6232. + * using closed-loop mode.
  6233. + * @aggregated: Boolean flag indicating that this CPR3 regulator
  6234. + * participated in the last aggregation event
  6235. + * @debug_corner: Index identifying voltage corner used for displaying
  6236. + * corner configuration values in debugfs
  6237. + * @vreg_enabled: Boolean defining the enable state of the CPR3
  6238. + * regulator's regulator within the regulator framework.
  6239. + * @aging_allowed: Boolean defining if CPR aging adjustments are allowed
  6240. + * for this CPR3 regulator given the fuse combo of the
  6241. + * device
  6242. + * @aging_allow_open_loop_adj: Boolean defining if the open-loop voltage of each
  6243. + * corner of this regulator should be adjusted as a result
  6244. + * of an aging measurement. This flag can be set to false
  6245. + * when the open-loop voltage adjustments have been
  6246. + * specified such that they include the maximum possible
  6247. + * aging adjustment. This flag is only used if
  6248. + * aging_allowed == true.
  6249. + * @aging_corner: The corner that should be configured for this regulator
  6250. + * when an aging measurement is performed.
  6251. + * @aging_max_adjust_volt: The maximum aging voltage margin in microvolts that
  6252. + * may be added to the target quotients of this regulator.
  6253. + * A value of 0 may be specified if this regulator does not
  6254. + * require any aging adjustment.
  6255. + * @allow_core_count_adj: Core count adjustments are allowed for this regulator.
  6256. + * @allow_temp_adj: Temperature based adjustments are allowed for this
  6257. + * regulator.
  6258. + * @max_core_count: Maximum number of cores considered for core count
  6259. + * adjustment logic.
  6260. + * @allow_boost: Voltage boost allowed for this regulator.
  6261. + *
  6262. + * This structure contains both configuration and runtime state data. The
  6263. + * elements current_corner, last_closed_loop_corner, aggregated, debug_corner,
  6264. + * and vreg_enabled are state variables.
  6265. + */
  6266. +struct cpr3_regulator {
  6267. + struct device_node *of_node;
  6268. + struct cpr3_thread *thread;
  6269. + const char *name;
  6270. + struct regulator_desc rdesc;
  6271. + struct regulator_dev *rdev;
  6272. + struct regulator *mem_acc_regulator;
  6273. + struct cpr3_corner *corner;
  6274. + int corner_count;
  6275. + struct cprh_corner_band *corner_band;
  6276. + struct cpr4_reg_data *cpr4_regulator_data;
  6277. + struct cpr3_reg_data *cpr3_regulator_data;
  6278. + u32 corner_band_count;
  6279. +
  6280. + void *platform_fuses;
  6281. + int speed_bin_fuse;
  6282. + int speed_bins_supported;
  6283. + int cpr_rev_fuse;
  6284. + int part_type;
  6285. + int part_type_supported;
  6286. + int fuse_combo;
  6287. + int fuse_combos_supported;
  6288. + int fuse_corner_count;
  6289. + int *fuse_corner_map;
  6290. + int fuse_combo_corner_sum;
  6291. + int fuse_combo_offset;
  6292. + int speed_bin_corner_sum;
  6293. + int speed_bin_offset;
  6294. + int fuse_combo_corner_band_sum;
  6295. + int fuse_combo_corner_band_offset;
  6296. + int speed_bin_corner_band_sum;
  6297. + int speed_bin_corner_band_offset;
  6298. + u32 pd_bypass_mask;
  6299. + int dynamic_floor_corner;
  6300. + bool uses_dynamic_floor;
  6301. +
  6302. + int current_corner;
  6303. + int last_closed_loop_corner;
  6304. + bool aggregated;
  6305. + int debug_corner;
  6306. + bool vreg_enabled;
  6307. +
  6308. + bool aging_allowed;
  6309. + bool aging_allow_open_loop_adj;
  6310. + int aging_corner;
  6311. + int aging_max_adjust_volt;
  6312. +
  6313. + bool allow_core_count_adj;
  6314. + bool allow_temp_adj;
  6315. + int max_core_count;
  6316. + bool allow_boost;
  6317. +};
  6318. +
  6319. +/**
  6320. + * struct cpr3_thread - CPR3 hardware thread data structure
  6321. + * @thread_id: Hardware thread ID
  6322. + * @of_node: Device node associated with the device tree child node
  6323. + * of this CPR3 thread
  6324. + * @ctrl: Pointer to the CPR3 controller which manages this thread
  6325. + * @vreg: Array of CPR3 regulators handled by the CPR3 thread
  6326. + * @vreg_count: Number of elements in the vreg array
  6327. + * @aggr_corner: CPR corner containing the in process aggregated voltage
  6328. + * and target quotient configurations which will be applied
  6329. + * @last_closed_loop_aggr_corner: CPR corner containing the most recent
  6330. + * configurations which were written into hardware
  6331. + * registers when operating in closed loop mode (i.e. with
  6332. + * CPR enabled)
  6333. + * @consecutive_up: The number of consecutive CPR step up events needed to
  6334. + * to trigger an up interrupt
  6335. + * @consecutive_down: The number of consecutive CPR step down events needed to
  6336. + * to trigger a down interrupt
  6337. + * @up_threshold: The number CPR error steps required to generate an up
  6338. + * event
  6339. + * @down_threshold: The number CPR error steps required to generate a down
  6340. + * event
  6341. + *
  6342. + * This structure contains both configuration and runtime state data. The
  6343. + * elements aggr_corner and last_closed_loop_aggr_corner are state variables.
  6344. + */
  6345. +struct cpr3_thread {
  6346. + u32 thread_id;
  6347. + struct device_node *of_node;
  6348. + struct cpr3_controller *ctrl;
  6349. + struct cpr3_regulator *vreg;
  6350. + int vreg_count;
  6351. + struct cpr3_corner aggr_corner;
  6352. + struct cpr3_corner last_closed_loop_aggr_corner;
  6353. +
  6354. + u32 consecutive_up;
  6355. + u32 consecutive_down;
  6356. + u32 up_threshold;
  6357. + u32 down_threshold;
  6358. +};
  6359. +
  6360. +/* Per CPR controller data */
  6361. +/**
  6362. + * enum cpr3_mem_acc_corners - Constants which define the number of mem-acc
  6363. + * regulator corners available in the mem-acc corner map array.
  6364. + * %CPR3_MEM_ACC_LOW_CORNER: Index in mem-acc corner map array mapping to the
  6365. + * mem-acc regulator corner
  6366. + * to be used for low voltage vdd supply
  6367. + * %CPR3_MEM_ACC_HIGH_CORNER: Index in mem-acc corner map array mapping to the
  6368. + * mem-acc regulator corner to be used for high
  6369. + * voltage vdd supply
  6370. + * %CPR3_MEM_ACC_CORNERS: Number of elements in the mem-acc corner map
  6371. + * array
  6372. + */
  6373. +enum cpr3_mem_acc_corners {
  6374. + CPR3_MEM_ACC_LOW_CORNER = 0,
  6375. + CPR3_MEM_ACC_HIGH_CORNER = 1,
  6376. + CPR3_MEM_ACC_CORNERS = 2,
  6377. +};
  6378. +
  6379. +/**
  6380. + * enum cpr3_count_mode - CPR3 controller count mode which defines the
  6381. + * method that CPR sensor data is acquired
  6382. + * %CPR3_COUNT_MODE_ALL_AT_ONCE_MIN: Capture all CPR sensor readings
  6383. + * simultaneously and report the minimum
  6384. + * value seen in successive measurements
  6385. + * %CPR3_COUNT_MODE_ALL_AT_ONCE_MAX: Capture all CPR sensor readings
  6386. + * simultaneously and report the maximum
  6387. + * value seen in successive measurements
  6388. + * %CPR3_COUNT_MODE_STAGGERED: Read one sensor at a time in a
  6389. + * sequential fashion
  6390. + * %CPR3_COUNT_MODE_ALL_AT_ONCE_AGE: Capture all CPR aging sensor readings
  6391. + * simultaneously.
  6392. + */
  6393. +enum cpr3_count_mode {
  6394. + CPR3_COUNT_MODE_ALL_AT_ONCE_MIN = 0,
  6395. + CPR3_COUNT_MODE_ALL_AT_ONCE_MAX = 1,
  6396. + CPR3_COUNT_MODE_STAGGERED = 2,
  6397. + CPR3_COUNT_MODE_ALL_AT_ONCE_AGE = 3,
  6398. +};
  6399. +
  6400. +/**
  6401. + * enum cpr_controller_type - supported CPR controller hardware types
  6402. + * %CPR_CTRL_TYPE_CPR3: HW has CPR3 controller
  6403. + * %CPR_CTRL_TYPE_CPR4: HW has CPR4 controller
  6404. + */
  6405. +enum cpr_controller_type {
  6406. + CPR_CTRL_TYPE_CPR3,
  6407. + CPR_CTRL_TYPE_CPR4,
  6408. +};
  6409. +
  6410. +/**
  6411. + * cpr_setting - supported CPR global settings
  6412. + * %CPR_DEFAULT: default mode from dts will be used
  6413. + * %CPR_DISABLED: ceiling voltage will be used for all the corners
  6414. + * %CPR_OPEN_LOOP_EN: CPR will work in OL
  6415. + * %CPR_CLOSED_LOOP_EN: CPR will work in CL, if supported
  6416. + */
  6417. +enum cpr_setting {
  6418. + CPR_DEFAULT = 0,
  6419. + CPR_DISABLED = 1,
  6420. + CPR_OPEN_LOOP_EN = 2,
  6421. + CPR_CLOSED_LOOP_EN = 3,
  6422. +};
  6423. +
  6424. +/**
  6425. + * struct cpr3_aging_sensor_info - CPR3 aging sensor information
  6426. + * @sensor_id The index of the CPR3 sensor to be used in the aging
  6427. + * measurement.
  6428. + * @ro_scale The CPR ring oscillator (RO) scaling factor for the
  6429. + * aging sensor with units of QUOT/V.
  6430. + * @init_quot_diff: The fused quotient difference between aged and un-aged
  6431. + * paths that was measured at manufacturing time.
  6432. + * @measured_quot_diff: The quotient difference measured at runtime.
  6433. + * @bypass_mask: Bit mask of the CPR sensors that must be bypassed during
  6434. + * the aging measurement for this sensor
  6435. + *
  6436. + * This structure contains both configuration and runtime state data. The
  6437. + * element measured_quot_diff is a state variable.
  6438. + */
  6439. +struct cpr3_aging_sensor_info {
  6440. + u32 sensor_id;
  6441. + u32 ro_scale;
  6442. + int init_quot_diff;
  6443. + int measured_quot_diff;
  6444. + u32 bypass_mask[CPR3_MAX_SENSOR_COUNT / 32];
  6445. +};
  6446. +
  6447. +/**
  6448. + * struct cpr3_reg_info - Register information data structure
  6449. + * @name: Register name
  6450. + * @addr: Register physical address
  6451. + * @value: Register content
  6452. + * @virt_addr: Register virtual address
  6453. + *
  6454. + * This data structure is used to dump some critical register contents
  6455. + * when the device crashes due to a kernel panic.
  6456. + */
  6457. +struct cpr3_reg_info {
  6458. + const char *name;
  6459. + u32 addr;
  6460. + u32 value;
  6461. + void __iomem *virt_addr;
  6462. +};
  6463. +
  6464. +/**
  6465. + * struct cpr3_panic_regs_info - Data structure to dump critical register
  6466. + * contents.
  6467. + * @reg_count: Number of elements in the regs array
  6468. + * @regs: Array of critical registers information
  6469. + *
  6470. + * This data structure is used to dump critical register contents when
  6471. + * the device crashes due to a kernel panic.
  6472. + */
  6473. +struct cpr3_panic_regs_info {
  6474. + int reg_count;
  6475. + struct cpr3_reg_info *regs;
  6476. +};
  6477. +
  6478. +/**
  6479. + * struct cpr3_controller - CPR3 controller data structure
  6480. + * @dev: Device pointer for the CPR3 controller device
  6481. + * @name: Unique name for the CPR3 controller
  6482. + * @ctrl_id: Controller ID corresponding to the VDD supply number
  6483. + * that this CPR3 controller manages.
  6484. + * @cpr_ctrl_base: Virtual address of the CPR3 controller base register
  6485. + * @fuse_base: Virtual address of fuse row 0
  6486. + * @aging_possible_reg: Virtual address of an optional platform-specific
  6487. + * register that must be ready to determine if it is
  6488. + * possible to perform an aging measurement.
  6489. + * @list: list head used in a global cpr3-regulator list so that
  6490. + * cpr3-regulator structs can be found easily in RAM dumps
  6491. + * @thread: Array of CPR3 threads managed by the CPR3 controller
  6492. + * @thread_count: Number of elements in the thread array
  6493. + * @sensor_owner: Array of thread IDs indicating which thread owns a given
  6494. + * CPR sensor
  6495. + * @sensor_count: The number of CPR sensors found on the CPR loop managed
  6496. + * by this CPR controller. Must be equal to the number of
  6497. + * elements in the sensor_owner array
  6498. + * @soc_revision: Revision number of the SoC. This may be unused by
  6499. + * platforms that do not have different behavior for
  6500. + * different SoC revisions.
  6501. + * @lock: Mutex lock used to ensure mutual exclusion between
  6502. + * all of the threads associated with the controller
  6503. + * @vdd_regulator: Pointer to the VDD supply regulator which this CPR3
  6504. + * controller manages
  6505. + * @system_regulator: Pointer to the optional system-supply regulator upon
  6506. + * which the VDD supply regulator depends.
  6507. + * @mem_acc_regulator: Pointer to the optional mem-acc supply regulator used
  6508. + * to manage memory circuitry settings based upon the
  6509. + * VDD supply output voltage.
  6510. + * @vdd_limit_regulator: Pointer to the VDD supply limit regulator which is used
  6511. + * for hardware closed-loop in order specify ceiling and
  6512. + * floor voltage limits (platform specific)
  6513. + * @system_supply_max_volt: Voltage in microvolts which corresponds to the
  6514. + * absolute ceiling voltage of the system-supply
  6515. + * @mem_acc_threshold_volt: mem-acc threshold voltage in microvolts
  6516. + * @mem_acc_corner_map: mem-acc regulator corners mapping to low and high
  6517. + * voltage mem-acc settings for the memories powered by
  6518. + * this CPR3 controller and its associated CPR3 regulators
  6519. + * @mem_acc_crossover_volt: Voltage in microvolts corresponding to the voltage
  6520. + * that the VDD supply must be set to while a MEM ACC
  6521. + * switch is in progress. This element must be initialized
  6522. + * for CPRh controllers when a MEM ACC threshold voltage is
  6523. + * defined.
  6524. + * @core_clk: Pointer to the CPR3 controller core clock
  6525. + * @iface_clk: Pointer to the CPR3 interface clock (platform specific)
  6526. + * @bus_clk: Pointer to the CPR3 bus clock (platform specific)
  6527. + * @irq: CPR interrupt number
  6528. + * @irq_affinity_mask: The cpumask for the CPUs which the CPR interrupt should
  6529. + * have affinity for
  6530. + * @cpu_hotplug_notifier: CPU hotplug notifier used to reset IRQ affinity when a
  6531. + * CPU is brought back online
  6532. + * @ceiling_irq: Interrupt number for the interrupt that is triggered
  6533. + * when hardware closed-loop attempts to exceed the ceiling
  6534. + * voltage
  6535. + * @apm: Handle to the array power mux (APM)
  6536. + * @apm_threshold_volt: Voltage in microvolts which defines the threshold
  6537. + * voltage to determine the APM supply selection for
  6538. + * each corner
  6539. + * @apm_crossover_volt: Voltage in microvolts corresponding to the voltage that
  6540. + * the VDD supply must be set to while an APM switch is in
  6541. + * progress. This element must be initialized for CPRh
  6542. + * controllers when an APM threshold voltage is defined
  6543. + * @apm_adj_volt: Minimum difference between APM threshold voltage and
  6544. + * open-loop voltage which allows the APM threshold voltage
  6545. + * to be used as a ceiling
  6546. + * @apm_high_supply: APM supply to configure if VDD voltage is greater than
  6547. + * or equal to the APM threshold voltage
  6548. + * @apm_low_supply: APM supply to configure if the VDD voltage is less than
  6549. + * the APM threshold voltage
  6550. + * @base_volt: Minimum voltage in microvolts supported by the VDD
  6551. + * supply managed by this CPR controller
  6552. + * @corner_switch_delay_time: The delay time in nanoseconds used by the CPR
  6553. + * controller to wait for voltage settling before
  6554. + * acknowledging the OSM block after corner changes
  6555. + * @cpr_clock_rate: CPR reference clock frequency in Hz.
  6556. + * @sensor_time: The time in nanoseconds that each sensor takes to
  6557. + * perform a measurement.
  6558. + * @loop_time: The time in nanoseconds between consecutive CPR
  6559. + * measurements.
  6560. + * @up_down_delay_time: The time to delay in nanoseconds between consecutive CPR
  6561. + * measurements when the last measurement recommended
  6562. + * increasing or decreasing the vdd-supply voltage.
  6563. + * (platform specific)
  6564. + * @idle_clocks: Number of CPR reference clock ticks that the CPR
  6565. + * controller waits in transitional states.
  6566. + * @step_quot_init_min: The default minimum CPR step quotient value. The step
  6567. + * quotient is the number of additional ring oscillator
  6568. + * ticks observed when increasing one step in vdd-supply
  6569. + * output voltage.
  6570. + * @step_quot_init_max: The default maximum CPR step quotient value.
  6571. + * @step_volt: Step size in microvolts between available set points
  6572. + * of the VDD supply
  6573. + * @down_error_step_limit: CPR4 hardware closed-loop down error step limit which
  6574. + * defines the maximum number of VDD supply regulator steps
  6575. + * that the voltage may be reduced as the result of a
  6576. + * single CPR measurement.
  6577. + * @up_error_step_limit: CPR4 hardware closed-loop up error step limit which
  6578. + * defines the maximum number of VDD supply regulator steps
  6579. + * that the voltage may be increased as the result of a
  6580. + * single CPR measurement.
  6581. + * @count_mode: CPR controller count mode
  6582. + * @count_repeat: Number of times to perform consecutive sensor
  6583. + * measurements when using all-at-once count modes.
  6584. + * @proc_clock_throttle: Defines the processor clock frequency throttling
  6585. + * register value to use. This can be used to reduce the
  6586. + * clock frequency when a power domain exits a low power
  6587. + * mode until CPR settles at a new voltage.
  6588. + * (platform specific)
  6589. + * @cpr_allowed_hw: Boolean which indicates if closed-loop CPR operation is
  6590. + * permitted for a given chip based upon hardware fuse
  6591. + * values
  6592. + * @cpr_allowed_sw: Boolean which indicates if closed-loop CPR operation is
  6593. + * permitted based upon software policies
  6594. + * @supports_hw_closed_loop: Boolean which indicates if this CPR3/4 controller
  6595. + * physically supports hardware closed-loop CPR operation
  6596. + * @use_hw_closed_loop: Boolean which indicates that this controller will be
  6597. + * using hardware closed-loop operation in place of
  6598. + * software closed-loop operation.
  6599. + * @ctrl_type: CPR controller type
  6600. + * @saw_use_unit_mV: Boolean which indicates the unit used in SAW PVC
  6601. + * interface is mV.
  6602. + * @aggr_corner: CPR corner containing the most recently aggregated
  6603. + * voltage configurations which are being used currently
  6604. + * @cpr_enabled: Boolean which indicates that the CPR controller is
  6605. + * enabled and operating in closed-loop mode. CPR clocks
  6606. + * have been prepared and enabled whenever this flag is
  6607. + * true.
  6608. + * @last_corner_was_closed_loop: Boolean indicating if the last known corners
  6609. + * were updated during closed loop operation.
  6610. + * @cpr_suspended: Boolean which indicates that CPR has been temporarily
  6611. + * disabled while enterring system suspend.
  6612. + * @debugfs: Pointer to the debugfs directory of this CPR3 controller
  6613. + * @aging_ref_volt: Reference voltage in microvolts to configure when
  6614. + * performing CPR aging measurements.
  6615. + * @aging_vdd_mode: vdd-supply regulator mode to configure before performing
  6616. + * a CPR aging measurement. It should be one of
  6617. + * REGULATOR_MODE_*.
  6618. + * @aging_complete_vdd_mode: vdd-supply regulator mode to configure after
  6619. + * performing a CPR aging measurement. It should be one of
  6620. + * REGULATOR_MODE_*.
  6621. + * @aging_ref_adjust_volt: The reference aging voltage margin in microvolts that
  6622. + * should be added to the target quotients of the
  6623. + * regulators managed by this controller after derating.
  6624. + * @aging_required: Flag which indicates that a CPR aging measurement still
  6625. + * needs to be performed for this CPR3 controller.
  6626. + * @aging_succeeded: Flag which indicates that a CPR aging measurement has
  6627. + * completed successfully.
  6628. + * @aging_failed: Flag which indicates that a CPR aging measurement has
  6629. + * failed to complete successfully.
  6630. + * @aging_sensor: Array of CPR3 aging sensors which are used to perform
  6631. + * aging measurements at a runtime.
  6632. + * @aging_sensor_count: Number of elements in the aging_sensor array
  6633. + * @aging_possible_mask: Optional bitmask used to mask off the
  6634. + * aging_possible_reg register.
  6635. + * @aging_possible_val: Optional value that the masked aging_possible_reg
  6636. + * register must have in order for a CPR aging measurement
  6637. + * to be possible.
  6638. + * @step_quot_fixed: Fixed step quotient value used for target quotient
  6639. + * adjustment if use_dynamic_step_quot is not set.
  6640. + * This parameter is only relevant for CPR4 controllers
  6641. + * when using the per-online-core or per-temperature
  6642. + * adjustments.
  6643. + * @initial_temp_band: Temperature band used for calculation of base-line
  6644. + * target quotients (fused).
  6645. + * @use_dynamic_step_quot: Boolean value which indicates that margin adjustment
  6646. + * of target quotient will be based on the step quotient
  6647. + * calculated dynamically in hardware for each RO.
  6648. + * @allow_core_count_adj: Core count adjustments are allowed for this controller
  6649. + * @allow_temp_adj: Temperature based adjustments are allowed for
  6650. + * this controller
  6651. + * @allow_boost: Voltage boost allowed for this controller.
  6652. + * @temp_band_count: Number of temperature bands used for temperature based
  6653. + * adjustment logic
  6654. + * @temp_points: Array of temperature points in decidegrees Celsius used
  6655. + * to specify the ranges for selected temperature bands.
  6656. + * The array must have (temp_band_count - 1) elements
  6657. + * allocated.
  6658. + * @temp_sensor_id_start: Start ID of temperature sensors used for temperature
  6659. + * based adjustments.
  6660. + * @temp_sensor_id_end: End ID of temperature sensors used for temperature
  6661. + * based adjustments.
  6662. + * @voltage_settling_time: The time in nanoseconds that it takes for the
  6663. + * VDD supply voltage to settle after being increased or
  6664. + * decreased by step_volt microvolts which is used when
  6665. + * SDELTA voltage margin adjustments are applied.
  6666. + * @cpr_global_setting: Global setting for this CPR controller
  6667. + * @panic_regs_info: Array of panic registers information which provides the
  6668. + * list of registers to dump when the device crashes.
  6669. + * @panic_notifier: Notifier block registered to global panic notifier list.
  6670. + *
  6671. + * This structure contains both configuration and runtime state data. The
  6672. + * elements cpr_allowed_sw, use_hw_closed_loop, aggr_corner, cpr_enabled,
  6673. + * last_corner_was_closed_loop, cpr_suspended, aging_ref_adjust_volt,
  6674. + * aging_required, aging_succeeded, and aging_failed are state variables.
  6675. + *
  6676. + * The apm* elements do not need to be initialized if the VDD supply managed by
  6677. + * the CPR3 controller does not utilize an APM.
  6678. + *
  6679. + * The elements step_quot_fixed, initial_temp_band, allow_core_count_adj,
  6680. + * allow_temp_adj and temp* need to be initialized for CPR4 controllers which
  6681. + * are using per-online-core or per-temperature adjustments.
  6682. + */
  6683. +struct cpr3_controller {
  6684. + struct device *dev;
  6685. + const char *name;
  6686. + int ctrl_id;
  6687. + void __iomem *cpr_ctrl_base;
  6688. + void __iomem *fuse_base;
  6689. + void __iomem *aging_possible_reg;
  6690. + struct list_head list;
  6691. + struct cpr3_thread *thread;
  6692. + int thread_count;
  6693. + u8 *sensor_owner;
  6694. + int sensor_count;
  6695. + int soc_revision;
  6696. + struct mutex lock;
  6697. + struct regulator *vdd_regulator;
  6698. + struct regulator *system_regulator;
  6699. + struct regulator *mem_acc_regulator;
  6700. + struct regulator *vdd_limit_regulator;
  6701. + int system_supply_max_volt;
  6702. + int mem_acc_threshold_volt;
  6703. + int mem_acc_corner_map[CPR3_MEM_ACC_CORNERS];
  6704. + int mem_acc_crossover_volt;
  6705. + struct clk *core_clk;
  6706. + struct clk *iface_clk;
  6707. + struct clk *bus_clk;
  6708. + int irq;
  6709. + struct cpumask irq_affinity_mask;
  6710. + struct notifier_block cpu_hotplug_notifier;
  6711. + int ceiling_irq;
  6712. + struct msm_apm_ctrl_dev *apm;
  6713. + int apm_threshold_volt;
  6714. + int apm_crossover_volt;
  6715. + int apm_adj_volt;
  6716. + enum msm_apm_supply apm_high_supply;
  6717. + enum msm_apm_supply apm_low_supply;
  6718. + int base_volt;
  6719. + u32 corner_switch_delay_time;
  6720. + u32 cpr_clock_rate;
  6721. + u32 sensor_time;
  6722. + u32 loop_time;
  6723. + u32 up_down_delay_time;
  6724. + u32 idle_clocks;
  6725. + u32 step_quot_init_min;
  6726. + u32 step_quot_init_max;
  6727. + int step_volt;
  6728. + u32 down_error_step_limit;
  6729. + u32 up_error_step_limit;
  6730. + enum cpr3_count_mode count_mode;
  6731. + u32 count_repeat;
  6732. + u32 proc_clock_throttle;
  6733. + bool cpr_allowed_hw;
  6734. + bool cpr_allowed_sw;
  6735. + bool supports_hw_closed_loop;
  6736. + bool use_hw_closed_loop;
  6737. + enum cpr_controller_type ctrl_type;
  6738. + bool saw_use_unit_mV;
  6739. + struct cpr3_corner aggr_corner;
  6740. + bool cpr_enabled;
  6741. + bool last_corner_was_closed_loop;
  6742. + bool cpr_suspended;
  6743. + struct dentry *debugfs;
  6744. +
  6745. + int aging_ref_volt;
  6746. + unsigned int aging_vdd_mode;
  6747. + unsigned int aging_complete_vdd_mode;
  6748. + int aging_ref_adjust_volt;
  6749. + bool aging_required;
  6750. + bool aging_succeeded;
  6751. + bool aging_failed;
  6752. + struct cpr3_aging_sensor_info *aging_sensor;
  6753. + int aging_sensor_count;
  6754. + u32 cur_sensor_state;
  6755. + u32 aging_possible_mask;
  6756. + u32 aging_possible_val;
  6757. +
  6758. + u32 step_quot_fixed;
  6759. + u32 initial_temp_band;
  6760. + bool use_dynamic_step_quot;
  6761. + bool allow_core_count_adj;
  6762. + bool allow_temp_adj;
  6763. + bool allow_boost;
  6764. + int temp_band_count;
  6765. + int *temp_points;
  6766. + u32 temp_sensor_id_start;
  6767. + u32 temp_sensor_id_end;
  6768. + u32 voltage_settling_time;
  6769. + enum cpr_setting cpr_global_setting;
  6770. + struct cpr3_panic_regs_info *panic_regs_info;
  6771. + struct notifier_block panic_notifier;
  6772. +};
  6773. +
  6774. +/* Used for rounding voltages to the closest physically available set point. */
  6775. +#define CPR3_ROUND(n, d) (DIV_ROUND_UP(n, d) * (d))
  6776. +
  6777. +#define cpr3_err(cpr3_thread, message, ...) \
  6778. + pr_err("%s: " message, (cpr3_thread)->name, ##__VA_ARGS__)
  6779. +#define cpr3_info(cpr3_thread, message, ...) \
  6780. + pr_info("%s: " message, (cpr3_thread)->name, ##__VA_ARGS__)
  6781. +#define cpr3_debug(cpr3_thread, message, ...) \
  6782. + pr_debug("%s: " message, (cpr3_thread)->name, ##__VA_ARGS__)
  6783. +
  6784. +/*
  6785. + * Offset subtracted from voltage corner values passed in from the regulator
  6786. + * framework in order to get internal voltage corner values. This is needed
  6787. + * since the regulator framework treats 0 as an error value at regulator
  6788. + * registration time.
  6789. + */
  6790. +#define CPR3_CORNER_OFFSET 1
  6791. +
  6792. +#ifdef CONFIG_REGULATOR_CPR3
  6793. +
  6794. +int cpr3_regulator_register(struct platform_device *pdev,
  6795. + struct cpr3_controller *ctrl);
  6796. +int cpr3_open_loop_regulator_register(struct platform_device *pdev,
  6797. + struct cpr3_controller *ctrl);
  6798. +int cpr3_regulator_unregister(struct cpr3_controller *ctrl);
  6799. +int cpr3_open_loop_regulator_unregister(struct cpr3_controller *ctrl);
  6800. +int cpr3_regulator_suspend(struct cpr3_controller *ctrl);
  6801. +int cpr3_regulator_resume(struct cpr3_controller *ctrl);
  6802. +
  6803. +int cpr3_allocate_threads(struct cpr3_controller *ctrl, u32 min_thread_id,
  6804. + u32 max_thread_id);
  6805. +int cpr3_map_fuse_base(struct cpr3_controller *ctrl,
  6806. + struct platform_device *pdev);
  6807. +int cpr3_read_tcsr_setting(struct cpr3_controller *ctrl,
  6808. + struct platform_device *pdev, u8 start, u8 end);
  6809. +int cpr3_read_fuse_param(void __iomem *fuse_base_addr,
  6810. + const struct cpr3_fuse_param *param, u64 *param_value);
  6811. +int cpr3_convert_open_loop_voltage_fuse(int ref_volt, int step_volt, u32 fuse,
  6812. + int fuse_len);
  6813. +u64 cpr3_interpolate(u64 x1, u64 y1, u64 x2, u64 y2, u64 x);
  6814. +int cpr3_parse_array_property(struct cpr3_regulator *vreg,
  6815. + const char *prop_name, int tuple_size, u32 *out);
  6816. +int cpr3_parse_corner_array_property(struct cpr3_regulator *vreg,
  6817. + const char *prop_name, int tuple_size, u32 *out);
  6818. +int cpr3_parse_corner_band_array_property(struct cpr3_regulator *vreg,
  6819. + const char *prop_name, int tuple_size, u32 *out);
  6820. +int cpr3_parse_common_corner_data(struct cpr3_regulator *vreg);
  6821. +int cpr3_parse_thread_u32(struct cpr3_thread *thread, const char *propname,
  6822. + u32 *out_value, u32 value_min, u32 value_max);
  6823. +int cpr3_parse_ctrl_u32(struct cpr3_controller *ctrl, const char *propname,
  6824. + u32 *out_value, u32 value_min, u32 value_max);
  6825. +int cpr3_parse_common_thread_data(struct cpr3_thread *thread);
  6826. +int cpr3_parse_common_ctrl_data(struct cpr3_controller *ctrl);
  6827. +int cpr3_parse_open_loop_common_ctrl_data(struct cpr3_controller *ctrl);
  6828. +int cpr3_limit_open_loop_voltages(struct cpr3_regulator *vreg);
  6829. +void cpr3_open_loop_voltage_as_ceiling(struct cpr3_regulator *vreg);
  6830. +int cpr3_limit_floor_voltages(struct cpr3_regulator *vreg);
  6831. +void cpr3_print_quots(struct cpr3_regulator *vreg);
  6832. +int cpr3_determine_part_type(struct cpr3_regulator *vreg, int fuse_volt);
  6833. +int cpr3_determine_temp_base_open_loop_correction(struct cpr3_regulator *vreg,
  6834. + int *fuse_volt);
  6835. +int cpr3_adjust_fused_open_loop_voltages(struct cpr3_regulator *vreg,
  6836. + int *fuse_volt);
  6837. +int cpr3_adjust_open_loop_voltages(struct cpr3_regulator *vreg);
  6838. +int cpr3_quot_adjustment(int ro_scale, int volt_adjust);
  6839. +int cpr3_voltage_adjustment(int ro_scale, int quot_adjust);
  6840. +int cpr3_parse_closed_loop_voltage_adjustments(struct cpr3_regulator *vreg,
  6841. + u64 *ro_sel, int *volt_adjust,
  6842. + int *volt_adjust_fuse, int *ro_scale);
  6843. +int cpr4_parse_core_count_temp_voltage_adj(struct cpr3_regulator *vreg,
  6844. + bool use_corner_band);
  6845. +int cpr3_apm_init(struct cpr3_controller *ctrl);
  6846. +int cpr3_mem_acc_init(struct cpr3_regulator *vreg);
  6847. +void cprh_adjust_voltages_for_apm(struct cpr3_regulator *vreg);
  6848. +void cprh_adjust_voltages_for_mem_acc(struct cpr3_regulator *vreg);
  6849. +int cpr3_adjust_target_quotients(struct cpr3_regulator *vreg,
  6850. + int *fuse_volt_adjust);
  6851. +int cpr3_handle_temp_open_loop_adjustment(struct cpr3_controller *ctrl,
  6852. + bool is_cold);
  6853. +int cpr3_get_cold_temp_threshold(struct cpr3_regulator *vreg, int *cold_temp);
  6854. +bool cpr3_can_adjust_cold_temp(struct cpr3_regulator *vreg);
  6855. +
  6856. +#else
  6857. +
  6858. +static inline int cpr3_regulator_register(struct platform_device *pdev,
  6859. + struct cpr3_controller *ctrl)
  6860. +{
  6861. + return -ENXIO;
  6862. +}
  6863. +
  6864. +static inline int
  6865. +cpr3_open_loop_regulator_register(struct platform_device *pdev,
  6866. + struct cpr3_controller *ctrl);
  6867. +{
  6868. + return -ENXIO;
  6869. +}
  6870. +
  6871. +static inline int cpr3_regulator_unregister(struct cpr3_controller *ctrl)
  6872. +{
  6873. + return -ENXIO;
  6874. +}
  6875. +
  6876. +static inline int
  6877. +cpr3_open_loop_regulator_unregister(struct cpr3_controller *ctrl)
  6878. +{
  6879. + return -ENXIO;
  6880. +}
  6881. +
  6882. +static inline int cpr3_regulator_suspend(struct cpr3_controller *ctrl)
  6883. +{
  6884. + return -ENXIO;
  6885. +}
  6886. +
  6887. +static inline int cpr3_regulator_resume(struct cpr3_controller *ctrl)
  6888. +{
  6889. + return -ENXIO;
  6890. +}
  6891. +
  6892. +static inline int cpr3_get_thread_name(struct cpr3_thread *thread,
  6893. + struct device_node *thread_node)
  6894. +{
  6895. + return -EPERM;
  6896. +}
  6897. +
  6898. +static inline int cpr3_allocate_threads(struct cpr3_controller *ctrl,
  6899. + u32 min_thread_id, u32 max_thread_id)
  6900. +{
  6901. + return -EPERM;
  6902. +}
  6903. +
  6904. +static inline int cpr3_map_fuse_base(struct cpr3_controller *ctrl,
  6905. + struct platform_device *pdev)
  6906. +{
  6907. + return -ENXIO;
  6908. +}
  6909. +
  6910. +static inline int cpr3_read_tcsr_setting(struct cpr3_controller *ctrl,
  6911. + struct platform_device *pdev, u8 start, u8 end)
  6912. +{
  6913. + return 0;
  6914. +}
  6915. +
  6916. +static inline int cpr3_read_fuse_param(void __iomem *fuse_base_addr,
  6917. + const struct cpr3_fuse_param *param, u64 *param_value)
  6918. +{
  6919. + return -EPERM;
  6920. +}
  6921. +
  6922. +static inline int cpr3_convert_open_loop_voltage_fuse(int ref_volt,
  6923. + int step_volt, u32 fuse, int fuse_len)
  6924. +{
  6925. + return -EPERM;
  6926. +}
  6927. +
  6928. +static inline u64 cpr3_interpolate(u64 x1, u64 y1, u64 x2, u64 y2, u64 x)
  6929. +{
  6930. + return 0;
  6931. +}
  6932. +
  6933. +static inline int cpr3_parse_array_property(struct cpr3_regulator *vreg,
  6934. + const char *prop_name, int tuple_size, u32 *out)
  6935. +{
  6936. + return -EPERM;
  6937. +}
  6938. +
  6939. +static inline int cpr3_parse_corner_array_property(struct cpr3_regulator *vreg,
  6940. + const char *prop_name, int tuple_size, u32 *out)
  6941. +{
  6942. + return -EPERM;
  6943. +}
  6944. +
  6945. +static inline int cpr3_parse_corner_band_array_property(
  6946. + struct cpr3_regulator *vreg, const char *prop_name,
  6947. + int tuple_size, u32 *out)
  6948. +{
  6949. + return -EPERM;
  6950. +}
  6951. +
  6952. +static inline int cpr3_parse_common_corner_data(struct cpr3_regulator *vreg)
  6953. +{
  6954. + return -EPERM;
  6955. +}
  6956. +
  6957. +static inline int cpr3_parse_thread_u32(struct cpr3_thread *thread,
  6958. + const char *propname, u32 *out_value, u32 value_min,
  6959. + u32 value_max)
  6960. +{
  6961. + return -EPERM;
  6962. +}
  6963. +
  6964. +static inline int cpr3_parse_ctrl_u32(struct cpr3_controller *ctrl,
  6965. + const char *propname, u32 *out_value, u32 value_min,
  6966. + u32 value_max)
  6967. +{
  6968. + return -EPERM;
  6969. +}
  6970. +
  6971. +static inline int cpr3_parse_common_thread_data(struct cpr3_thread *thread)
  6972. +{
  6973. + return -EPERM;
  6974. +}
  6975. +
  6976. +static inline int cpr3_parse_common_ctrl_data(struct cpr3_controller *ctrl)
  6977. +{
  6978. + return -EPERM;
  6979. +}
  6980. +
  6981. +static inline int
  6982. +cpr3_parse_open_loop_common_ctrl_data(struct cpr3_controller *ctrl)
  6983. +{
  6984. + return -EPERM;
  6985. +}
  6986. +
  6987. +static inline int cpr3_limit_open_loop_voltages(struct cpr3_regulator *vreg)
  6988. +{
  6989. + return -EPERM;
  6990. +}
  6991. +
  6992. +static inline void cpr3_open_loop_voltage_as_ceiling(
  6993. + struct cpr3_regulator *vreg)
  6994. +{
  6995. + return;
  6996. +}
  6997. +
  6998. +static inline int cpr3_limit_floor_voltages(struct cpr3_regulator *vreg)
  6999. +{
  7000. + return -EPERM;
  7001. +}
  7002. +
  7003. +static inline void cpr3_print_quots(struct cpr3_regulator *vreg)
  7004. +{
  7005. + return;
  7006. +}
  7007. +
  7008. +static inline int
  7009. +cpr3_determine_part_type(struct cpr3_regulator *vreg, int fuse_volt)
  7010. +{
  7011. + return -EPERM;
  7012. +}
  7013. +
  7014. +static inline int
  7015. +cpr3_determine_temp_base_open_loop_correction(struct cpr3_regulator *vreg,
  7016. + int *fuse_volt)
  7017. +{
  7018. + return -EPERM;
  7019. +}
  7020. +
  7021. +static inline int cpr3_adjust_fused_open_loop_voltages(
  7022. + struct cpr3_regulator *vreg, int *fuse_volt)
  7023. +{
  7024. + return -EPERM;
  7025. +}
  7026. +
  7027. +static inline int cpr3_adjust_open_loop_voltages(struct cpr3_regulator *vreg)
  7028. +{
  7029. + return -EPERM;
  7030. +}
  7031. +
  7032. +static inline int cpr3_quot_adjustment(int ro_scale, int volt_adjust)
  7033. +{
  7034. + return 0;
  7035. +}
  7036. +
  7037. +static inline int cpr3_voltage_adjustment(int ro_scale, int quot_adjust)
  7038. +{
  7039. + return 0;
  7040. +}
  7041. +
  7042. +static inline int cpr3_parse_closed_loop_voltage_adjustments(
  7043. + struct cpr3_regulator *vreg, u64 *ro_sel,
  7044. + int *volt_adjust, int *volt_adjust_fuse, int *ro_scale)
  7045. +{
  7046. + return 0;
  7047. +}
  7048. +
  7049. +static inline int cpr4_parse_core_count_temp_voltage_adj(
  7050. + struct cpr3_regulator *vreg, bool use_corner_band)
  7051. +{
  7052. + return 0;
  7053. +}
  7054. +
  7055. +static inline int cpr3_apm_init(struct cpr3_controller *ctrl)
  7056. +{
  7057. + return 0;
  7058. +}
  7059. +
  7060. +static inline int cpr3_mem_acc_init(struct cpr3_regulator *vreg)
  7061. +{
  7062. + return 0;
  7063. +}
  7064. +
  7065. +static inline void cprh_adjust_voltages_for_apm(struct cpr3_regulator *vreg)
  7066. +{
  7067. +}
  7068. +
  7069. +static inline void cprh_adjust_voltages_for_mem_acc(struct cpr3_regulator *vreg)
  7070. +{
  7071. +}
  7072. +
  7073. +static inline int cpr3_adjust_target_quotients(struct cpr3_regulator *vreg,
  7074. + int *fuse_volt_adjust)
  7075. +{
  7076. + return 0;
  7077. +}
  7078. +
  7079. +static inline int
  7080. +cpr3_handle_temp_open_loop_adjustment(struct cpr3_controller *ctrl,
  7081. + bool is_cold)
  7082. +{
  7083. + return 0;
  7084. +}
  7085. +
  7086. +static inline bool
  7087. +cpr3_can_adjust_cold_temp(struct cpr3_regulator *vreg)
  7088. +{
  7089. + return false;
  7090. +}
  7091. +
  7092. +static inline int
  7093. +cpr3_get_cold_temp_threshold(struct cpr3_regulator *vreg, int *cold_temp)
  7094. +{
  7095. + return 0;
  7096. +}
  7097. +#endif /* CONFIG_REGULATOR_CPR3 */
  7098. +
  7099. +#endif /* __REGULATOR_CPR_REGULATOR_H__ */
  7100. --- /dev/null
  7101. +++ b/drivers/regulator/cpr3-util.c
  7102. @@ -0,0 +1,2750 @@
  7103. +/*
  7104. + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
  7105. + *
  7106. + * This program is free software; you can redistribute it and/or modify
  7107. + * it under the terms of the GNU General Public License version 2 and
  7108. + * only version 2 as published by the Free Software Foundation.
  7109. + *
  7110. + * This program is distributed in the hope that it will be useful,
  7111. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  7112. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  7113. + * GNU General Public License for more details.
  7114. + */
  7115. +
  7116. +/*
  7117. + * This file contains utility functions to be used by platform specific CPR3
  7118. + * regulator drivers.
  7119. + */
  7120. +
  7121. +#define pr_fmt(fmt) "%s: " fmt, __func__
  7122. +
  7123. +#include <linux/cpumask.h>
  7124. +#include <linux/device.h>
  7125. +#include <linux/io.h>
  7126. +#include <linux/kernel.h>
  7127. +#include <linux/of.h>
  7128. +#include <linux/platform_device.h>
  7129. +#include <linux/slab.h>
  7130. +#include <linux/types.h>
  7131. +
  7132. +#include <soc/qcom/socinfo.h>
  7133. +
  7134. +#include "cpr3-regulator.h"
  7135. +
  7136. +#define BYTES_PER_FUSE_ROW 8
  7137. +#define MAX_FUSE_ROW_BIT 63
  7138. +
  7139. +#define CPR3_CONSECUTIVE_UP_DOWN_MIN 0
  7140. +#define CPR3_CONSECUTIVE_UP_DOWN_MAX 15
  7141. +#define CPR3_UP_DOWN_THRESHOLD_MIN 0
  7142. +#define CPR3_UP_DOWN_THRESHOLD_MAX 31
  7143. +#define CPR3_STEP_QUOT_MIN 0
  7144. +#define CPR3_STEP_QUOT_MAX 63
  7145. +#define CPR3_IDLE_CLOCKS_MIN 0
  7146. +#define CPR3_IDLE_CLOCKS_MAX 31
  7147. +
  7148. +/* This constant has units of uV/mV so 1000 corresponds to 100%. */
  7149. +#define CPR3_AGING_DERATE_UNITY 1000
  7150. +
  7151. +/**
  7152. + * cpr3_allocate_regulators() - allocate and initialize CPR3 regulators for a
  7153. + * given thread based upon device tree data
  7154. + * @thread: Pointer to the CPR3 thread
  7155. + *
  7156. + * This function allocates the thread->vreg array based upon the number of
  7157. + * device tree regulator subnodes. It also initializes generic elements of each
  7158. + * regulator struct such as name, of_node, and thread.
  7159. + *
  7160. + * Return: 0 on success, errno on failure
  7161. + */
  7162. +static int cpr3_allocate_regulators(struct cpr3_thread *thread)
  7163. +{
  7164. + struct device_node *node;
  7165. + int i, rc;
  7166. +
  7167. + thread->vreg_count = 0;
  7168. +
  7169. + for_each_available_child_of_node(thread->of_node, node) {
  7170. + thread->vreg_count++;
  7171. + }
  7172. +
  7173. + thread->vreg = devm_kcalloc(thread->ctrl->dev, thread->vreg_count,
  7174. + sizeof(*thread->vreg), GFP_KERNEL);
  7175. + if (!thread->vreg)
  7176. + return -ENOMEM;
  7177. +
  7178. + i = 0;
  7179. + for_each_available_child_of_node(thread->of_node, node) {
  7180. + thread->vreg[i].of_node = node;
  7181. + thread->vreg[i].thread = thread;
  7182. +
  7183. + rc = of_property_read_string(node, "regulator-name",
  7184. + &thread->vreg[i].name);
  7185. + if (rc) {
  7186. + dev_err(thread->ctrl->dev, "could not find regulator name, rc=%d\n",
  7187. + rc);
  7188. + return rc;
  7189. + }
  7190. +
  7191. + i++;
  7192. + }
  7193. +
  7194. + return 0;
  7195. +}
  7196. +
  7197. +/**
  7198. + * cpr3_allocate_threads() - allocate and initialize CPR3 threads for a given
  7199. + * controller based upon device tree data
  7200. + * @ctrl: Pointer to the CPR3 controller
  7201. + * @min_thread_id: Minimum allowed hardware thread ID for this controller
  7202. + * @max_thread_id: Maximum allowed hardware thread ID for this controller
  7203. + *
  7204. + * This function allocates the ctrl->thread array based upon the number of
  7205. + * device tree thread subnodes. It also initializes generic elements of each
  7206. + * thread struct such as thread_id, of_node, ctrl, and vreg array.
  7207. + *
  7208. + * Return: 0 on success, errno on failure
  7209. + */
  7210. +int cpr3_allocate_threads(struct cpr3_controller *ctrl, u32 min_thread_id,
  7211. + u32 max_thread_id)
  7212. +{
  7213. + struct device *dev = ctrl->dev;
  7214. + struct device_node *thread_node;
  7215. + int i, j, rc;
  7216. +
  7217. + ctrl->thread_count = 0;
  7218. +
  7219. + for_each_available_child_of_node(dev->of_node, thread_node) {
  7220. + ctrl->thread_count++;
  7221. + }
  7222. +
  7223. + ctrl->thread = devm_kcalloc(dev, ctrl->thread_count,
  7224. + sizeof(*ctrl->thread), GFP_KERNEL);
  7225. + if (!ctrl->thread)
  7226. + return -ENOMEM;
  7227. +
  7228. + i = 0;
  7229. + for_each_available_child_of_node(dev->of_node, thread_node) {
  7230. + ctrl->thread[i].of_node = thread_node;
  7231. + ctrl->thread[i].ctrl = ctrl;
  7232. +
  7233. + rc = of_property_read_u32(thread_node, "qcom,cpr-thread-id",
  7234. + &ctrl->thread[i].thread_id);
  7235. + if (rc) {
  7236. + dev_err(dev, "could not read DT property qcom,cpr-thread-id, rc=%d\n",
  7237. + rc);
  7238. + return rc;
  7239. + }
  7240. +
  7241. + if (ctrl->thread[i].thread_id < min_thread_id ||
  7242. + ctrl->thread[i].thread_id > max_thread_id) {
  7243. + dev_err(dev, "invalid thread id = %u; not within [%u, %u]\n",
  7244. + ctrl->thread[i].thread_id, min_thread_id,
  7245. + max_thread_id);
  7246. + return -EINVAL;
  7247. + }
  7248. +
  7249. + /* Verify that the thread ID is unique for all child nodes. */
  7250. + for (j = 0; j < i; j++) {
  7251. + if (ctrl->thread[j].thread_id
  7252. + == ctrl->thread[i].thread_id) {
  7253. + dev_err(dev, "duplicate thread id = %u found\n",
  7254. + ctrl->thread[i].thread_id);
  7255. + return -EINVAL;
  7256. + }
  7257. + }
  7258. +
  7259. + rc = cpr3_allocate_regulators(&ctrl->thread[i]);
  7260. + if (rc)
  7261. + return rc;
  7262. +
  7263. + i++;
  7264. + }
  7265. +
  7266. + return 0;
  7267. +}
  7268. +
  7269. +/**
  7270. + * cpr3_map_fuse_base() - ioremap the base address of the fuse region
  7271. + * @ctrl: Pointer to the CPR3 controller
  7272. + * @pdev: Platform device pointer for the CPR3 controller
  7273. + *
  7274. + * Return: 0 on success, errno on failure
  7275. + */
  7276. +int cpr3_map_fuse_base(struct cpr3_controller *ctrl,
  7277. + struct platform_device *pdev)
  7278. +{
  7279. + struct resource *res;
  7280. +
  7281. + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fuse_base");
  7282. + if (!res || !res->start) {
  7283. + dev_err(&pdev->dev, "fuse base address is missing\n");
  7284. + return -ENXIO;
  7285. + }
  7286. +
  7287. + ctrl->fuse_base = devm_ioremap(&pdev->dev, res->start,
  7288. + resource_size(res));
  7289. +
  7290. + return 0;
  7291. +}
  7292. +
  7293. +/**
  7294. + * cpr3_read_tcsr_setting - reads the CPR setting bits from TCSR register
  7295. + * @ctrl: Pointer to the CPR3 controller
  7296. + * @pdev: Platform device pointer for the CPR3 controller
  7297. + * @start: start bit in TCSR register
  7298. + * @end: end bit in TCSR register
  7299. + *
  7300. + * Return: 0 on success, errno on failure
  7301. + */
  7302. +int cpr3_read_tcsr_setting(struct cpr3_controller *ctrl,
  7303. + struct platform_device *pdev, u8 start, u8 end)
  7304. +{
  7305. + struct resource *res;
  7306. + void __iomem *tcsr_reg;
  7307. + u32 val;
  7308. +
  7309. + res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
  7310. + "cpr_tcsr_reg");
  7311. + if (!res || !res->start)
  7312. + return 0;
  7313. +
  7314. + tcsr_reg = ioremap(res->start, resource_size(res));
  7315. + if (!tcsr_reg) {
  7316. + dev_err(&pdev->dev, "tcsr ioremap failed\n");
  7317. + return 0;
  7318. + }
  7319. +
  7320. + val = readl_relaxed(tcsr_reg);
  7321. + val &= GENMASK(end, start);
  7322. + val >>= start;
  7323. +
  7324. + switch (val) {
  7325. + case 1:
  7326. + ctrl->cpr_global_setting = CPR_DISABLED;
  7327. + break;
  7328. + case 2:
  7329. + ctrl->cpr_global_setting = CPR_OPEN_LOOP_EN;
  7330. + break;
  7331. + case 3:
  7332. + ctrl->cpr_global_setting = CPR_CLOSED_LOOP_EN;
  7333. + break;
  7334. + default:
  7335. + ctrl->cpr_global_setting = CPR_DEFAULT;
  7336. + }
  7337. +
  7338. + iounmap(tcsr_reg);
  7339. +
  7340. + return 0;
  7341. +}
  7342. +
  7343. +/**
  7344. + * cpr3_read_fuse_param() - reads a CPR3 fuse parameter out of eFuses
  7345. + * @fuse_base_addr: Virtual memory address of the eFuse base address
  7346. + * @param: Null terminated array of fuse param segments to read
  7347. + * from
  7348. + * @param_value: Output with value read from the eFuses
  7349. + *
  7350. + * This function reads from each of the parameter segments listed in the param
  7351. + * array and concatenates their values together. Reading stops when an element
  7352. + * is reached which has all 0 struct values. The total number of bits specified
  7353. + * for the fuse parameter across all segments must be less than or equal to 64.
  7354. + *
  7355. + * Return: 0 on success, errno on failure
  7356. + */
  7357. +int cpr3_read_fuse_param(void __iomem *fuse_base_addr,
  7358. + const struct cpr3_fuse_param *param, u64 *param_value)
  7359. +{
  7360. + u64 fuse_val, val;
  7361. + int bits;
  7362. + int bits_total = 0;
  7363. +
  7364. + *param_value = 0;
  7365. +
  7366. + while (param->row || param->bit_start || param->bit_end) {
  7367. + if (param->bit_start > param->bit_end
  7368. + || param->bit_end > MAX_FUSE_ROW_BIT) {
  7369. + pr_err("Invalid fuse parameter segment: row=%u, start=%u, end=%u\n",
  7370. + param->row, param->bit_start, param->bit_end);
  7371. + return -EINVAL;
  7372. + }
  7373. +
  7374. + bits = param->bit_end - param->bit_start + 1;
  7375. + if (bits_total + bits > 64) {
  7376. + pr_err("Invalid fuse parameter segments; total bits = %d\n",
  7377. + bits_total + bits);
  7378. + return -EINVAL;
  7379. + }
  7380. +
  7381. + fuse_val = readq_relaxed(fuse_base_addr
  7382. + + param->row * BYTES_PER_FUSE_ROW);
  7383. + val = (fuse_val >> param->bit_start) & ((1ULL << bits) - 1);
  7384. + *param_value |= val << bits_total;
  7385. + bits_total += bits;
  7386. +
  7387. + param++;
  7388. + }
  7389. +
  7390. + return 0;
  7391. +}
  7392. +
  7393. +/**
  7394. + * cpr3_convert_open_loop_voltage_fuse() - converts an open loop voltage fuse
  7395. + * value into an absolute voltage with units of microvolts
  7396. + * @ref_volt: Reference voltage in microvolts
  7397. + * @step_volt: The step size in microvolts of the fuse LSB
  7398. + * @fuse: Open loop voltage fuse value
  7399. + * @fuse_len: The bit length of the fuse value
  7400. + *
  7401. + * The MSB of the fuse parameter corresponds to a sign bit. If it is set, then
  7402. + * the lower bits correspond to the number of steps to go down from the
  7403. + * reference voltage. If it is not set, then the lower bits correspond to the
  7404. + * number of steps to go up from the reference voltage.
  7405. + */
  7406. +int cpr3_convert_open_loop_voltage_fuse(int ref_volt, int step_volt, u32 fuse,
  7407. + int fuse_len)
  7408. +{
  7409. + int sign, steps;
  7410. +
  7411. + sign = (fuse & (1 << (fuse_len - 1))) ? -1 : 1;
  7412. + steps = fuse & ((1 << (fuse_len - 1)) - 1);
  7413. +
  7414. + return ref_volt + sign * steps * step_volt;
  7415. +}
  7416. +
  7417. +/**
  7418. + * cpr3_interpolate() - performs linear interpolation
  7419. + * @x1 Lower known x value
  7420. + * @y1 Lower known y value
  7421. + * @x2 Upper known x value
  7422. + * @y2 Upper known y value
  7423. + * @x Intermediate x value
  7424. + *
  7425. + * Returns y where (x, y) falls on the line between (x1, y1) and (x2, y2).
  7426. + * It is required that x1 < x2, y1 <= y2, and x1 <= x <= x2. If these
  7427. + * conditions are not met, then y2 will be returned.
  7428. + */
  7429. +u64 cpr3_interpolate(u64 x1, u64 y1, u64 x2, u64 y2, u64 x)
  7430. +{
  7431. + u64 temp;
  7432. +
  7433. + if (x1 >= x2 || y1 > y2 || x1 > x || x > x2)
  7434. + return y2;
  7435. +
  7436. + temp = (x2 - x) * (y2 - y1);
  7437. + do_div(temp, (u32)(x2 - x1));
  7438. +
  7439. + return y2 - temp;
  7440. +}
  7441. +
  7442. +/**
  7443. + * cpr3_parse_array_property() - fill an array from a portion of the values
  7444. + * specified for a device tree property
  7445. + * @vreg: Pointer to the CPR3 regulator
  7446. + * @prop_name: The name of the device tree property to read from
  7447. + * @tuple_size: The number of elements in each tuple
  7448. + * @out: Output data array which must be of size tuple_size
  7449. + *
  7450. + * cpr3_parse_common_corner_data() must be called for vreg before this function
  7451. + * is called so that fuse combo and speed bin size elements are initialized.
  7452. + *
  7453. + * Three formats are supported for the device tree property:
  7454. + * 1. Length == tuple_size
  7455. + * (reading begins at index 0)
  7456. + * 2. Length == tuple_size * vreg->fuse_combos_supported
  7457. + * (reading begins at index tuple_size * vreg->fuse_combo)
  7458. + * 3. Length == tuple_size * vreg->speed_bins_supported
  7459. + * (reading begins at index tuple_size * vreg->speed_bin_fuse)
  7460. + *
  7461. + * All other property lengths are treated as errors.
  7462. + *
  7463. + * Return: 0 on success, errno on failure
  7464. + */
  7465. +int cpr3_parse_array_property(struct cpr3_regulator *vreg,
  7466. + const char *prop_name, int tuple_size, u32 *out)
  7467. +{
  7468. + struct device_node *node = vreg->of_node;
  7469. + int len = 0;
  7470. + int i, offset, rc;
  7471. +
  7472. + if (!of_find_property(node, prop_name, &len)) {
  7473. + cpr3_err(vreg, "property %s is missing\n", prop_name);
  7474. + return -EINVAL;
  7475. + }
  7476. +
  7477. + if (len == tuple_size * sizeof(u32)) {
  7478. + offset = 0;
  7479. + } else if (len == tuple_size * vreg->fuse_combos_supported
  7480. + * sizeof(u32)) {
  7481. + offset = tuple_size * vreg->fuse_combo;
  7482. + } else if (vreg->speed_bins_supported > 0 &&
  7483. + len == tuple_size * vreg->speed_bins_supported * sizeof(u32)) {
  7484. + offset = tuple_size * vreg->speed_bin_fuse;
  7485. + } else {
  7486. + if (vreg->speed_bins_supported > 0)
  7487. + cpr3_err(vreg, "property %s has invalid length=%d, should be %zu, %zu, or %zu\n",
  7488. + prop_name, len,
  7489. + tuple_size * sizeof(u32),
  7490. + tuple_size * vreg->speed_bins_supported
  7491. + * sizeof(u32),
  7492. + tuple_size * vreg->fuse_combos_supported
  7493. + * sizeof(u32));
  7494. + else
  7495. + cpr3_err(vreg, "property %s has invalid length=%d, should be %zu or %zu\n",
  7496. + prop_name, len,
  7497. + tuple_size * sizeof(u32),
  7498. + tuple_size * vreg->fuse_combos_supported
  7499. + * sizeof(u32));
  7500. + return -EINVAL;
  7501. + }
  7502. +
  7503. + for (i = 0; i < tuple_size; i++) {
  7504. + rc = of_property_read_u32_index(node, prop_name, offset + i,
  7505. + &out[i]);
  7506. + if (rc) {
  7507. + cpr3_err(vreg, "error reading property %s, rc=%d\n",
  7508. + prop_name, rc);
  7509. + return rc;
  7510. + }
  7511. + }
  7512. +
  7513. + return 0;
  7514. +}
  7515. +
  7516. +/**
  7517. + * cpr3_parse_corner_array_property() - fill a per-corner array from a portion
  7518. + * of the values specified for a device tree property
  7519. + * @vreg: Pointer to the CPR3 regulator
  7520. + * @prop_name: The name of the device tree property to read from
  7521. + * @tuple_size: The number of elements in each per-corner tuple
  7522. + * @out: Output data array which must be of size:
  7523. + * tuple_size * vreg->corner_count
  7524. + *
  7525. + * cpr3_parse_common_corner_data() must be called for vreg before this function
  7526. + * is called so that fuse combo and speed bin size elements are initialized.
  7527. + *
  7528. + * Three formats are supported for the device tree property:
  7529. + * 1. Length == tuple_size * vreg->corner_count
  7530. + * (reading begins at index 0)
  7531. + * 2. Length == tuple_size * vreg->fuse_combo_corner_sum
  7532. + * (reading begins at index tuple_size * vreg->fuse_combo_offset)
  7533. + * 3. Length == tuple_size * vreg->speed_bin_corner_sum
  7534. + * (reading begins at index tuple_size * vreg->speed_bin_offset)
  7535. + *
  7536. + * All other property lengths are treated as errors.
  7537. + *
  7538. + * Return: 0 on success, errno on failure
  7539. + */
  7540. +int cpr3_parse_corner_array_property(struct cpr3_regulator *vreg,
  7541. + const char *prop_name, int tuple_size, u32 *out)
  7542. +{
  7543. + struct device_node *node = vreg->of_node;
  7544. + int len = 0;
  7545. + int i, offset, rc;
  7546. +
  7547. + if (!of_find_property(node, prop_name, &len)) {
  7548. + cpr3_err(vreg, "property %s is missing\n", prop_name);
  7549. + return -EINVAL;
  7550. + }
  7551. +
  7552. + if (len == tuple_size * vreg->corner_count * sizeof(u32)) {
  7553. + offset = 0;
  7554. + } else if (len == tuple_size * vreg->fuse_combo_corner_sum
  7555. + * sizeof(u32)) {
  7556. + offset = tuple_size * vreg->fuse_combo_offset;
  7557. + } else if (vreg->speed_bin_corner_sum > 0 &&
  7558. + len == tuple_size * vreg->speed_bin_corner_sum * sizeof(u32)) {
  7559. + offset = tuple_size * vreg->speed_bin_offset;
  7560. + } else {
  7561. + if (vreg->speed_bin_corner_sum > 0)
  7562. + cpr3_err(vreg, "property %s has invalid length=%d, should be %zu, %zu, or %zu\n",
  7563. + prop_name, len,
  7564. + tuple_size * vreg->corner_count * sizeof(u32),
  7565. + tuple_size * vreg->speed_bin_corner_sum
  7566. + * sizeof(u32),
  7567. + tuple_size * vreg->fuse_combo_corner_sum
  7568. + * sizeof(u32));
  7569. + else
  7570. + cpr3_err(vreg, "property %s has invalid length=%d, should be %zu or %zu\n",
  7571. + prop_name, len,
  7572. + tuple_size * vreg->corner_count * sizeof(u32),
  7573. + tuple_size * vreg->fuse_combo_corner_sum
  7574. + * sizeof(u32));
  7575. + return -EINVAL;
  7576. + }
  7577. +
  7578. + for (i = 0; i < tuple_size * vreg->corner_count; i++) {
  7579. + rc = of_property_read_u32_index(node, prop_name, offset + i,
  7580. + &out[i]);
  7581. + if (rc) {
  7582. + cpr3_err(vreg, "error reading property %s, rc=%d\n",
  7583. + prop_name, rc);
  7584. + return rc;
  7585. + }
  7586. + }
  7587. +
  7588. + return 0;
  7589. +}
  7590. +
  7591. +/**
  7592. + * cpr3_parse_corner_band_array_property() - fill a per-corner band array
  7593. + * from a portion of the values specified for a device tree
  7594. + * property
  7595. + * @vreg: Pointer to the CPR3 regulator
  7596. + * @prop_name: The name of the device tree property to read from
  7597. + * @tuple_size: The number of elements in each per-corner band tuple
  7598. + * @out: Output data array which must be of size:
  7599. + * tuple_size * vreg->corner_band_count
  7600. + *
  7601. + * cpr3_parse_common_corner_data() must be called for vreg before this function
  7602. + * is called so that fuse combo and speed bin size elements are initialized.
  7603. + * In addition, corner band fuse combo and speed bin sum and offset elements
  7604. + * must be initialized prior to executing this function.
  7605. + *
  7606. + * Three formats are supported for the device tree property:
  7607. + * 1. Length == tuple_size * vreg->corner_band_count
  7608. + * (reading begins at index 0)
  7609. + * 2. Length == tuple_size * vreg->fuse_combo_corner_band_sum
  7610. + * (reading begins at index tuple_size *
  7611. + * vreg->fuse_combo_corner_band_offset)
  7612. + * 3. Length == tuple_size * vreg->speed_bin_corner_band_sum
  7613. + * (reading begins at index tuple_size *
  7614. + * vreg->speed_bin_corner_band_offset)
  7615. + *
  7616. + * All other property lengths are treated as errors.
  7617. + *
  7618. + * Return: 0 on success, errno on failure
  7619. + */
  7620. +int cpr3_parse_corner_band_array_property(struct cpr3_regulator *vreg,
  7621. + const char *prop_name, int tuple_size, u32 *out)
  7622. +{
  7623. + struct device_node *node = vreg->of_node;
  7624. + int len = 0;
  7625. + int i, offset, rc;
  7626. +
  7627. + if (!of_find_property(node, prop_name, &len)) {
  7628. + cpr3_err(vreg, "property %s is missing\n", prop_name);
  7629. + return -EINVAL;
  7630. + }
  7631. +
  7632. + if (len == tuple_size * vreg->corner_band_count * sizeof(u32)) {
  7633. + offset = 0;
  7634. + } else if (len == tuple_size * vreg->fuse_combo_corner_band_sum
  7635. + * sizeof(u32)) {
  7636. + offset = tuple_size * vreg->fuse_combo_corner_band_offset;
  7637. + } else if (vreg->speed_bin_corner_band_sum > 0 &&
  7638. + len == tuple_size * vreg->speed_bin_corner_band_sum *
  7639. + sizeof(u32)) {
  7640. + offset = tuple_size * vreg->speed_bin_corner_band_offset;
  7641. + } else {
  7642. + if (vreg->speed_bin_corner_band_sum > 0)
  7643. + cpr3_err(vreg, "property %s has invalid length=%d, should be %zu, %zu, or %zu\n",
  7644. + prop_name, len,
  7645. + tuple_size * vreg->corner_band_count *
  7646. + sizeof(u32),
  7647. + tuple_size * vreg->speed_bin_corner_band_sum
  7648. + * sizeof(u32),
  7649. + tuple_size * vreg->fuse_combo_corner_band_sum
  7650. + * sizeof(u32));
  7651. + else
  7652. + cpr3_err(vreg, "property %s has invalid length=%d, should be %zu or %zu\n",
  7653. + prop_name, len,
  7654. + tuple_size * vreg->corner_band_count *
  7655. + sizeof(u32),
  7656. + tuple_size * vreg->fuse_combo_corner_band_sum
  7657. + * sizeof(u32));
  7658. + return -EINVAL;
  7659. + }
  7660. +
  7661. + for (i = 0; i < tuple_size * vreg->corner_band_count; i++) {
  7662. + rc = of_property_read_u32_index(node, prop_name, offset + i,
  7663. + &out[i]);
  7664. + if (rc) {
  7665. + cpr3_err(vreg, "error reading property %s, rc=%d\n",
  7666. + prop_name, rc);
  7667. + return rc;
  7668. + }
  7669. + }
  7670. +
  7671. + return 0;
  7672. +}
  7673. +
  7674. +/**
  7675. + * cpr3_parse_common_corner_data() - parse common CPR3 properties relating to
  7676. + * the corners supported by a CPR3 regulator from device tree
  7677. + * @vreg: Pointer to the CPR3 regulator
  7678. + *
  7679. + * This function reads, validates, and utilizes the following device tree
  7680. + * properties: qcom,cpr-fuse-corners, qcom,cpr-fuse-combos, qcom,cpr-speed-bins,
  7681. + * qcom,cpr-speed-bin-corners, qcom,cpr-corners, qcom,cpr-voltage-ceiling,
  7682. + * qcom,cpr-voltage-floor, qcom,corner-frequencies,
  7683. + * and qcom,cpr-corner-fmax-map.
  7684. + *
  7685. + * It initializes these CPR3 regulator elements: corner, corner_count,
  7686. + * fuse_combos_supported, fuse_corner_map, and speed_bins_supported. It
  7687. + * initializes these elements for each corner: ceiling_volt, floor_volt,
  7688. + * proc_freq, and cpr_fuse_corner.
  7689. + *
  7690. + * It requires that the following CPR3 regulator elements be initialized before
  7691. + * being called: fuse_corner_count, fuse_combo, and speed_bin_fuse.
  7692. + *
  7693. + * Return: 0 on success, errno on failure
  7694. + */
  7695. +int cpr3_parse_common_corner_data(struct cpr3_regulator *vreg)
  7696. +{
  7697. + struct device_node *node = vreg->of_node;
  7698. + struct cpr3_controller *ctrl = vreg->thread->ctrl;
  7699. + u32 max_fuse_combos, fuse_corners, aging_allowed = 0;
  7700. + u32 max_speed_bins = 0;
  7701. + u32 *combo_corners;
  7702. + u32 *speed_bin_corners;
  7703. + u32 *temp;
  7704. + int i, j, rc;
  7705. +
  7706. + rc = of_property_read_u32(node, "qcom,cpr-fuse-corners", &fuse_corners);
  7707. + if (rc) {
  7708. + cpr3_err(vreg, "error reading property qcom,cpr-fuse-corners, rc=%d\n",
  7709. + rc);
  7710. + return rc;
  7711. + }
  7712. +
  7713. + if (vreg->fuse_corner_count != fuse_corners) {
  7714. + cpr3_err(vreg, "device tree config supports %d fuse corners but the hardware has %d fuse corners\n",
  7715. + fuse_corners, vreg->fuse_corner_count);
  7716. + return -EINVAL;
  7717. + }
  7718. +
  7719. + rc = of_property_read_u32(node, "qcom,cpr-fuse-combos",
  7720. + &max_fuse_combos);
  7721. + if (rc) {
  7722. + cpr3_err(vreg, "error reading property qcom,cpr-fuse-combos, rc=%d\n",
  7723. + rc);
  7724. + return rc;
  7725. + }
  7726. +
  7727. + /*
  7728. + * Sanity check against arbitrarily large value to avoid excessive
  7729. + * memory allocation.
  7730. + */
  7731. + if (max_fuse_combos > 100 || max_fuse_combos == 0) {
  7732. + cpr3_err(vreg, "qcom,cpr-fuse-combos is invalid: %u\n",
  7733. + max_fuse_combos);
  7734. + return -EINVAL;
  7735. + }
  7736. +
  7737. + if (vreg->fuse_combo >= max_fuse_combos) {
  7738. + cpr3_err(vreg, "device tree config supports fuse combos 0-%u but the hardware has combo %d\n",
  7739. + max_fuse_combos - 1, vreg->fuse_combo);
  7740. + BUG_ON(1);
  7741. + return -EINVAL;
  7742. + }
  7743. +
  7744. + vreg->fuse_combos_supported = max_fuse_combos;
  7745. +
  7746. + of_property_read_u32(node, "qcom,cpr-speed-bins", &max_speed_bins);
  7747. +
  7748. + /*
  7749. + * Sanity check against arbitrarily large value to avoid excessive
  7750. + * memory allocation.
  7751. + */
  7752. + if (max_speed_bins > 100) {
  7753. + cpr3_err(vreg, "qcom,cpr-speed-bins is invalid: %u\n",
  7754. + max_speed_bins);
  7755. + return -EINVAL;
  7756. + }
  7757. +
  7758. + if (max_speed_bins && vreg->speed_bin_fuse >= max_speed_bins) {
  7759. + cpr3_err(vreg, "device tree config supports speed bins 0-%u but the hardware has speed bin %d\n",
  7760. + max_speed_bins - 1, vreg->speed_bin_fuse);
  7761. + BUG();
  7762. + return -EINVAL;
  7763. + }
  7764. +
  7765. + vreg->speed_bins_supported = max_speed_bins;
  7766. +
  7767. + combo_corners = kcalloc(vreg->fuse_combos_supported,
  7768. + sizeof(*combo_corners), GFP_KERNEL);
  7769. + if (!combo_corners)
  7770. + return -ENOMEM;
  7771. +
  7772. + rc = of_property_read_u32_array(node, "qcom,cpr-corners", combo_corners,
  7773. + vreg->fuse_combos_supported);
  7774. + if (rc == -EOVERFLOW) {
  7775. + /* Single value case */
  7776. + rc = of_property_read_u32(node, "qcom,cpr-corners",
  7777. + combo_corners);
  7778. + for (i = 1; i < vreg->fuse_combos_supported; i++)
  7779. + combo_corners[i] = combo_corners[0];
  7780. + }
  7781. + if (rc) {
  7782. + cpr3_err(vreg, "error reading property qcom,cpr-corners, rc=%d\n",
  7783. + rc);
  7784. + kfree(combo_corners);
  7785. + return rc;
  7786. + }
  7787. +
  7788. + vreg->fuse_combo_offset = 0;
  7789. + vreg->fuse_combo_corner_sum = 0;
  7790. + for (i = 0; i < vreg->fuse_combos_supported; i++) {
  7791. + vreg->fuse_combo_corner_sum += combo_corners[i];
  7792. + if (i < vreg->fuse_combo)
  7793. + vreg->fuse_combo_offset += combo_corners[i];
  7794. + }
  7795. +
  7796. + vreg->corner_count = combo_corners[vreg->fuse_combo];
  7797. +
  7798. + kfree(combo_corners);
  7799. +
  7800. + vreg->speed_bin_offset = 0;
  7801. + vreg->speed_bin_corner_sum = 0;
  7802. + if (vreg->speed_bins_supported > 0) {
  7803. + speed_bin_corners = kcalloc(vreg->speed_bins_supported,
  7804. + sizeof(*speed_bin_corners), GFP_KERNEL);
  7805. + if (!speed_bin_corners)
  7806. + return -ENOMEM;
  7807. +
  7808. + rc = of_property_read_u32_array(node,
  7809. + "qcom,cpr-speed-bin-corners", speed_bin_corners,
  7810. + vreg->speed_bins_supported);
  7811. + if (rc) {
  7812. + cpr3_err(vreg, "error reading property qcom,cpr-speed-bin-corners, rc=%d\n",
  7813. + rc);
  7814. + kfree(speed_bin_corners);
  7815. + return rc;
  7816. + }
  7817. +
  7818. + for (i = 0; i < vreg->speed_bins_supported; i++) {
  7819. + vreg->speed_bin_corner_sum += speed_bin_corners[i];
  7820. + if (i < vreg->speed_bin_fuse)
  7821. + vreg->speed_bin_offset += speed_bin_corners[i];
  7822. + }
  7823. +
  7824. + if (speed_bin_corners[vreg->speed_bin_fuse]
  7825. + != vreg->corner_count) {
  7826. + cpr3_err(vreg, "qcom,cpr-corners and qcom,cpr-speed-bin-corners conflict on number of corners: %d vs %u\n",
  7827. + vreg->corner_count,
  7828. + speed_bin_corners[vreg->speed_bin_fuse]);
  7829. + kfree(speed_bin_corners);
  7830. + return -EINVAL;
  7831. + }
  7832. +
  7833. + kfree(speed_bin_corners);
  7834. + }
  7835. +
  7836. + vreg->corner = devm_kcalloc(ctrl->dev, vreg->corner_count,
  7837. + sizeof(*vreg->corner), GFP_KERNEL);
  7838. + temp = kcalloc(vreg->corner_count, sizeof(*temp), GFP_KERNEL);
  7839. + if (!vreg->corner || !temp)
  7840. + return -ENOMEM;
  7841. +
  7842. + rc = cpr3_parse_corner_array_property(vreg, "qcom,cpr-voltage-ceiling",
  7843. + 1, temp);
  7844. + if (rc)
  7845. + goto free_temp;
  7846. + for (i = 0; i < vreg->corner_count; i++) {
  7847. + vreg->corner[i].ceiling_volt
  7848. + = CPR3_ROUND(temp[i], ctrl->step_volt);
  7849. + vreg->corner[i].abs_ceiling_volt = vreg->corner[i].ceiling_volt;
  7850. + }
  7851. +
  7852. + rc = cpr3_parse_corner_array_property(vreg, "qcom,cpr-voltage-floor",
  7853. + 1, temp);
  7854. + if (rc)
  7855. + goto free_temp;
  7856. + for (i = 0; i < vreg->corner_count; i++)
  7857. + vreg->corner[i].floor_volt
  7858. + = CPR3_ROUND(temp[i], ctrl->step_volt);
  7859. +
  7860. + /* Validate ceiling and floor values */
  7861. + for (i = 0; i < vreg->corner_count; i++) {
  7862. + if (vreg->corner[i].floor_volt
  7863. + > vreg->corner[i].ceiling_volt) {
  7864. + cpr3_err(vreg, "CPR floor[%d]=%d > ceiling[%d]=%d uV\n",
  7865. + i, vreg->corner[i].floor_volt,
  7866. + i, vreg->corner[i].ceiling_volt);
  7867. + rc = -EINVAL;
  7868. + goto free_temp;
  7869. + }
  7870. + }
  7871. +
  7872. + /* Load optional system-supply voltages */
  7873. + if (of_find_property(vreg->of_node, "qcom,system-voltage", NULL)) {
  7874. + rc = cpr3_parse_corner_array_property(vreg,
  7875. + "qcom,system-voltage", 1, temp);
  7876. + if (rc)
  7877. + goto free_temp;
  7878. + for (i = 0; i < vreg->corner_count; i++)
  7879. + vreg->corner[i].system_volt = temp[i];
  7880. + }
  7881. +
  7882. + rc = cpr3_parse_corner_array_property(vreg, "qcom,corner-frequencies",
  7883. + 1, temp);
  7884. + if (rc)
  7885. + goto free_temp;
  7886. + for (i = 0; i < vreg->corner_count; i++)
  7887. + vreg->corner[i].proc_freq = temp[i];
  7888. +
  7889. + /* Validate frequencies */
  7890. + for (i = 1; i < vreg->corner_count; i++) {
  7891. + if (vreg->corner[i].proc_freq
  7892. + < vreg->corner[i - 1].proc_freq) {
  7893. + cpr3_err(vreg, "invalid frequency: freq[%d]=%u < freq[%d]=%u\n",
  7894. + i, vreg->corner[i].proc_freq, i - 1,
  7895. + vreg->corner[i - 1].proc_freq);
  7896. + rc = -EINVAL;
  7897. + goto free_temp;
  7898. + }
  7899. + }
  7900. +
  7901. + vreg->fuse_corner_map = devm_kcalloc(ctrl->dev, vreg->fuse_corner_count,
  7902. + sizeof(*vreg->fuse_corner_map), GFP_KERNEL);
  7903. + if (!vreg->fuse_corner_map) {
  7904. + rc = -ENOMEM;
  7905. + goto free_temp;
  7906. + }
  7907. +
  7908. + rc = cpr3_parse_array_property(vreg, "qcom,cpr-corner-fmax-map",
  7909. + vreg->fuse_corner_count, temp);
  7910. + if (rc)
  7911. + goto free_temp;
  7912. + for (i = 0; i < vreg->fuse_corner_count; i++) {
  7913. + vreg->fuse_corner_map[i] = temp[i] - CPR3_CORNER_OFFSET;
  7914. + if (temp[i] < CPR3_CORNER_OFFSET
  7915. + || temp[i] > vreg->corner_count + CPR3_CORNER_OFFSET) {
  7916. + cpr3_err(vreg, "invalid corner value specified in qcom,cpr-corner-fmax-map: %u\n",
  7917. + temp[i]);
  7918. + rc = -EINVAL;
  7919. + goto free_temp;
  7920. + } else if (i > 0 && temp[i - 1] >= temp[i]) {
  7921. + cpr3_err(vreg, "invalid corner %u less than or equal to previous corner %u\n",
  7922. + temp[i], temp[i - 1]);
  7923. + rc = -EINVAL;
  7924. + goto free_temp;
  7925. + }
  7926. + }
  7927. + if (temp[vreg->fuse_corner_count - 1] != vreg->corner_count)
  7928. + cpr3_debug(vreg, "Note: highest Fmax corner %u in qcom,cpr-corner-fmax-map does not match highest supported corner %d\n",
  7929. + temp[vreg->fuse_corner_count - 1],
  7930. + vreg->corner_count);
  7931. +
  7932. + for (i = 0; i < vreg->corner_count; i++) {
  7933. + for (j = 0; j < vreg->fuse_corner_count; j++) {
  7934. + if (i + CPR3_CORNER_OFFSET <= temp[j]) {
  7935. + vreg->corner[i].cpr_fuse_corner = j;
  7936. + break;
  7937. + }
  7938. + }
  7939. + if (j == vreg->fuse_corner_count) {
  7940. + /*
  7941. + * Handle the case where the highest fuse corner maps
  7942. + * to a corner below the highest corner.
  7943. + */
  7944. + vreg->corner[i].cpr_fuse_corner
  7945. + = vreg->fuse_corner_count - 1;
  7946. + }
  7947. + }
  7948. +
  7949. + if (of_find_property(vreg->of_node,
  7950. + "qcom,allow-aging-voltage-adjustment", NULL)) {
  7951. + rc = cpr3_parse_array_property(vreg,
  7952. + "qcom,allow-aging-voltage-adjustment",
  7953. + 1, &aging_allowed);
  7954. + if (rc)
  7955. + goto free_temp;
  7956. +
  7957. + vreg->aging_allowed = aging_allowed;
  7958. + }
  7959. +
  7960. + if (of_find_property(vreg->of_node,
  7961. + "qcom,allow-aging-open-loop-voltage-adjustment", NULL)) {
  7962. + rc = cpr3_parse_array_property(vreg,
  7963. + "qcom,allow-aging-open-loop-voltage-adjustment",
  7964. + 1, &aging_allowed);
  7965. + if (rc)
  7966. + goto free_temp;
  7967. +
  7968. + vreg->aging_allow_open_loop_adj = aging_allowed;
  7969. + }
  7970. +
  7971. + if (vreg->aging_allowed) {
  7972. + if (ctrl->aging_ref_volt <= 0) {
  7973. + cpr3_err(ctrl, "qcom,cpr-aging-ref-voltage must be specified\n");
  7974. + rc = -EINVAL;
  7975. + goto free_temp;
  7976. + }
  7977. +
  7978. + rc = cpr3_parse_array_property(vreg,
  7979. + "qcom,cpr-aging-max-voltage-adjustment",
  7980. + 1, &vreg->aging_max_adjust_volt);
  7981. + if (rc)
  7982. + goto free_temp;
  7983. +
  7984. + rc = cpr3_parse_array_property(vreg,
  7985. + "qcom,cpr-aging-ref-corner", 1, &vreg->aging_corner);
  7986. + if (rc) {
  7987. + goto free_temp;
  7988. + } else if (vreg->aging_corner < CPR3_CORNER_OFFSET
  7989. + || vreg->aging_corner > vreg->corner_count - 1
  7990. + + CPR3_CORNER_OFFSET) {
  7991. + cpr3_err(vreg, "aging reference corner=%d not in range [%d, %d]\n",
  7992. + vreg->aging_corner, CPR3_CORNER_OFFSET,
  7993. + vreg->corner_count - 1 + CPR3_CORNER_OFFSET);
  7994. + rc = -EINVAL;
  7995. + goto free_temp;
  7996. + }
  7997. + vreg->aging_corner -= CPR3_CORNER_OFFSET;
  7998. +
  7999. + if (of_find_property(vreg->of_node, "qcom,cpr-aging-derate",
  8000. + NULL)) {
  8001. + rc = cpr3_parse_corner_array_property(vreg,
  8002. + "qcom,cpr-aging-derate", 1, temp);
  8003. + if (rc)
  8004. + goto free_temp;
  8005. +
  8006. + for (i = 0; i < vreg->corner_count; i++)
  8007. + vreg->corner[i].aging_derate = temp[i];
  8008. + } else {
  8009. + for (i = 0; i < vreg->corner_count; i++)
  8010. + vreg->corner[i].aging_derate
  8011. + = CPR3_AGING_DERATE_UNITY;
  8012. + }
  8013. + }
  8014. +
  8015. +free_temp:
  8016. + kfree(temp);
  8017. + return rc;
  8018. +}
  8019. +
  8020. +/**
  8021. + * cpr3_parse_thread_u32() - parse the specified property from the CPR3 thread's
  8022. + * device tree node and verify that it is within the allowed limits
  8023. + * @thread: Pointer to the CPR3 thread
  8024. + * @propname: The name of the device tree property to read
  8025. + * @out_value: The output pointer to fill with the value read
  8026. + * @value_min: The minimum allowed property value
  8027. + * @value_max: The maximum allowed property value
  8028. + *
  8029. + * This function prints a verbose error message if the property is missing or
  8030. + * has a value which is not within the specified range.
  8031. + *
  8032. + * Return: 0 on success, errno on failure
  8033. + */
  8034. +int cpr3_parse_thread_u32(struct cpr3_thread *thread, const char *propname,
  8035. + u32 *out_value, u32 value_min, u32 value_max)
  8036. +{
  8037. + int rc;
  8038. +
  8039. + rc = of_property_read_u32(thread->of_node, propname, out_value);
  8040. + if (rc) {
  8041. + cpr3_err(thread->ctrl, "thread %u error reading property %s, rc=%d\n",
  8042. + thread->thread_id, propname, rc);
  8043. + return rc;
  8044. + }
  8045. +
  8046. + if (*out_value < value_min || *out_value > value_max) {
  8047. + cpr3_err(thread->ctrl, "thread %u %s=%u is invalid; allowed range: [%u, %u]\n",
  8048. + thread->thread_id, propname, *out_value, value_min,
  8049. + value_max);
  8050. + return -EINVAL;
  8051. + }
  8052. +
  8053. + return 0;
  8054. +}
  8055. +
  8056. +/**
  8057. + * cpr3_parse_ctrl_u32() - parse the specified property from the CPR3
  8058. + * controller's device tree node and verify that it is within the
  8059. + * allowed limits
  8060. + * @ctrl: Pointer to the CPR3 controller
  8061. + * @propname: The name of the device tree property to read
  8062. + * @out_value: The output pointer to fill with the value read
  8063. + * @value_min: The minimum allowed property value
  8064. + * @value_max: The maximum allowed property value
  8065. + *
  8066. + * This function prints a verbose error message if the property is missing or
  8067. + * has a value which is not within the specified range.
  8068. + *
  8069. + * Return: 0 on success, errno on failure
  8070. + */
  8071. +int cpr3_parse_ctrl_u32(struct cpr3_controller *ctrl, const char *propname,
  8072. + u32 *out_value, u32 value_min, u32 value_max)
  8073. +{
  8074. + int rc;
  8075. +
  8076. + rc = of_property_read_u32(ctrl->dev->of_node, propname, out_value);
  8077. + if (rc) {
  8078. + cpr3_err(ctrl, "error reading property %s, rc=%d\n",
  8079. + propname, rc);
  8080. + return rc;
  8081. + }
  8082. +
  8083. + if (*out_value < value_min || *out_value > value_max) {
  8084. + cpr3_err(ctrl, "%s=%u is invalid; allowed range: [%u, %u]\n",
  8085. + propname, *out_value, value_min, value_max);
  8086. + return -EINVAL;
  8087. + }
  8088. +
  8089. + return 0;
  8090. +}
  8091. +
  8092. +/**
  8093. + * cpr3_parse_common_thread_data() - parse common CPR3 thread properties from
  8094. + * device tree
  8095. + * @thread: Pointer to the CPR3 thread
  8096. + *
  8097. + * Return: 0 on success, errno on failure
  8098. + */
  8099. +int cpr3_parse_common_thread_data(struct cpr3_thread *thread)
  8100. +{
  8101. + int rc;
  8102. +
  8103. + rc = cpr3_parse_thread_u32(thread, "qcom,cpr-consecutive-up",
  8104. + &thread->consecutive_up, CPR3_CONSECUTIVE_UP_DOWN_MIN,
  8105. + CPR3_CONSECUTIVE_UP_DOWN_MAX);
  8106. + if (rc)
  8107. + return rc;
  8108. +
  8109. + rc = cpr3_parse_thread_u32(thread, "qcom,cpr-consecutive-down",
  8110. + &thread->consecutive_down, CPR3_CONSECUTIVE_UP_DOWN_MIN,
  8111. + CPR3_CONSECUTIVE_UP_DOWN_MAX);
  8112. + if (rc)
  8113. + return rc;
  8114. +
  8115. + rc = cpr3_parse_thread_u32(thread, "qcom,cpr-up-threshold",
  8116. + &thread->up_threshold, CPR3_UP_DOWN_THRESHOLD_MIN,
  8117. + CPR3_UP_DOWN_THRESHOLD_MAX);
  8118. + if (rc)
  8119. + return rc;
  8120. +
  8121. + rc = cpr3_parse_thread_u32(thread, "qcom,cpr-down-threshold",
  8122. + &thread->down_threshold, CPR3_UP_DOWN_THRESHOLD_MIN,
  8123. + CPR3_UP_DOWN_THRESHOLD_MAX);
  8124. + if (rc)
  8125. + return rc;
  8126. +
  8127. + return rc;
  8128. +}
  8129. +
  8130. +/**
  8131. + * cpr3_parse_irq_affinity() - parse CPR IRQ affinity information
  8132. + * @ctrl: Pointer to the CPR3 controller
  8133. + *
  8134. + * Return: 0 on success, errno on failure
  8135. + */
  8136. +static int cpr3_parse_irq_affinity(struct cpr3_controller *ctrl)
  8137. +{
  8138. + struct device_node *cpu_node;
  8139. + int i, cpu;
  8140. + int len = 0;
  8141. +
  8142. + if (!of_find_property(ctrl->dev->of_node, "qcom,cpr-interrupt-affinity",
  8143. + &len)) {
  8144. + /* No IRQ affinity required */
  8145. + return 0;
  8146. + }
  8147. +
  8148. + len /= sizeof(u32);
  8149. +
  8150. + for (i = 0; i < len; i++) {
  8151. + cpu_node = of_parse_phandle(ctrl->dev->of_node,
  8152. + "qcom,cpr-interrupt-affinity", i);
  8153. + if (!cpu_node) {
  8154. + cpr3_err(ctrl, "could not find CPU node %d\n", i);
  8155. + return -EINVAL;
  8156. + }
  8157. +
  8158. + for_each_possible_cpu(cpu) {
  8159. + if (of_get_cpu_node(cpu, NULL) == cpu_node) {
  8160. + cpumask_set_cpu(cpu, &ctrl->irq_affinity_mask);
  8161. + break;
  8162. + }
  8163. + }
  8164. + of_node_put(cpu_node);
  8165. + }
  8166. +
  8167. + return 0;
  8168. +}
  8169. +
  8170. +static int cpr3_panic_notifier_init(struct cpr3_controller *ctrl)
  8171. +{
  8172. + struct device_node *node = ctrl->dev->of_node;
  8173. + struct cpr3_panic_regs_info *panic_regs_info;
  8174. + struct cpr3_reg_info *regs;
  8175. + int i, reg_count, len, rc = 0;
  8176. +
  8177. + if (!of_find_property(node, "qcom,cpr-panic-reg-addr-list", &len)) {
  8178. + /* panic register address list not specified */
  8179. + return rc;
  8180. + }
  8181. +
  8182. + reg_count = len / sizeof(u32);
  8183. + if (!reg_count) {
  8184. + cpr3_err(ctrl, "qcom,cpr-panic-reg-addr-list has invalid len = %d\n",
  8185. + len);
  8186. + return -EINVAL;
  8187. + }
  8188. +
  8189. + if (!of_find_property(node, "qcom,cpr-panic-reg-name-list", NULL)) {
  8190. + cpr3_err(ctrl, "property qcom,cpr-panic-reg-name-list not specified\n");
  8191. + return -EINVAL;
  8192. + }
  8193. +
  8194. + len = of_property_count_strings(node, "qcom,cpr-panic-reg-name-list");
  8195. + if (reg_count != len) {
  8196. + cpr3_err(ctrl, "qcom,cpr-panic-reg-name-list should have %d strings\n",
  8197. + reg_count);
  8198. + return -EINVAL;
  8199. + }
  8200. +
  8201. + panic_regs_info = devm_kzalloc(ctrl->dev, sizeof(*panic_regs_info),
  8202. + GFP_KERNEL);
  8203. + if (!panic_regs_info)
  8204. + return -ENOMEM;
  8205. +
  8206. + regs = devm_kcalloc(ctrl->dev, reg_count, sizeof(*regs), GFP_KERNEL);
  8207. + if (!regs)
  8208. + return -ENOMEM;
  8209. +
  8210. + for (i = 0; i < reg_count; i++) {
  8211. + rc = of_property_read_string_index(node,
  8212. + "qcom,cpr-panic-reg-name-list", i,
  8213. + &(regs[i].name));
  8214. + if (rc) {
  8215. + cpr3_err(ctrl, "error reading property qcom,cpr-panic-reg-name-list, rc=%d\n",
  8216. + rc);
  8217. + return rc;
  8218. + }
  8219. +
  8220. + rc = of_property_read_u32_index(node,
  8221. + "qcom,cpr-panic-reg-addr-list", i,
  8222. + &(regs[i].addr));
  8223. + if (rc) {
  8224. + cpr3_err(ctrl, "error reading property qcom,cpr-panic-reg-addr-list, rc=%d\n",
  8225. + rc);
  8226. + return rc;
  8227. + }
  8228. + regs[i].virt_addr = devm_ioremap(ctrl->dev, regs[i].addr, 0x4);
  8229. + if (!regs[i].virt_addr) {
  8230. + pr_err("Unable to map panic register addr 0x%08x\n",
  8231. + regs[i].addr);
  8232. + return -EINVAL;
  8233. + }
  8234. + regs[i].value = 0xFFFFFFFF;
  8235. + }
  8236. +
  8237. + panic_regs_info->reg_count = reg_count;
  8238. + panic_regs_info->regs = regs;
  8239. + ctrl->panic_regs_info = panic_regs_info;
  8240. +
  8241. + return rc;
  8242. +}
  8243. +
  8244. +/**
  8245. + * cpr3_parse_common_ctrl_data() - parse common CPR3 controller properties from
  8246. + * device tree
  8247. + * @ctrl: Pointer to the CPR3 controller
  8248. + *
  8249. + * Return: 0 on success, errno on failure
  8250. + */
  8251. +int cpr3_parse_common_ctrl_data(struct cpr3_controller *ctrl)
  8252. +{
  8253. + int rc;
  8254. +
  8255. + rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-sensor-time",
  8256. + &ctrl->sensor_time, 0, UINT_MAX);
  8257. + if (rc)
  8258. + return rc;
  8259. +
  8260. + rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-loop-time",
  8261. + &ctrl->loop_time, 0, UINT_MAX);
  8262. + if (rc)
  8263. + return rc;
  8264. +
  8265. + rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-idle-cycles",
  8266. + &ctrl->idle_clocks, CPR3_IDLE_CLOCKS_MIN,
  8267. + CPR3_IDLE_CLOCKS_MAX);
  8268. + if (rc)
  8269. + return rc;
  8270. +
  8271. + rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-step-quot-init-min",
  8272. + &ctrl->step_quot_init_min, CPR3_STEP_QUOT_MIN,
  8273. + CPR3_STEP_QUOT_MAX);
  8274. + if (rc)
  8275. + return rc;
  8276. +
  8277. + rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-step-quot-init-max",
  8278. + &ctrl->step_quot_init_max, CPR3_STEP_QUOT_MIN,
  8279. + CPR3_STEP_QUOT_MAX);
  8280. + if (rc)
  8281. + return rc;
  8282. +
  8283. + rc = of_property_read_u32(ctrl->dev->of_node, "qcom,voltage-step",
  8284. + &ctrl->step_volt);
  8285. + if (rc) {
  8286. + cpr3_err(ctrl, "error reading property qcom,voltage-step, rc=%d\n",
  8287. + rc);
  8288. + return rc;
  8289. + }
  8290. + if (ctrl->step_volt <= 0) {
  8291. + cpr3_err(ctrl, "qcom,voltage-step=%d is invalid\n",
  8292. + ctrl->step_volt);
  8293. + return -EINVAL;
  8294. + }
  8295. +
  8296. + rc = cpr3_parse_ctrl_u32(ctrl, "qcom,cpr-count-mode",
  8297. + &ctrl->count_mode, CPR3_COUNT_MODE_ALL_AT_ONCE_MIN,
  8298. + CPR3_COUNT_MODE_STAGGERED);
  8299. + if (rc)
  8300. + return rc;
  8301. +
  8302. + /* Count repeat is optional */
  8303. + ctrl->count_repeat = 0;
  8304. + of_property_read_u32(ctrl->dev->of_node, "qcom,cpr-count-repeat",
  8305. + &ctrl->count_repeat);
  8306. +
  8307. + ctrl->cpr_allowed_sw =
  8308. + of_property_read_bool(ctrl->dev->of_node, "qcom,cpr-enable") ||
  8309. + ctrl->cpr_global_setting == CPR_CLOSED_LOOP_EN;
  8310. +
  8311. + rc = cpr3_parse_irq_affinity(ctrl);
  8312. + if (rc)
  8313. + return rc;
  8314. +
  8315. + /* Aging reference voltage is optional */
  8316. + ctrl->aging_ref_volt = 0;
  8317. + of_property_read_u32(ctrl->dev->of_node, "qcom,cpr-aging-ref-voltage",
  8318. + &ctrl->aging_ref_volt);
  8319. +
  8320. + /* Aging possible bitmask is optional */
  8321. + ctrl->aging_possible_mask = 0;
  8322. + of_property_read_u32(ctrl->dev->of_node,
  8323. + "qcom,cpr-aging-allowed-reg-mask",
  8324. + &ctrl->aging_possible_mask);
  8325. +
  8326. + if (ctrl->aging_possible_mask) {
  8327. + /*
  8328. + * Aging possible register value required if bitmask is
  8329. + * specified
  8330. + */
  8331. + rc = cpr3_parse_ctrl_u32(ctrl,
  8332. + "qcom,cpr-aging-allowed-reg-value",
  8333. + &ctrl->aging_possible_val, 0, UINT_MAX);
  8334. + if (rc)
  8335. + return rc;
  8336. + }
  8337. +
  8338. + if (of_find_property(ctrl->dev->of_node, "clock-names", NULL)) {
  8339. + ctrl->core_clk = devm_clk_get(ctrl->dev, "core_clk");
  8340. + if (IS_ERR(ctrl->core_clk)) {
  8341. + rc = PTR_ERR(ctrl->core_clk);
  8342. + if (rc != -EPROBE_DEFER)
  8343. + cpr3_err(ctrl, "unable request core clock, rc=%d\n",
  8344. + rc);
  8345. + return rc;
  8346. + }
  8347. + }
  8348. +
  8349. + rc = cpr3_panic_notifier_init(ctrl);
  8350. + if (rc)
  8351. + return rc;
  8352. +
  8353. + if (of_find_property(ctrl->dev->of_node, "vdd-supply", NULL)) {
  8354. + ctrl->vdd_regulator = devm_regulator_get(ctrl->dev, "vdd");
  8355. + if (IS_ERR(ctrl->vdd_regulator)) {
  8356. + rc = PTR_ERR(ctrl->vdd_regulator);
  8357. + if (rc != -EPROBE_DEFER)
  8358. + cpr3_err(ctrl, "unable to request vdd regulator, rc=%d\n",
  8359. + rc);
  8360. + return rc;
  8361. + }
  8362. + } else {
  8363. + cpr3_err(ctrl, "vdd supply is not defined\n");
  8364. + return -ENODEV;
  8365. + }
  8366. +
  8367. + ctrl->system_regulator = devm_regulator_get_optional(ctrl->dev,
  8368. + "system");
  8369. + if (IS_ERR(ctrl->system_regulator)) {
  8370. + rc = PTR_ERR(ctrl->system_regulator);
  8371. + if (rc != -EPROBE_DEFER) {
  8372. + rc = 0;
  8373. + ctrl->system_regulator = NULL;
  8374. + } else {
  8375. + return rc;
  8376. + }
  8377. + }
  8378. +
  8379. + ctrl->mem_acc_regulator = devm_regulator_get_optional(ctrl->dev,
  8380. + "mem-acc");
  8381. + if (IS_ERR(ctrl->mem_acc_regulator)) {
  8382. + rc = PTR_ERR(ctrl->mem_acc_regulator);
  8383. + if (rc != -EPROBE_DEFER) {
  8384. + rc = 0;
  8385. + ctrl->mem_acc_regulator = NULL;
  8386. + } else {
  8387. + return rc;
  8388. + }
  8389. + }
  8390. +
  8391. + return rc;
  8392. +}
  8393. +
  8394. +/**
  8395. + * cpr3_parse_open_loop_common_ctrl_data() - parse common open loop CPR3
  8396. + * controller properties from device tree
  8397. + * @ctrl: Pointer to the CPR3 controller
  8398. + *
  8399. + * Return: 0 on success, errno on failure
  8400. + */
  8401. +int cpr3_parse_open_loop_common_ctrl_data(struct cpr3_controller *ctrl)
  8402. +{
  8403. + int rc;
  8404. +
  8405. + rc = of_property_read_u32(ctrl->dev->of_node, "qcom,voltage-step",
  8406. + &ctrl->step_volt);
  8407. + if (rc) {
  8408. + cpr3_err(ctrl, "error reading property qcom,voltage-step, rc=%d\n",
  8409. + rc);
  8410. + return rc;
  8411. + }
  8412. +
  8413. + if (ctrl->step_volt <= 0) {
  8414. + cpr3_err(ctrl, "qcom,voltage-step=%d is invalid\n",
  8415. + ctrl->step_volt);
  8416. + return -EINVAL;
  8417. + }
  8418. +
  8419. + if (of_find_property(ctrl->dev->of_node, "vdd-supply", NULL)) {
  8420. + ctrl->vdd_regulator = devm_regulator_get(ctrl->dev, "vdd");
  8421. + if (IS_ERR(ctrl->vdd_regulator)) {
  8422. + rc = PTR_ERR(ctrl->vdd_regulator);
  8423. + if (rc != -EPROBE_DEFER)
  8424. + cpr3_err(ctrl, "unable to request vdd regulator, rc=%d\n",
  8425. + rc);
  8426. + return rc;
  8427. + }
  8428. + } else {
  8429. + cpr3_err(ctrl, "vdd supply is not defined\n");
  8430. + return -ENODEV;
  8431. + }
  8432. +
  8433. + ctrl->system_regulator = devm_regulator_get_optional(ctrl->dev,
  8434. + "system");
  8435. + if (IS_ERR(ctrl->system_regulator)) {
  8436. + rc = PTR_ERR(ctrl->system_regulator);
  8437. + if (rc != -EPROBE_DEFER) {
  8438. + rc = 0;
  8439. + ctrl->system_regulator = NULL;
  8440. + } else {
  8441. + return rc;
  8442. + }
  8443. + } else {
  8444. + rc = regulator_enable(ctrl->system_regulator);
  8445. + }
  8446. +
  8447. + ctrl->mem_acc_regulator = devm_regulator_get_optional(ctrl->dev,
  8448. + "mem-acc");
  8449. + if (IS_ERR(ctrl->mem_acc_regulator)) {
  8450. + rc = PTR_ERR(ctrl->mem_acc_regulator);
  8451. + if (rc != -EPROBE_DEFER) {
  8452. + rc = 0;
  8453. + ctrl->mem_acc_regulator = NULL;
  8454. + } else {
  8455. + return rc;
  8456. + }
  8457. + }
  8458. +
  8459. + return rc;
  8460. +}
  8461. +
  8462. +/**
  8463. + * cpr3_limit_open_loop_voltages() - modify the open-loop voltage of each corner
  8464. + * so that it fits within the floor to ceiling
  8465. + * voltage range of the corner
  8466. + * @vreg: Pointer to the CPR3 regulator
  8467. + *
  8468. + * This function clips the open-loop voltage for each corner so that it is
  8469. + * limited to the floor to ceiling range. It also rounds each open-loop voltage
  8470. + * so that it corresponds to a set point available to the underlying regulator.
  8471. + *
  8472. + * Return: 0 on success, errno on failure
  8473. + */
  8474. +int cpr3_limit_open_loop_voltages(struct cpr3_regulator *vreg)
  8475. +{
  8476. + int i, volt;
  8477. +
  8478. + cpr3_debug(vreg, "open-loop voltages after trimming and rounding:\n");
  8479. + for (i = 0; i < vreg->corner_count; i++) {
  8480. + volt = CPR3_ROUND(vreg->corner[i].open_loop_volt,
  8481. + vreg->thread->ctrl->step_volt);
  8482. + if (volt < vreg->corner[i].floor_volt)
  8483. + volt = vreg->corner[i].floor_volt;
  8484. + else if (volt > vreg->corner[i].ceiling_volt)
  8485. + volt = vreg->corner[i].ceiling_volt;
  8486. + vreg->corner[i].open_loop_volt = volt;
  8487. + cpr3_debug(vreg, "corner[%2d]: open-loop=%d uV\n", i, volt);
  8488. + }
  8489. +
  8490. + return 0;
  8491. +}
  8492. +
  8493. +/**
  8494. + * cpr3_open_loop_voltage_as_ceiling() - configures the ceiling voltage for each
  8495. + * corner to equal the open-loop voltage if the relevant device
  8496. + * tree property is found for the CPR3 regulator
  8497. + * @vreg: Pointer to the CPR3 regulator
  8498. + *
  8499. + * This function assumes that the the open-loop voltage for each corner has
  8500. + * already been rounded to the nearest allowed set point and that it falls
  8501. + * within the floor to ceiling range.
  8502. + *
  8503. + * Return: none
  8504. + */
  8505. +void cpr3_open_loop_voltage_as_ceiling(struct cpr3_regulator *vreg)
  8506. +{
  8507. + int i;
  8508. +
  8509. + if (!of_property_read_bool(vreg->of_node,
  8510. + "qcom,cpr-scaled-open-loop-voltage-as-ceiling"))
  8511. + return;
  8512. +
  8513. + for (i = 0; i < vreg->corner_count; i++)
  8514. + vreg->corner[i].ceiling_volt
  8515. + = vreg->corner[i].open_loop_volt;
  8516. +}
  8517. +
  8518. +/**
  8519. + * cpr3_limit_floor_voltages() - raise the floor voltage of each corner so that
  8520. + * the optional maximum floor to ceiling voltage range specified in
  8521. + * device tree is satisfied
  8522. + * @vreg: Pointer to the CPR3 regulator
  8523. + *
  8524. + * This function also ensures that the open-loop voltage for each corner falls
  8525. + * within the final floor to ceiling voltage range and that floor voltages
  8526. + * increase monotonically.
  8527. + *
  8528. + * Return: 0 on success, errno on failure
  8529. + */
  8530. +int cpr3_limit_floor_voltages(struct cpr3_regulator *vreg)
  8531. +{
  8532. + char *prop = "qcom,cpr-floor-to-ceiling-max-range";
  8533. + int i, floor_new;
  8534. + u32 *floor_range;
  8535. + int rc = 0;
  8536. +
  8537. + if (!of_find_property(vreg->of_node, prop, NULL))
  8538. + goto enforce_monotonicity;
  8539. +
  8540. + floor_range = kcalloc(vreg->corner_count, sizeof(*floor_range),
  8541. + GFP_KERNEL);
  8542. + if (!floor_range)
  8543. + return -ENOMEM;
  8544. +
  8545. + rc = cpr3_parse_corner_array_property(vreg, prop, 1, floor_range);
  8546. + if (rc)
  8547. + goto free_floor_adjust;
  8548. +
  8549. + for (i = 0; i < vreg->corner_count; i++) {
  8550. + if ((s32)floor_range[i] >= 0) {
  8551. + floor_new = CPR3_ROUND(vreg->corner[i].ceiling_volt
  8552. + - floor_range[i],
  8553. + vreg->thread->ctrl->step_volt);
  8554. +
  8555. + vreg->corner[i].floor_volt = max(floor_new,
  8556. + vreg->corner[i].floor_volt);
  8557. + if (vreg->corner[i].open_loop_volt
  8558. + < vreg->corner[i].floor_volt)
  8559. + vreg->corner[i].open_loop_volt
  8560. + = vreg->corner[i].floor_volt;
  8561. + }
  8562. + }
  8563. +
  8564. +free_floor_adjust:
  8565. + kfree(floor_range);
  8566. +
  8567. +enforce_monotonicity:
  8568. + /* Ensure that floor voltages increase monotonically. */
  8569. + for (i = 1; i < vreg->corner_count; i++) {
  8570. + if (vreg->corner[i].floor_volt
  8571. + < vreg->corner[i - 1].floor_volt) {
  8572. + cpr3_debug(vreg, "corner %d floor voltage=%d uV < corner %d voltage=%d uV; overriding: corner %d voltage=%d\n",
  8573. + i, vreg->corner[i].floor_volt,
  8574. + i - 1, vreg->corner[i - 1].floor_volt,
  8575. + i, vreg->corner[i - 1].floor_volt);
  8576. + vreg->corner[i].floor_volt
  8577. + = vreg->corner[i - 1].floor_volt;
  8578. +
  8579. + if (vreg->corner[i].open_loop_volt
  8580. + < vreg->corner[i].floor_volt)
  8581. + vreg->corner[i].open_loop_volt
  8582. + = vreg->corner[i].floor_volt;
  8583. + if (vreg->corner[i].ceiling_volt
  8584. + < vreg->corner[i].floor_volt)
  8585. + vreg->corner[i].ceiling_volt
  8586. + = vreg->corner[i].floor_volt;
  8587. + }
  8588. + }
  8589. +
  8590. + return rc;
  8591. +}
  8592. +
  8593. +/**
  8594. + * cpr3_print_quots() - print CPR target quotients into the kernel log for
  8595. + * debugging purposes
  8596. + * @vreg: Pointer to the CPR3 regulator
  8597. + *
  8598. + * Return: none
  8599. + */
  8600. +void cpr3_print_quots(struct cpr3_regulator *vreg)
  8601. +{
  8602. + int i, j, pos;
  8603. + size_t buflen;
  8604. + char *buf;
  8605. +
  8606. + buflen = sizeof(*buf) * CPR3_RO_COUNT * (MAX_CHARS_PER_INT + 2);
  8607. + buf = kzalloc(buflen, GFP_KERNEL);
  8608. + if (!buf)
  8609. + return;
  8610. +
  8611. + for (i = 0; i < vreg->corner_count; i++) {
  8612. + for (j = 0, pos = 0; j < CPR3_RO_COUNT; j++)
  8613. + pos += scnprintf(buf + pos, buflen - pos, " %u",
  8614. + vreg->corner[i].target_quot[j]);
  8615. + cpr3_debug(vreg, "target quots[%2d]:%s\n", i, buf);
  8616. + }
  8617. +
  8618. + kfree(buf);
  8619. +}
  8620. +
  8621. +/**
  8622. + * cpr3_determine_part_type() - determine the part type (SS/TT/FF).
  8623. + *
  8624. + * qcom,cpr-part-types prop tells the number of part types for which correction
  8625. + * voltages are different. Another prop qcom,cpr-parts-voltage will contain the
  8626. + * open loop fuse voltage which will be compared with this part voltage
  8627. + * and accordingly part type will de determined.
  8628. + *
  8629. + * if qcom,cpr-part-types has value n, then qcom,cpr-parts-voltage will be
  8630. + * array of n - 1 elements which will contain the voltage in increasing order.
  8631. + * This function compares the fused volatge with all these voltage and returns
  8632. + * the first index for which the fused volatge is greater.
  8633. + *
  8634. + * @vreg: Pointer to the CPR3 regulator
  8635. + * @fuse_volt: fused open loop voltage which will be compared with
  8636. + * qcom,cpr-parts-voltage array
  8637. + *
  8638. + * Return: 0 on success, errno on failure
  8639. + */
  8640. +int cpr3_determine_part_type(struct cpr3_regulator *vreg, int fuse_volt)
  8641. +{
  8642. + int i, rc, len;
  8643. + u32 volt;
  8644. + int soc_version_major;
  8645. + char prop_name[100];
  8646. + const char prop_name_def[] = "qcom,cpr-parts-voltage";
  8647. + const char prop_name_v2[] = "qcom,cpr-parts-voltage-v2";
  8648. +
  8649. + soc_version_major = read_ipq_soc_version_major();
  8650. + BUG_ON(soc_version_major <= 0);
  8651. +
  8652. + if (of_property_read_u32(vreg->of_node, "qcom,cpr-part-types",
  8653. + &vreg->part_type_supported))
  8654. + return 0;
  8655. +
  8656. + if (soc_version_major > 1)
  8657. + strlcpy(prop_name, prop_name_v2, sizeof(prop_name_v2));
  8658. + else
  8659. + strlcpy(prop_name, prop_name_def, sizeof(prop_name_def));
  8660. +
  8661. + if (!of_find_property(vreg->of_node, prop_name, &len)) {
  8662. + cpr3_err(vreg, "property %s is missing\n", prop_name);
  8663. + return -EINVAL;
  8664. + }
  8665. +
  8666. + if (len != (vreg->part_type_supported - 1) * sizeof(u32)) {
  8667. + cpr3_err(vreg, "wrong len in qcom,cpr-parts-voltage\n");
  8668. + return -EINVAL;
  8669. + }
  8670. +
  8671. + for (i = 0; i < vreg->part_type_supported - 1; i++) {
  8672. + rc = of_property_read_u32_index(vreg->of_node,
  8673. + prop_name, i, &volt);
  8674. + if (rc) {
  8675. + cpr3_err(vreg, "error reading property %s, rc=%d\n",
  8676. + prop_name, rc);
  8677. + return rc;
  8678. + }
  8679. +
  8680. + if (fuse_volt < volt)
  8681. + break;
  8682. + }
  8683. +
  8684. + vreg->part_type = i;
  8685. + return 0;
  8686. +}
  8687. +
  8688. +int cpr3_determine_temp_base_open_loop_correction(struct cpr3_regulator *vreg,
  8689. + int *fuse_volt)
  8690. +{
  8691. + int i, rc, prev_volt;
  8692. + int *volt_adjust;
  8693. + char prop_str[75];
  8694. + int soc_version_major = read_ipq_soc_version_major();
  8695. +
  8696. + BUG_ON(soc_version_major <= 0);
  8697. +
  8698. + if (vreg->part_type_supported) {
  8699. + if (soc_version_major > 1)
  8700. + snprintf(prop_str, sizeof(prop_str),
  8701. + "qcom,cpr-cold-temp-voltage-adjustment-v2-%d",
  8702. + vreg->part_type);
  8703. + else
  8704. + snprintf(prop_str, sizeof(prop_str),
  8705. + "qcom,cpr-cold-temp-voltage-adjustment-%d",
  8706. + vreg->part_type);
  8707. + } else {
  8708. + strlcpy(prop_str, "qcom,cpr-cold-temp-voltage-adjustment",
  8709. + sizeof(prop_str));
  8710. + }
  8711. +
  8712. + if (!of_find_property(vreg->of_node, prop_str, NULL)) {
  8713. + /* No adjustment required. */
  8714. + cpr3_info(vreg, "No cold temperature adjustment required.\n");
  8715. + return 0;
  8716. + }
  8717. +
  8718. + volt_adjust = kcalloc(vreg->fuse_corner_count, sizeof(*volt_adjust),
  8719. + GFP_KERNEL);
  8720. + if (!volt_adjust)
  8721. + return -ENOMEM;
  8722. +
  8723. + rc = cpr3_parse_array_property(vreg, prop_str,
  8724. + vreg->fuse_corner_count, volt_adjust);
  8725. + if (rc) {
  8726. + cpr3_err(vreg, "could not load cold temp voltage adjustments, rc=%d\n",
  8727. + rc);
  8728. + goto done;
  8729. + }
  8730. +
  8731. + for (i = 0; i < vreg->fuse_corner_count; i++) {
  8732. + if (volt_adjust[i]) {
  8733. + prev_volt = fuse_volt[i];
  8734. + fuse_volt[i] += volt_adjust[i];
  8735. + cpr3_debug(vreg,
  8736. + "adjusted fuse corner %d open-loop voltage: %d -> %d uV\n",
  8737. + i, prev_volt, fuse_volt[i]);
  8738. + }
  8739. + }
  8740. +
  8741. +done:
  8742. + kfree(volt_adjust);
  8743. + return rc;
  8744. +}
  8745. +
  8746. +/**
  8747. + * cpr3_can_adjust_cold_temp() - Is cold temperature adjustment available
  8748. + *
  8749. + * @vreg: Pointer to the CPR3 regulator
  8750. + *
  8751. + * This function checks the cold temperature threshold is available
  8752. + *
  8753. + * Return: true on cold temperature threshold is available, else false
  8754. + */
  8755. +bool cpr3_can_adjust_cold_temp(struct cpr3_regulator *vreg)
  8756. +{
  8757. + char prop_str[75];
  8758. + int soc_version_major = read_ipq_soc_version_major();
  8759. +
  8760. + BUG_ON(soc_version_major <= 0);
  8761. +
  8762. + if (soc_version_major > 1)
  8763. + strlcpy(prop_str, "qcom,cpr-cold-temp-threshold-v2",
  8764. + sizeof(prop_str));
  8765. + else
  8766. + strlcpy(prop_str, "qcom,cpr-cold-temp-threshold",
  8767. + sizeof(prop_str));
  8768. +
  8769. + if (!of_find_property(vreg->of_node, prop_str, NULL)) {
  8770. + /* No adjustment required. */
  8771. + return false;
  8772. + } else
  8773. + return true;
  8774. +}
  8775. +
  8776. +/**
  8777. + * cpr3_get_cold_temp_threshold() - get cold temperature threshold
  8778. + *
  8779. + * @vreg: Pointer to the CPR3 regulator
  8780. + * @cold_temp: cold temperature read.
  8781. + *
  8782. + * This function reads the cold temperature threshold below which
  8783. + * cold temperature adjustment margins will be applied.
  8784. + *
  8785. + * Return: 0 on success, errno on failure
  8786. + */
  8787. +int cpr3_get_cold_temp_threshold(struct cpr3_regulator *vreg, int *cold_temp)
  8788. +{
  8789. + int rc;
  8790. + u32 temp;
  8791. + char req_prop_str[75], prop_str[75];
  8792. + int soc_version_major = read_ipq_soc_version_major();
  8793. +
  8794. + BUG_ON(soc_version_major <= 0);
  8795. +
  8796. + if (vreg->part_type_supported) {
  8797. + if (soc_version_major > 1)
  8798. + snprintf(req_prop_str, sizeof(req_prop_str),
  8799. + "qcom,cpr-cold-temp-voltage-adjustment-v2-%d",
  8800. + vreg->part_type);
  8801. + else
  8802. + snprintf(req_prop_str, sizeof(req_prop_str),
  8803. + "qcom,cpr-cold-temp-voltage-adjustment-%d",
  8804. + vreg->part_type);
  8805. + } else {
  8806. + strlcpy(req_prop_str, "qcom,cpr-cold-temp-voltage-adjustment",
  8807. + sizeof(req_prop_str));
  8808. + }
  8809. +
  8810. + if (soc_version_major > 1)
  8811. + strlcpy(prop_str, "qcom,cpr-cold-temp-threshold-v2",
  8812. + sizeof(prop_str));
  8813. + else
  8814. + strlcpy(prop_str, "qcom,cpr-cold-temp-threshold",
  8815. + sizeof(prop_str));
  8816. +
  8817. + if (!of_find_property(vreg->of_node, req_prop_str, NULL)) {
  8818. + /* No adjustment required. */
  8819. + cpr3_info(vreg, "Cold temperature adjustment not required.\n");
  8820. + return 0;
  8821. + }
  8822. +
  8823. + if (!of_find_property(vreg->of_node, prop_str, NULL)) {
  8824. + /* No adjustment required. */
  8825. + cpr3_err(vreg, "Missing %s required for %s\n",
  8826. + prop_str, req_prop_str);
  8827. + return -EINVAL;
  8828. + }
  8829. +
  8830. + rc = of_property_read_u32(vreg->of_node, prop_str, &temp);
  8831. + if (rc) {
  8832. + cpr3_err(vreg, "error reading property %s, rc=%d\n",
  8833. + prop_str, rc);
  8834. + return rc;
  8835. + }
  8836. +
  8837. + *cold_temp = temp;
  8838. + return 0;
  8839. +}
  8840. +
  8841. +/**
  8842. + * cpr3_adjust_fused_open_loop_voltages() - adjust the fused open-loop voltages
  8843. + * for each fuse corner according to device tree values
  8844. + * @vreg: Pointer to the CPR3 regulator
  8845. + * @fuse_volt: Pointer to an array of the fused open-loop voltage
  8846. + * values
  8847. + *
  8848. + * Voltage values in fuse_volt are modified in place.
  8849. + *
  8850. + * Return: 0 on success, errno on failure
  8851. + */
  8852. +int cpr3_adjust_fused_open_loop_voltages(struct cpr3_regulator *vreg,
  8853. + int *fuse_volt)
  8854. +{
  8855. + int i, rc, prev_volt;
  8856. + int *volt_adjust;
  8857. + char prop_str[75];
  8858. + int soc_version_major = read_ipq_soc_version_major();
  8859. +
  8860. + BUG_ON(soc_version_major <= 0);
  8861. +
  8862. + if (vreg->part_type_supported) {
  8863. + if (soc_version_major > 1)
  8864. + snprintf(prop_str, sizeof(prop_str),
  8865. + "qcom,cpr-open-loop-voltage-fuse-adjustment-v2-%d",
  8866. + vreg->part_type);
  8867. + else
  8868. + snprintf(prop_str, sizeof(prop_str),
  8869. + "qcom,cpr-open-loop-voltage-fuse-adjustment-%d",
  8870. + vreg->part_type);
  8871. + } else {
  8872. + strlcpy(prop_str, "qcom,cpr-open-loop-voltage-fuse-adjustment",
  8873. + sizeof(prop_str));
  8874. + }
  8875. +
  8876. + if (!of_find_property(vreg->of_node, prop_str, NULL)) {
  8877. + /* No adjustment required. */
  8878. + return 0;
  8879. + }
  8880. +
  8881. + volt_adjust = kcalloc(vreg->fuse_corner_count, sizeof(*volt_adjust),
  8882. + GFP_KERNEL);
  8883. + if (!volt_adjust)
  8884. + return -ENOMEM;
  8885. +
  8886. + rc = cpr3_parse_array_property(vreg,
  8887. + prop_str, vreg->fuse_corner_count, volt_adjust);
  8888. + if (rc) {
  8889. + cpr3_err(vreg, "could not load open-loop fused voltage adjustments, rc=%d\n",
  8890. + rc);
  8891. + goto done;
  8892. + }
  8893. +
  8894. + for (i = 0; i < vreg->fuse_corner_count; i++) {
  8895. + if (volt_adjust[i]) {
  8896. + prev_volt = fuse_volt[i];
  8897. + fuse_volt[i] += volt_adjust[i];
  8898. + cpr3_debug(vreg, "adjusted fuse corner %d open-loop voltage: %d --> %d uV\n",
  8899. + i, prev_volt, fuse_volt[i]);
  8900. + }
  8901. + }
  8902. +
  8903. +done:
  8904. + kfree(volt_adjust);
  8905. + return rc;
  8906. +}
  8907. +
  8908. +/**
  8909. + * cpr3_adjust_open_loop_voltages() - adjust the open-loop voltages for each
  8910. + * corner according to device tree values
  8911. + * @vreg: Pointer to the CPR3 regulator
  8912. + *
  8913. + * Return: 0 on success, errno on failure
  8914. + */
  8915. +int cpr3_adjust_open_loop_voltages(struct cpr3_regulator *vreg)
  8916. +{
  8917. + int i, rc, prev_volt, min_volt;
  8918. + int *volt_adjust, *volt_diff;
  8919. +
  8920. + if (!of_find_property(vreg->of_node,
  8921. + "qcom,cpr-open-loop-voltage-adjustment", NULL)) {
  8922. + /* No adjustment required. */
  8923. + return 0;
  8924. + }
  8925. +
  8926. + volt_adjust = kcalloc(vreg->corner_count, sizeof(*volt_adjust),
  8927. + GFP_KERNEL);
  8928. + volt_diff = kcalloc(vreg->corner_count, sizeof(*volt_diff), GFP_KERNEL);
  8929. + if (!volt_adjust || !volt_diff) {
  8930. + rc = -ENOMEM;
  8931. + goto done;
  8932. + }
  8933. +
  8934. + rc = cpr3_parse_corner_array_property(vreg,
  8935. + "qcom,cpr-open-loop-voltage-adjustment", 1, volt_adjust);
  8936. + if (rc) {
  8937. + cpr3_err(vreg, "could not load open-loop voltage adjustments, rc=%d\n",
  8938. + rc);
  8939. + goto done;
  8940. + }
  8941. +
  8942. + for (i = 0; i < vreg->corner_count; i++) {
  8943. + if (volt_adjust[i]) {
  8944. + prev_volt = vreg->corner[i].open_loop_volt;
  8945. + vreg->corner[i].open_loop_volt += volt_adjust[i];
  8946. + cpr3_debug(vreg, "adjusted corner %d open-loop voltage: %d --> %d uV\n",
  8947. + i, prev_volt, vreg->corner[i].open_loop_volt);
  8948. + }
  8949. + }
  8950. +
  8951. + if (of_find_property(vreg->of_node,
  8952. + "qcom,cpr-open-loop-voltage-min-diff", NULL)) {
  8953. + rc = cpr3_parse_corner_array_property(vreg,
  8954. + "qcom,cpr-open-loop-voltage-min-diff", 1, volt_diff);
  8955. + if (rc) {
  8956. + cpr3_err(vreg, "could not load minimum open-loop voltage differences, rc=%d\n",
  8957. + rc);
  8958. + goto done;
  8959. + }
  8960. + }
  8961. +
  8962. + /*
  8963. + * Ensure that open-loop voltages increase monotonically with respect
  8964. + * to configurable minimum allowed differences.
  8965. + */
  8966. + for (i = 1; i < vreg->corner_count; i++) {
  8967. + min_volt = vreg->corner[i - 1].open_loop_volt + volt_diff[i];
  8968. + if (vreg->corner[i].open_loop_volt < min_volt) {
  8969. + cpr3_debug(vreg, "adjusted corner %d open-loop voltage=%d uV < corner %d voltage=%d uV + min diff=%d uV; overriding: corner %d voltage=%d\n",
  8970. + i, vreg->corner[i].open_loop_volt,
  8971. + i - 1, vreg->corner[i - 1].open_loop_volt,
  8972. + volt_diff[i], i, min_volt);
  8973. + vreg->corner[i].open_loop_volt = min_volt;
  8974. + }
  8975. + }
  8976. +
  8977. +done:
  8978. + kfree(volt_diff);
  8979. + kfree(volt_adjust);
  8980. + return rc;
  8981. +}
  8982. +
  8983. +/**
  8984. + * cpr3_quot_adjustment() - returns the quotient adjustment value resulting from
  8985. + * the specified voltage adjustment and RO scaling factor
  8986. + * @ro_scale: The CPR ring oscillator (RO) scaling factor with units
  8987. + * of QUOT/V
  8988. + * @volt_adjust: The amount to adjust the voltage by in units of
  8989. + * microvolts. This value may be positive or negative.
  8990. + */
  8991. +int cpr3_quot_adjustment(int ro_scale, int volt_adjust)
  8992. +{
  8993. + unsigned long long temp;
  8994. + int quot_adjust;
  8995. + int sign = 1;
  8996. +
  8997. + if (ro_scale < 0) {
  8998. + sign = -sign;
  8999. + ro_scale = -ro_scale;
  9000. + }
  9001. +
  9002. + if (volt_adjust < 0) {
  9003. + sign = -sign;
  9004. + volt_adjust = -volt_adjust;
  9005. + }
  9006. +
  9007. + temp = (unsigned long long)ro_scale * (unsigned long long)volt_adjust;
  9008. + do_div(temp, 1000000);
  9009. +
  9010. + quot_adjust = temp;
  9011. + quot_adjust *= sign;
  9012. +
  9013. + return quot_adjust;
  9014. +}
  9015. +
  9016. +/**
  9017. + * cpr3_voltage_adjustment() - returns the voltage adjustment value resulting
  9018. + * from the specified quotient adjustment and RO scaling factor
  9019. + * @ro_scale: The CPR ring oscillator (RO) scaling factor with units
  9020. + * of QUOT/V
  9021. + * @quot_adjust: The amount to adjust the quotient by in units of
  9022. + * QUOT. This value may be positive or negative.
  9023. + */
  9024. +int cpr3_voltage_adjustment(int ro_scale, int quot_adjust)
  9025. +{
  9026. + unsigned long long temp;
  9027. + int volt_adjust;
  9028. + int sign = 1;
  9029. +
  9030. + if (ro_scale < 0) {
  9031. + sign = -sign;
  9032. + ro_scale = -ro_scale;
  9033. + }
  9034. +
  9035. + if (quot_adjust < 0) {
  9036. + sign = -sign;
  9037. + quot_adjust = -quot_adjust;
  9038. + }
  9039. +
  9040. + if (ro_scale == 0)
  9041. + return 0;
  9042. +
  9043. + temp = (unsigned long long)quot_adjust * 1000000;
  9044. + do_div(temp, ro_scale);
  9045. +
  9046. + volt_adjust = temp;
  9047. + volt_adjust *= sign;
  9048. +
  9049. + return volt_adjust;
  9050. +}
  9051. +
  9052. +/**
  9053. + * cpr3_parse_closed_loop_voltage_adjustments() - load per-fuse-corner and
  9054. + * per-corner closed-loop adjustment values from device tree
  9055. + * @vreg: Pointer to the CPR3 regulator
  9056. + * @ro_sel: Array of ring oscillator values selected for each
  9057. + * fuse corner
  9058. + * @volt_adjust: Pointer to array which will be filled with the
  9059. + * per-corner closed-loop adjustment voltages
  9060. + * @volt_adjust_fuse: Pointer to array which will be filled with the
  9061. + * per-fuse-corner closed-loop adjustment voltages
  9062. + * @ro_scale: Pointer to array which will be filled with the
  9063. + * per-fuse-corner RO scaling factor values with units of
  9064. + * QUOT/V
  9065. + *
  9066. + * Return: 0 on success, errno on failure
  9067. + */
  9068. +int cpr3_parse_closed_loop_voltage_adjustments(
  9069. + struct cpr3_regulator *vreg, u64 *ro_sel,
  9070. + int *volt_adjust, int *volt_adjust_fuse, int *ro_scale)
  9071. +{
  9072. + int i, rc;
  9073. + u32 *ro_all_scale;
  9074. +
  9075. + char volt_adj[] = "qcom,cpr-closed-loop-voltage-adjustment";
  9076. + char volt_fuse_adj[] = "qcom,cpr-closed-loop-voltage-fuse-adjustment";
  9077. + char ro_scaling[] = "qcom,cpr-ro-scaling-factor";
  9078. +
  9079. + if (!of_find_property(vreg->of_node, volt_adj, NULL)
  9080. + && !of_find_property(vreg->of_node, volt_fuse_adj, NULL)
  9081. + && !vreg->aging_allowed) {
  9082. + /* No adjustment required. */
  9083. + return 0;
  9084. + } else if (!of_find_property(vreg->of_node, ro_scaling, NULL)) {
  9085. + cpr3_err(vreg, "Missing %s required for closed-loop voltage adjustment.\n",
  9086. + ro_scaling);
  9087. + return -EINVAL;
  9088. + }
  9089. +
  9090. + ro_all_scale = kcalloc(vreg->fuse_corner_count * CPR3_RO_COUNT,
  9091. + sizeof(*ro_all_scale), GFP_KERNEL);
  9092. + if (!ro_all_scale)
  9093. + return -ENOMEM;
  9094. +
  9095. + rc = cpr3_parse_array_property(vreg, ro_scaling,
  9096. + vreg->fuse_corner_count * CPR3_RO_COUNT, ro_all_scale);
  9097. + if (rc) {
  9098. + cpr3_err(vreg, "could not load RO scaling factors, rc=%d\n",
  9099. + rc);
  9100. + goto done;
  9101. + }
  9102. +
  9103. + for (i = 0; i < vreg->fuse_corner_count; i++)
  9104. + ro_scale[i] = ro_all_scale[i * CPR3_RO_COUNT + ro_sel[i]];
  9105. +
  9106. + for (i = 0; i < vreg->corner_count; i++)
  9107. + memcpy(vreg->corner[i].ro_scale,
  9108. + &ro_all_scale[vreg->corner[i].cpr_fuse_corner * CPR3_RO_COUNT],
  9109. + sizeof(*ro_all_scale) * CPR3_RO_COUNT);
  9110. +
  9111. + if (of_find_property(vreg->of_node, volt_fuse_adj, NULL)) {
  9112. + rc = cpr3_parse_array_property(vreg, volt_fuse_adj,
  9113. + vreg->fuse_corner_count, volt_adjust_fuse);
  9114. + if (rc) {
  9115. + cpr3_err(vreg, "could not load closed-loop fused voltage adjustments, rc=%d\n",
  9116. + rc);
  9117. + goto done;
  9118. + }
  9119. + }
  9120. +
  9121. + if (of_find_property(vreg->of_node, volt_adj, NULL)) {
  9122. + rc = cpr3_parse_corner_array_property(vreg, volt_adj,
  9123. + 1, volt_adjust);
  9124. + if (rc) {
  9125. + cpr3_err(vreg, "could not load closed-loop voltage adjustments, rc=%d\n",
  9126. + rc);
  9127. + goto done;
  9128. + }
  9129. + }
  9130. +
  9131. +done:
  9132. + kfree(ro_all_scale);
  9133. + return rc;
  9134. +}
  9135. +
  9136. +/**
  9137. + * cpr3_apm_init() - initialize APM data for a CPR3 controller
  9138. + * @ctrl: Pointer to the CPR3 controller
  9139. + *
  9140. + * This function loads memory array power mux (APM) data from device tree
  9141. + * if it is present and requests a handle to the appropriate APM controller
  9142. + * device.
  9143. + *
  9144. + * Return: 0 on success, errno on failure
  9145. + */
  9146. +int cpr3_apm_init(struct cpr3_controller *ctrl)
  9147. +{
  9148. + struct device_node *node = ctrl->dev->of_node;
  9149. + int rc;
  9150. +
  9151. + if (!of_find_property(node, "qcom,apm-ctrl", NULL)) {
  9152. + /* No APM used */
  9153. + return 0;
  9154. + }
  9155. +
  9156. + ctrl->apm = msm_apm_ctrl_dev_get(ctrl->dev);
  9157. + if (IS_ERR(ctrl->apm)) {
  9158. + rc = PTR_ERR(ctrl->apm);
  9159. + if (rc != -EPROBE_DEFER)
  9160. + cpr3_err(ctrl, "APM get failed, rc=%d\n", rc);
  9161. + return rc;
  9162. + }
  9163. +
  9164. + rc = of_property_read_u32(node, "qcom,apm-threshold-voltage",
  9165. + &ctrl->apm_threshold_volt);
  9166. + if (rc) {
  9167. + cpr3_err(ctrl, "error reading qcom,apm-threshold-voltage, rc=%d\n",
  9168. + rc);
  9169. + return rc;
  9170. + }
  9171. + ctrl->apm_threshold_volt
  9172. + = CPR3_ROUND(ctrl->apm_threshold_volt, ctrl->step_volt);
  9173. +
  9174. + /* No error check since this is an optional property. */
  9175. + of_property_read_u32(node, "qcom,apm-hysteresis-voltage",
  9176. + &ctrl->apm_adj_volt);
  9177. + ctrl->apm_adj_volt = CPR3_ROUND(ctrl->apm_adj_volt, ctrl->step_volt);
  9178. +
  9179. + ctrl->apm_high_supply = MSM_APM_SUPPLY_APCC;
  9180. + ctrl->apm_low_supply = MSM_APM_SUPPLY_MX;
  9181. +
  9182. + return 0;
  9183. +}
  9184. +
  9185. +/**
  9186. + * cpr3_mem_acc_init() - initialize mem-acc regulator data for
  9187. + * a CPR3 regulator
  9188. + * @ctrl: Pointer to the CPR3 controller
  9189. + *
  9190. + * Return: 0 on success, errno on failure
  9191. + */
  9192. +int cpr3_mem_acc_init(struct cpr3_regulator *vreg)
  9193. +{
  9194. + struct cpr3_controller *ctrl = vreg->thread->ctrl;
  9195. + u32 *temp;
  9196. + int i, rc;
  9197. +
  9198. + if (!ctrl->mem_acc_regulator) {
  9199. + cpr3_info(ctrl, "not using memory accelerator regulator\n");
  9200. + return 0;
  9201. + }
  9202. +
  9203. + temp = kcalloc(vreg->corner_count, sizeof(*temp), GFP_KERNEL);
  9204. + if (!temp)
  9205. + return -ENOMEM;
  9206. +
  9207. + rc = cpr3_parse_corner_array_property(vreg, "qcom,mem-acc-voltage",
  9208. + 1, temp);
  9209. + if (rc) {
  9210. + cpr3_err(ctrl, "could not load mem-acc corners, rc=%d\n", rc);
  9211. + } else {
  9212. + for (i = 0; i < vreg->corner_count; i++)
  9213. + vreg->corner[i].mem_acc_volt = temp[i];
  9214. + }
  9215. +
  9216. + kfree(temp);
  9217. + return rc;
  9218. +}
  9219. +
  9220. +/**
  9221. + * cpr4_load_core_and_temp_adj() - parse amount of voltage adjustment for
  9222. + * per-online-core and per-temperature voltage adjustment for a
  9223. + * given corner or corner band from device tree.
  9224. + * @vreg: Pointer to the CPR3 regulator
  9225. + * @num: Corner number or corner band number
  9226. + * @use_corner_band: Boolean indicating if the CPR3 regulator supports
  9227. + * adjustments per corner band
  9228. + *
  9229. + * Return: 0 on success, errno on failure
  9230. + */
  9231. +static int cpr4_load_core_and_temp_adj(struct cpr3_regulator *vreg,
  9232. + int num, bool use_corner_band)
  9233. +{
  9234. + struct cpr3_controller *ctrl = vreg->thread->ctrl;
  9235. + struct cpr4_sdelta *sdelta;
  9236. + int sdelta_size, i, j, pos, rc = 0;
  9237. + char str[75];
  9238. + size_t buflen;
  9239. + char *buf;
  9240. +
  9241. + sdelta = use_corner_band ? vreg->corner_band[num].sdelta :
  9242. + vreg->corner[num].sdelta;
  9243. +
  9244. + if (!sdelta->allow_core_count_adj && !sdelta->allow_temp_adj) {
  9245. + /* corner doesn't need sdelta table */
  9246. + sdelta->max_core_count = 0;
  9247. + sdelta->temp_band_count = 0;
  9248. + return rc;
  9249. + }
  9250. +
  9251. + sdelta_size = sdelta->max_core_count * sdelta->temp_band_count;
  9252. + if (use_corner_band)
  9253. + snprintf(str, sizeof(str),
  9254. + "corner_band=%d core_config_count=%d temp_band_count=%d sdelta_size=%d\n",
  9255. + num, sdelta->max_core_count,
  9256. + sdelta->temp_band_count, sdelta_size);
  9257. + else
  9258. + snprintf(str, sizeof(str),
  9259. + "corner=%d core_config_count=%d temp_band_count=%d sdelta_size=%d\n",
  9260. + num, sdelta->max_core_count,
  9261. + sdelta->temp_band_count, sdelta_size);
  9262. +
  9263. + cpr3_debug(vreg, "%s", str);
  9264. +
  9265. + sdelta->table = devm_kcalloc(ctrl->dev, sdelta_size,
  9266. + sizeof(*sdelta->table), GFP_KERNEL);
  9267. + if (!sdelta->table)
  9268. + return -ENOMEM;
  9269. +
  9270. + if (use_corner_band)
  9271. + snprintf(str, sizeof(str),
  9272. + "qcom,cpr-corner-band%d-temp-core-voltage-adjustment",
  9273. + num + CPR3_CORNER_OFFSET);
  9274. + else
  9275. + snprintf(str, sizeof(str),
  9276. + "qcom,cpr-corner%d-temp-core-voltage-adjustment",
  9277. + num + CPR3_CORNER_OFFSET);
  9278. +
  9279. + rc = cpr3_parse_array_property(vreg, str, sdelta_size,
  9280. + sdelta->table);
  9281. + if (rc) {
  9282. + cpr3_err(vreg, "could not load %s, rc=%d\n", str, rc);
  9283. + return rc;
  9284. + }
  9285. +
  9286. + /*
  9287. + * Convert sdelta margins from uV to PMIC steps and apply negation to
  9288. + * follow the SDELTA register semantics.
  9289. + */
  9290. + for (i = 0; i < sdelta_size; i++)
  9291. + sdelta->table[i] = -(sdelta->table[i] / ctrl->step_volt);
  9292. +
  9293. + buflen = sizeof(*buf) * sdelta_size * (MAX_CHARS_PER_INT + 2);
  9294. + buf = kzalloc(buflen, GFP_KERNEL);
  9295. + if (!buf)
  9296. + return rc;
  9297. +
  9298. + for (i = 0; i < sdelta->max_core_count; i++) {
  9299. + for (j = 0, pos = 0; j < sdelta->temp_band_count; j++)
  9300. + pos += scnprintf(buf + pos, buflen - pos, " %u",
  9301. + sdelta->table[i * sdelta->temp_band_count + j]);
  9302. + cpr3_debug(vreg, "sdelta[%d]:%s\n", i, buf);
  9303. + }
  9304. +
  9305. + kfree(buf);
  9306. + return rc;
  9307. +}
  9308. +
  9309. +/**
  9310. + * cpr4_parse_core_count_temp_voltage_adj() - parse configuration data for
  9311. + * per-online-core and per-temperature voltage adjustment for
  9312. + * a CPR3 regulator from device tree.
  9313. + * @vreg: Pointer to the CPR3 regulator
  9314. + * @use_corner_band: Boolean indicating if the CPR3 regulator supports
  9315. + * adjustments per corner band
  9316. + *
  9317. + * This function supports parsing of per-online-core and per-temperature
  9318. + * adjustments per corner or per corner band. CPR controllers which support
  9319. + * corner bands apply the same adjustments to all corners within a corner band.
  9320. + *
  9321. + * Return: 0 on success, errno on failure
  9322. + */
  9323. +int cpr4_parse_core_count_temp_voltage_adj(
  9324. + struct cpr3_regulator *vreg, bool use_corner_band)
  9325. +{
  9326. + struct cpr3_controller *ctrl = vreg->thread->ctrl;
  9327. + struct device_node *node = vreg->of_node;
  9328. + struct cpr3_corner *corner;
  9329. + struct cpr4_sdelta *sdelta;
  9330. + int i, sdelta_table_count, rc = 0;
  9331. + int *allow_core_count_adj = NULL, *allow_temp_adj = NULL;
  9332. + char prop_str[75];
  9333. +
  9334. + if (of_find_property(node, use_corner_band ?
  9335. + "qcom,corner-band-allow-temp-adjustment"
  9336. + : "qcom,corner-allow-temp-adjustment", NULL)) {
  9337. + if (!ctrl->allow_temp_adj) {
  9338. + cpr3_err(ctrl, "Temperature adjustment configurations missing\n");
  9339. + return -EINVAL;
  9340. + }
  9341. +
  9342. + vreg->allow_temp_adj = true;
  9343. + }
  9344. +
  9345. + if (of_find_property(node, use_corner_band ?
  9346. + "qcom,corner-band-allow-core-count-adjustment"
  9347. + : "qcom,corner-allow-core-count-adjustment",
  9348. + NULL)) {
  9349. + rc = of_property_read_u32(node, "qcom,max-core-count",
  9350. + &vreg->max_core_count);
  9351. + if (rc) {
  9352. + cpr3_err(vreg, "error reading qcom,max-core-count, rc=%d\n",
  9353. + rc);
  9354. + return -EINVAL;
  9355. + }
  9356. +
  9357. + vreg->allow_core_count_adj = true;
  9358. + ctrl->allow_core_count_adj = true;
  9359. + }
  9360. +
  9361. + if (!vreg->allow_temp_adj && !vreg->allow_core_count_adj) {
  9362. + /*
  9363. + * Both per-online-core and temperature based adjustments are
  9364. + * disabled for this regulator.
  9365. + */
  9366. + return 0;
  9367. + } else if (!vreg->allow_core_count_adj) {
  9368. + /*
  9369. + * Only per-temperature voltage adjusments are allowed.
  9370. + * Keep max core count value as 1 to allocate SDELTA.
  9371. + */
  9372. + vreg->max_core_count = 1;
  9373. + }
  9374. +
  9375. + if (vreg->allow_core_count_adj) {
  9376. + allow_core_count_adj = kcalloc(vreg->corner_count,
  9377. + sizeof(*allow_core_count_adj),
  9378. + GFP_KERNEL);
  9379. + if (!allow_core_count_adj)
  9380. + return -ENOMEM;
  9381. +
  9382. + snprintf(prop_str, sizeof(prop_str), "%s", use_corner_band ?
  9383. + "qcom,corner-band-allow-core-count-adjustment" :
  9384. + "qcom,corner-allow-core-count-adjustment");
  9385. +
  9386. + rc = use_corner_band ?
  9387. + cpr3_parse_corner_band_array_property(vreg, prop_str,
  9388. + 1, allow_core_count_adj) :
  9389. + cpr3_parse_corner_array_property(vreg, prop_str,
  9390. + 1, allow_core_count_adj);
  9391. + if (rc) {
  9392. + cpr3_err(vreg, "error reading %s, rc=%d\n", prop_str,
  9393. + rc);
  9394. + goto done;
  9395. + }
  9396. + }
  9397. +
  9398. + if (vreg->allow_temp_adj) {
  9399. + allow_temp_adj = kcalloc(vreg->corner_count,
  9400. + sizeof(*allow_temp_adj), GFP_KERNEL);
  9401. + if (!allow_temp_adj) {
  9402. + rc = -ENOMEM;
  9403. + goto done;
  9404. + }
  9405. +
  9406. + snprintf(prop_str, sizeof(prop_str), "%s", use_corner_band ?
  9407. + "qcom,corner-band-allow-temp-adjustment" :
  9408. + "qcom,corner-allow-temp-adjustment");
  9409. +
  9410. + rc = use_corner_band ?
  9411. + cpr3_parse_corner_band_array_property(vreg, prop_str,
  9412. + 1, allow_temp_adj) :
  9413. + cpr3_parse_corner_array_property(vreg, prop_str,
  9414. + 1, allow_temp_adj);
  9415. + if (rc) {
  9416. + cpr3_err(vreg, "error reading %s, rc=%d\n", prop_str,
  9417. + rc);
  9418. + goto done;
  9419. + }
  9420. + }
  9421. +
  9422. + sdelta_table_count = use_corner_band ? vreg->corner_band_count :
  9423. + vreg->corner_count;
  9424. +
  9425. + for (i = 0; i < sdelta_table_count; i++) {
  9426. + sdelta = devm_kzalloc(ctrl->dev, sizeof(*corner->sdelta),
  9427. + GFP_KERNEL);
  9428. + if (!sdelta) {
  9429. + rc = -ENOMEM;
  9430. + goto done;
  9431. + }
  9432. +
  9433. + if (allow_core_count_adj)
  9434. + sdelta->allow_core_count_adj = allow_core_count_adj[i];
  9435. + if (allow_temp_adj)
  9436. + sdelta->allow_temp_adj = allow_temp_adj[i];
  9437. + sdelta->max_core_count = vreg->max_core_count;
  9438. + sdelta->temp_band_count = ctrl->temp_band_count;
  9439. +
  9440. + if (use_corner_band)
  9441. + vreg->corner_band[i].sdelta = sdelta;
  9442. + else
  9443. + vreg->corner[i].sdelta = sdelta;
  9444. +
  9445. + rc = cpr4_load_core_and_temp_adj(vreg, i, use_corner_band);
  9446. + if (rc) {
  9447. + cpr3_err(vreg, "corner/band %d core and temp adjustment loading failed, rc=%d\n",
  9448. + i, rc);
  9449. + goto done;
  9450. + }
  9451. + }
  9452. +
  9453. +done:
  9454. + kfree(allow_core_count_adj);
  9455. + kfree(allow_temp_adj);
  9456. +
  9457. + return rc;
  9458. +}
  9459. +
  9460. +/**
  9461. + * cprh_adjust_voltages_for_apm() - adjust per-corner floor and ceiling voltages
  9462. + * so that they do not overlap the APM threshold voltage.
  9463. + * @vreg: Pointer to the CPR3 regulator
  9464. + *
  9465. + * The memory array power mux (APM) must be configured for a specific supply
  9466. + * based upon where the VDD voltage lies with respect to the APM threshold
  9467. + * voltage. When using CPR hardware closed-loop, the voltage may vary anywhere
  9468. + * between the floor and ceiling voltage without software notification.
  9469. + * Therefore, it is required that the floor to ceiling range for every corner
  9470. + * not intersect the APM threshold voltage. This function adjusts the floor to
  9471. + * ceiling range for each corner which violates this requirement.
  9472. + *
  9473. + * The following algorithm is applied:
  9474. + * if floor < threshold <= ceiling:
  9475. + * if open_loop >= threshold, then floor = threshold - adj
  9476. + * else ceiling = threshold - step
  9477. + * where:
  9478. + * adj = APM hysteresis voltage established to minimize the number of
  9479. + * corners with artificially increased floor voltages
  9480. + * step = voltage in microvolts of a single step of the VDD supply
  9481. + *
  9482. + * The open-loop voltage is also bounded by the new floor or ceiling value as
  9483. + * needed.
  9484. + *
  9485. + * Return: none
  9486. + */
  9487. +void cprh_adjust_voltages_for_apm(struct cpr3_regulator *vreg)
  9488. +{
  9489. + struct cpr3_controller *ctrl = vreg->thread->ctrl;
  9490. + struct cpr3_corner *corner;
  9491. + int i, adj, threshold, prev_ceiling, prev_floor, prev_open_loop;
  9492. +
  9493. + if (!ctrl->apm_threshold_volt) {
  9494. + /* APM not being used. */
  9495. + return;
  9496. + }
  9497. +
  9498. + ctrl->apm_threshold_volt = CPR3_ROUND(ctrl->apm_threshold_volt,
  9499. + ctrl->step_volt);
  9500. + ctrl->apm_adj_volt = CPR3_ROUND(ctrl->apm_adj_volt, ctrl->step_volt);
  9501. +
  9502. + threshold = ctrl->apm_threshold_volt;
  9503. + adj = ctrl->apm_adj_volt;
  9504. +
  9505. + for (i = 0; i < vreg->corner_count; i++) {
  9506. + corner = &vreg->corner[i];
  9507. +
  9508. + if (threshold <= corner->floor_volt
  9509. + || threshold > corner->ceiling_volt)
  9510. + continue;
  9511. +
  9512. + prev_floor = corner->floor_volt;
  9513. + prev_ceiling = corner->ceiling_volt;
  9514. + prev_open_loop = corner->open_loop_volt;
  9515. +
  9516. + if (corner->open_loop_volt >= threshold) {
  9517. + corner->floor_volt = max(corner->floor_volt,
  9518. + threshold - adj);
  9519. + if (corner->open_loop_volt < corner->floor_volt)
  9520. + corner->open_loop_volt = corner->floor_volt;
  9521. + } else {
  9522. + corner->ceiling_volt = threshold - ctrl->step_volt;
  9523. + }
  9524. +
  9525. + if (corner->floor_volt != prev_floor
  9526. + || corner->ceiling_volt != prev_ceiling
  9527. + || corner->open_loop_volt != prev_open_loop)
  9528. + cpr3_debug(vreg, "APM threshold=%d, APM adj=%d changed corner %d voltages; prev: floor=%d, ceiling=%d, open-loop=%d; new: floor=%d, ceiling=%d, open-loop=%d\n",
  9529. + threshold, adj, i, prev_floor, prev_ceiling,
  9530. + prev_open_loop, corner->floor_volt,
  9531. + corner->ceiling_volt, corner->open_loop_volt);
  9532. + }
  9533. +}
  9534. +
  9535. +/**
  9536. + * cprh_adjust_voltages_for_mem_acc() - adjust per-corner floor and ceiling
  9537. + * voltages so that they do not intersect the MEM ACC threshold
  9538. + * voltage
  9539. + * @vreg: Pointer to the CPR3 regulator
  9540. + *
  9541. + * The following algorithm is applied:
  9542. + * if floor < threshold <= ceiling:
  9543. + * if open_loop >= threshold, then floor = threshold
  9544. + * else ceiling = threshold - step
  9545. + * where:
  9546. + * step = voltage in microvolts of a single step of the VDD supply
  9547. + *
  9548. + * The open-loop voltage is also bounded by the new floor or ceiling value as
  9549. + * needed.
  9550. + *
  9551. + * Return: none
  9552. + */
  9553. +void cprh_adjust_voltages_for_mem_acc(struct cpr3_regulator *vreg)
  9554. +{
  9555. + struct cpr3_controller *ctrl = vreg->thread->ctrl;
  9556. + struct cpr3_corner *corner;
  9557. + int i, threshold, prev_ceiling, prev_floor, prev_open_loop;
  9558. +
  9559. + if (!ctrl->mem_acc_threshold_volt) {
  9560. + /* MEM ACC not being used. */
  9561. + return;
  9562. + }
  9563. +
  9564. + ctrl->mem_acc_threshold_volt = CPR3_ROUND(ctrl->mem_acc_threshold_volt,
  9565. + ctrl->step_volt);
  9566. +
  9567. + threshold = ctrl->mem_acc_threshold_volt;
  9568. +
  9569. + for (i = 0; i < vreg->corner_count; i++) {
  9570. + corner = &vreg->corner[i];
  9571. +
  9572. + if (threshold <= corner->floor_volt
  9573. + || threshold > corner->ceiling_volt)
  9574. + continue;
  9575. +
  9576. + prev_floor = corner->floor_volt;
  9577. + prev_ceiling = corner->ceiling_volt;
  9578. + prev_open_loop = corner->open_loop_volt;
  9579. +
  9580. + if (corner->open_loop_volt >= threshold) {
  9581. + corner->floor_volt = max(corner->floor_volt, threshold);
  9582. + if (corner->open_loop_volt < corner->floor_volt)
  9583. + corner->open_loop_volt = corner->floor_volt;
  9584. + } else {
  9585. + corner->ceiling_volt = threshold - ctrl->step_volt;
  9586. + }
  9587. +
  9588. + if (corner->floor_volt != prev_floor
  9589. + || corner->ceiling_volt != prev_ceiling
  9590. + || corner->open_loop_volt != prev_open_loop)
  9591. + cpr3_debug(vreg, "MEM ACC threshold=%d changed corner %d voltages; prev: floor=%d, ceiling=%d, open-loop=%d; new: floor=%d, ceiling=%d, open-loop=%d\n",
  9592. + threshold, i, prev_floor, prev_ceiling,
  9593. + prev_open_loop, corner->floor_volt,
  9594. + corner->ceiling_volt, corner->open_loop_volt);
  9595. + }
  9596. +}
  9597. +
  9598. +/**
  9599. + * cpr3_apply_closed_loop_offset_voltages() - modify the closed-loop voltage
  9600. + * adjustments by the amounts that are needed for this
  9601. + * fuse combo
  9602. + * @vreg: Pointer to the CPR3 regulator
  9603. + * @volt_adjust: Array of closed-loop voltage adjustment values of length
  9604. + * vreg->corner_count which is further adjusted based upon
  9605. + * offset voltage fuse values.
  9606. + * @fuse_volt_adjust: Fused closed-loop voltage adjustment values of length
  9607. + * vreg->fuse_corner_count.
  9608. + *
  9609. + * Return: 0 on success, errno on failure
  9610. + */
  9611. +static int cpr3_apply_closed_loop_offset_voltages(struct cpr3_regulator *vreg,
  9612. + int *volt_adjust, int *fuse_volt_adjust)
  9613. +{
  9614. + u32 *corner_map;
  9615. + int rc = 0, i;
  9616. +
  9617. + if (!of_find_property(vreg->of_node,
  9618. + "qcom,cpr-fused-closed-loop-voltage-adjustment-map", NULL)) {
  9619. + /* No closed-loop offset required. */
  9620. + return 0;
  9621. + }
  9622. +
  9623. + corner_map = kcalloc(vreg->corner_count, sizeof(*corner_map),
  9624. + GFP_KERNEL);
  9625. + if (!corner_map)
  9626. + return -ENOMEM;
  9627. +
  9628. + rc = cpr3_parse_corner_array_property(vreg,
  9629. + "qcom,cpr-fused-closed-loop-voltage-adjustment-map",
  9630. + 1, corner_map);
  9631. + if (rc)
  9632. + goto done;
  9633. +
  9634. + for (i = 0; i < vreg->corner_count; i++) {
  9635. + if (corner_map[i] == 0) {
  9636. + continue;
  9637. + } else if (corner_map[i] > vreg->fuse_corner_count) {
  9638. + cpr3_err(vreg, "corner %d mapped to invalid fuse corner: %u\n",
  9639. + i, corner_map[i]);
  9640. + rc = -EINVAL;
  9641. + goto done;
  9642. + }
  9643. +
  9644. + volt_adjust[i] += fuse_volt_adjust[corner_map[i] - 1];
  9645. + }
  9646. +
  9647. +done:
  9648. + kfree(corner_map);
  9649. + return rc;
  9650. +}
  9651. +
  9652. +/**
  9653. + * cpr3_enforce_inc_quotient_monotonicity() - Ensure that target quotients
  9654. + * increase monotonically from lower to higher corners
  9655. + * @vreg: Pointer to the CPR3 regulator
  9656. + *
  9657. + * Return: 0 on success, errno on failure
  9658. + */
  9659. +static void cpr3_enforce_inc_quotient_monotonicity(struct cpr3_regulator *vreg)
  9660. +{
  9661. + int i, j;
  9662. +
  9663. + for (i = 1; i < vreg->corner_count; i++) {
  9664. + for (j = 0; j < CPR3_RO_COUNT; j++) {
  9665. + if (vreg->corner[i].target_quot[j]
  9666. + && vreg->corner[i].target_quot[j]
  9667. + < vreg->corner[i - 1].target_quot[j]) {
  9668. + cpr3_debug(vreg, "corner %d RO%u target quot=%u < corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
  9669. + i, j,
  9670. + vreg->corner[i].target_quot[j],
  9671. + i - 1, j,
  9672. + vreg->corner[i - 1].target_quot[j],
  9673. + i, j,
  9674. + vreg->corner[i - 1].target_quot[j]);
  9675. + vreg->corner[i].target_quot[j]
  9676. + = vreg->corner[i - 1].target_quot[j];
  9677. + }
  9678. + }
  9679. + }
  9680. +}
  9681. +
  9682. +/**
  9683. + * cpr3_enforce_dec_quotient_monotonicity() - Ensure that target quotients
  9684. + * decrease monotonically from higher to lower corners
  9685. + * @vreg: Pointer to the CPR3 regulator
  9686. + *
  9687. + * Return: 0 on success, errno on failure
  9688. + */
  9689. +static void cpr3_enforce_dec_quotient_monotonicity(struct cpr3_regulator *vreg)
  9690. +{
  9691. + int i, j;
  9692. +
  9693. + for (i = vreg->corner_count - 2; i >= 0; i--) {
  9694. + for (j = 0; j < CPR3_RO_COUNT; j++) {
  9695. + if (vreg->corner[i + 1].target_quot[j]
  9696. + && vreg->corner[i].target_quot[j]
  9697. + > vreg->corner[i + 1].target_quot[j]) {
  9698. + cpr3_debug(vreg, "corner %d RO%u target quot=%u > corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
  9699. + i, j,
  9700. + vreg->corner[i].target_quot[j],
  9701. + i + 1, j,
  9702. + vreg->corner[i + 1].target_quot[j],
  9703. + i, j,
  9704. + vreg->corner[i + 1].target_quot[j]);
  9705. + vreg->corner[i].target_quot[j]
  9706. + = vreg->corner[i + 1].target_quot[j];
  9707. + }
  9708. + }
  9709. + }
  9710. +}
  9711. +
  9712. +/**
  9713. + * _cpr3_adjust_target_quotients() - adjust the target quotients for each
  9714. + * corner of the regulator according to input adjustment and
  9715. + * scaling arrays
  9716. + * @vreg: Pointer to the CPR3 regulator
  9717. + * @volt_adjust: Pointer to an array of closed-loop voltage adjustments
  9718. + * with units of microvolts. The array must have
  9719. + * vreg->corner_count number of elements.
  9720. + * @ro_scale: Pointer to a flattened 2D array of RO scaling factors.
  9721. + * The array must have an inner dimension of CPR3_RO_COUNT
  9722. + * and an outer dimension of vreg->corner_count
  9723. + * @label: Null terminated string providing a label for the type
  9724. + * of adjustment.
  9725. + *
  9726. + * Return: true if any corners received a positive voltage adjustment (> 0),
  9727. + * else false
  9728. + */
  9729. +static bool _cpr3_adjust_target_quotients(struct cpr3_regulator *vreg,
  9730. + const int *volt_adjust, const int *ro_scale, const char *label)
  9731. +{
  9732. + int i, j, quot_adjust;
  9733. + bool is_increasing = false;
  9734. + u32 prev_quot;
  9735. +
  9736. + for (i = 0; i < vreg->corner_count; i++) {
  9737. + for (j = 0; j < CPR3_RO_COUNT; j++) {
  9738. + if (vreg->corner[i].target_quot[j]) {
  9739. + quot_adjust = cpr3_quot_adjustment(
  9740. + ro_scale[i * CPR3_RO_COUNT + j],
  9741. + volt_adjust[i]);
  9742. + if (quot_adjust) {
  9743. + prev_quot = vreg->corner[i].
  9744. + target_quot[j];
  9745. + vreg->corner[i].target_quot[j]
  9746. + += quot_adjust;
  9747. + cpr3_debug(vreg, "adjusted corner %d RO%d target quot %s: %u --> %u (%d uV)\n",
  9748. + i, j, label, prev_quot,
  9749. + vreg->corner[i].target_quot[j],
  9750. + volt_adjust[i]);
  9751. + }
  9752. + }
  9753. + }
  9754. + if (volt_adjust[i] > 0)
  9755. + is_increasing = true;
  9756. + }
  9757. +
  9758. + return is_increasing;
  9759. +}
  9760. +
  9761. +/**
  9762. + * cpr3_adjust_target_quotients() - adjust the target quotients for each
  9763. + * corner according to device tree values and fuse values
  9764. + * @vreg: Pointer to the CPR3 regulator
  9765. + * @fuse_volt_adjust: Fused closed-loop voltage adjustment values of length
  9766. + * vreg->fuse_corner_count. This parameter could be null
  9767. + * pointer when no fused adjustments are needed.
  9768. + *
  9769. + * Return: 0 on success, errno on failure
  9770. + */
  9771. +int cpr3_adjust_target_quotients(struct cpr3_regulator *vreg,
  9772. + int *fuse_volt_adjust)
  9773. +{
  9774. + int i, rc;
  9775. + int *volt_adjust, *ro_scale;
  9776. + bool explicit_adjustment, fused_adjustment, is_increasing;
  9777. +
  9778. + explicit_adjustment = of_find_property(vreg->of_node,
  9779. + "qcom,cpr-closed-loop-voltage-adjustment", NULL);
  9780. + fused_adjustment = of_find_property(vreg->of_node,
  9781. + "qcom,cpr-fused-closed-loop-voltage-adjustment-map", NULL);
  9782. +
  9783. + if (!explicit_adjustment && !fused_adjustment && !vreg->aging_allowed) {
  9784. + /* No adjustment required. */
  9785. + return 0;
  9786. + } else if (!of_find_property(vreg->of_node,
  9787. + "qcom,cpr-ro-scaling-factor", NULL)) {
  9788. + cpr3_err(vreg, "qcom,cpr-ro-scaling-factor is required for closed-loop voltage adjustment, but is missing\n");
  9789. + return -EINVAL;
  9790. + }
  9791. +
  9792. + volt_adjust = kcalloc(vreg->corner_count, sizeof(*volt_adjust),
  9793. + GFP_KERNEL);
  9794. + ro_scale = kcalloc(vreg->corner_count * CPR3_RO_COUNT,
  9795. + sizeof(*ro_scale), GFP_KERNEL);
  9796. + if (!volt_adjust || !ro_scale) {
  9797. + rc = -ENOMEM;
  9798. + goto done;
  9799. + }
  9800. +
  9801. + rc = cpr3_parse_corner_array_property(vreg,
  9802. + "qcom,cpr-ro-scaling-factor", CPR3_RO_COUNT, ro_scale);
  9803. + if (rc) {
  9804. + cpr3_err(vreg, "could not load RO scaling factors, rc=%d\n",
  9805. + rc);
  9806. + goto done;
  9807. + }
  9808. +
  9809. + for (i = 0; i < vreg->corner_count; i++)
  9810. + memcpy(vreg->corner[i].ro_scale, &ro_scale[i * CPR3_RO_COUNT],
  9811. + sizeof(*ro_scale) * CPR3_RO_COUNT);
  9812. +
  9813. + if (explicit_adjustment) {
  9814. + rc = cpr3_parse_corner_array_property(vreg,
  9815. + "qcom,cpr-closed-loop-voltage-adjustment",
  9816. + 1, volt_adjust);
  9817. + if (rc) {
  9818. + cpr3_err(vreg, "could not load closed-loop voltage adjustments, rc=%d\n",
  9819. + rc);
  9820. + goto done;
  9821. + }
  9822. +
  9823. + _cpr3_adjust_target_quotients(vreg, volt_adjust, ro_scale,
  9824. + "from DT");
  9825. + cpr3_enforce_inc_quotient_monotonicity(vreg);
  9826. + }
  9827. +
  9828. + if (fused_adjustment && fuse_volt_adjust) {
  9829. + memset(volt_adjust, 0,
  9830. + sizeof(*volt_adjust) * vreg->corner_count);
  9831. +
  9832. + rc = cpr3_apply_closed_loop_offset_voltages(vreg, volt_adjust,
  9833. + fuse_volt_adjust);
  9834. + if (rc) {
  9835. + cpr3_err(vreg, "could not apply fused closed-loop voltage reductions, rc=%d\n",
  9836. + rc);
  9837. + goto done;
  9838. + }
  9839. +
  9840. + is_increasing = _cpr3_adjust_target_quotients(vreg, volt_adjust,
  9841. + ro_scale, "from fuse");
  9842. + if (is_increasing)
  9843. + cpr3_enforce_inc_quotient_monotonicity(vreg);
  9844. + else
  9845. + cpr3_enforce_dec_quotient_monotonicity(vreg);
  9846. + }
  9847. +
  9848. +done:
  9849. + kfree(volt_adjust);
  9850. + kfree(ro_scale);
  9851. + return rc;
  9852. +}
  9853. --- /dev/null
  9854. +++ b/drivers/regulator/cpr4-apss-regulator.c
  9855. @@ -0,0 +1,1819 @@
  9856. +/*
  9857. + * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
  9858. + *
  9859. + * This program is free software; you can redistribute it and/or modify
  9860. + * it under the terms of the GNU General Public License version 2 and
  9861. + * only version 2 as published by the Free Software Foundation.
  9862. + *
  9863. + * This program is distributed in the hope that it will be useful,
  9864. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9865. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9866. + * GNU General Public License for more details.
  9867. + */
  9868. +
  9869. +#define pr_fmt(fmt) "%s: " fmt, __func__
  9870. +
  9871. +#include <linux/bitops.h>
  9872. +#include <linux/debugfs.h>
  9873. +#include <linux/err.h>
  9874. +#include <linux/init.h>
  9875. +#include <linux/interrupt.h>
  9876. +#include <linux/io.h>
  9877. +#include <linux/kernel.h>
  9878. +#include <linux/list.h>
  9879. +#include <linux/module.h>
  9880. +#include <linux/of.h>
  9881. +#include <linux/of_device.h>
  9882. +#include <linux/platform_device.h>
  9883. +#include <linux/pm_opp.h>
  9884. +#include <linux/slab.h>
  9885. +#include <linux/string.h>
  9886. +#include <linux/uaccess.h>
  9887. +#include <linux/regulator/driver.h>
  9888. +#include <linux/regulator/machine.h>
  9889. +#include <linux/regulator/of_regulator.h>
  9890. +
  9891. +#include "cpr3-regulator.h"
  9892. +
  9893. +#define IPQ807x_APSS_FUSE_CORNERS 4
  9894. +#define IPQ817x_APPS_FUSE_CORNERS 2
  9895. +#define IPQ6018_APSS_FUSE_CORNERS 4
  9896. +#define IPQ9574_APSS_FUSE_CORNERS 4
  9897. +
  9898. +u32 g_valid_fuse_count = IPQ807x_APSS_FUSE_CORNERS;
  9899. +
  9900. +/**
  9901. + * struct cpr4_ipq807x_apss_fuses - APSS specific fuse data for IPQ807x
  9902. + * @ro_sel: Ring oscillator select fuse parameter value for each
  9903. + * fuse corner
  9904. + * @init_voltage: Initial (i.e. open-loop) voltage fuse parameter value
  9905. + * for each fuse corner (raw, not converted to a voltage)
  9906. + * @target_quot: CPR target quotient fuse parameter value for each fuse
  9907. + * corner
  9908. + * @quot_offset: CPR target quotient offset fuse parameter value for each
  9909. + * fuse corner (raw, not unpacked) used for target quotient
  9910. + * interpolation
  9911. + * @speed_bin: Application processor speed bin fuse parameter value for
  9912. + * the given chip
  9913. + * @cpr_fusing_rev: CPR fusing revision fuse parameter value
  9914. + * @boost_cfg: CPR boost configuration fuse parameter value
  9915. + * @boost_voltage: CPR boost voltage fuse parameter value (raw, not
  9916. + * converted to a voltage)
  9917. + *
  9918. + * This struct holds the values for all of the fuses read from memory.
  9919. + */
  9920. +struct cpr4_ipq807x_apss_fuses {
  9921. + u64 ro_sel[IPQ807x_APSS_FUSE_CORNERS];
  9922. + u64 init_voltage[IPQ807x_APSS_FUSE_CORNERS];
  9923. + u64 target_quot[IPQ807x_APSS_FUSE_CORNERS];
  9924. + u64 quot_offset[IPQ807x_APSS_FUSE_CORNERS];
  9925. + u64 speed_bin;
  9926. + u64 cpr_fusing_rev;
  9927. + u64 boost_cfg;
  9928. + u64 boost_voltage;
  9929. + u64 misc;
  9930. +};
  9931. +
  9932. +/*
  9933. + * fuse combo = fusing revision + 8 * (speed bin)
  9934. + * where: fusing revision = 0 - 7 and speed bin = 0 - 7
  9935. + */
  9936. +#define CPR4_IPQ807x_APSS_FUSE_COMBO_COUNT 64
  9937. +
  9938. +/*
  9939. + * Constants which define the name of each fuse corner.
  9940. + */
  9941. +enum cpr4_ipq807x_apss_fuse_corner {
  9942. + CPR4_IPQ807x_APSS_FUSE_CORNER_SVS = 0,
  9943. + CPR4_IPQ807x_APSS_FUSE_CORNER_NOM = 1,
  9944. + CPR4_IPQ807x_APSS_FUSE_CORNER_TURBO = 2,
  9945. + CPR4_IPQ807x_APSS_FUSE_CORNER_STURBO = 3,
  9946. +};
  9947. +
  9948. +static const char * const cpr4_ipq807x_apss_fuse_corner_name[] = {
  9949. + [CPR4_IPQ807x_APSS_FUSE_CORNER_SVS] = "SVS",
  9950. + [CPR4_IPQ807x_APSS_FUSE_CORNER_NOM] = "NOM",
  9951. + [CPR4_IPQ807x_APSS_FUSE_CORNER_TURBO] = "TURBO",
  9952. + [CPR4_IPQ807x_APSS_FUSE_CORNER_STURBO] = "STURBO",
  9953. +};
  9954. +
  9955. +/*
  9956. + * IPQ807x APSS fuse parameter locations:
  9957. + *
  9958. + * Structs are organized with the following dimensions:
  9959. + * Outer: 0 to 3 for fuse corners from lowest to highest corner
  9960. + * Inner: large enough to hold the longest set of parameter segments which
  9961. + * fully defines a fuse parameter, +1 (for NULL termination).
  9962. + * Each segment corresponds to a contiguous group of bits from a
  9963. + * single fuse row. These segments are concatentated together in
  9964. + * order to form the full fuse parameter value. The segments for
  9965. + * a given parameter may correspond to different fuse rows.
  9966. + */
  9967. +static struct cpr3_fuse_param
  9968. +ipq807x_apss_ro_sel_param[IPQ807x_APSS_FUSE_CORNERS][2] = {
  9969. + {{73, 8, 11}, {} },
  9970. + {{73, 4, 7}, {} },
  9971. + {{73, 0, 3}, {} },
  9972. + {{73, 12, 15}, {} },
  9973. +};
  9974. +
  9975. +static struct cpr3_fuse_param
  9976. +ipq807x_apss_init_voltage_param[IPQ807x_APSS_FUSE_CORNERS][2] = {
  9977. + {{71, 18, 23}, {} },
  9978. + {{71, 12, 17}, {} },
  9979. + {{71, 6, 11}, {} },
  9980. + {{71, 0, 5}, {} },
  9981. +};
  9982. +
  9983. +static struct cpr3_fuse_param
  9984. +ipq807x_apss_target_quot_param[IPQ807x_APSS_FUSE_CORNERS][2] = {
  9985. + {{72, 32, 43}, {} },
  9986. + {{72, 20, 31}, {} },
  9987. + {{72, 8, 19}, {} },
  9988. + {{72, 44, 55}, {} },
  9989. +};
  9990. +
  9991. +static struct cpr3_fuse_param
  9992. +ipq807x_apss_quot_offset_param[IPQ807x_APSS_FUSE_CORNERS][2] = {
  9993. + {{} },
  9994. + {{71, 46, 52}, {} },
  9995. + {{71, 39, 45}, {} },
  9996. + {{71, 32, 38}, {} },
  9997. +};
  9998. +
  9999. +static struct cpr3_fuse_param ipq807x_cpr_fusing_rev_param[] = {
  10000. + {71, 53, 55},
  10001. + {},
  10002. +};
  10003. +
  10004. +static struct cpr3_fuse_param ipq807x_apss_speed_bin_param[] = {
  10005. + {36, 40, 42},
  10006. + {},
  10007. +};
  10008. +
  10009. +static struct cpr3_fuse_param ipq807x_cpr_boost_fuse_cfg_param[] = {
  10010. + {36, 43, 45},
  10011. + {},
  10012. +};
  10013. +
  10014. +static struct cpr3_fuse_param ipq807x_apss_boost_fuse_volt_param[] = {
  10015. + {71, 0, 5},
  10016. + {},
  10017. +};
  10018. +
  10019. +static struct cpr3_fuse_param ipq807x_misc_fuse_volt_adj_param[] = {
  10020. + {36, 54, 54},
  10021. + {},
  10022. +};
  10023. +
  10024. +static struct cpr3_fuse_parameters ipq807x_fuse_params = {
  10025. + .apss_ro_sel_param = ipq807x_apss_ro_sel_param,
  10026. + .apss_init_voltage_param = ipq807x_apss_init_voltage_param,
  10027. + .apss_target_quot_param = ipq807x_apss_target_quot_param,
  10028. + .apss_quot_offset_param = ipq807x_apss_quot_offset_param,
  10029. + .cpr_fusing_rev_param = ipq807x_cpr_fusing_rev_param,
  10030. + .apss_speed_bin_param = ipq807x_apss_speed_bin_param,
  10031. + .cpr_boost_fuse_cfg_param = ipq807x_cpr_boost_fuse_cfg_param,
  10032. + .apss_boost_fuse_volt_param = ipq807x_apss_boost_fuse_volt_param,
  10033. + .misc_fuse_volt_adj_param = ipq807x_misc_fuse_volt_adj_param
  10034. +};
  10035. +
  10036. +/*
  10037. + * The number of possible values for misc fuse is
  10038. + * 2^(#bits defined for misc fuse)
  10039. + */
  10040. +#define IPQ807x_MISC_FUSE_VAL_COUNT BIT(1)
  10041. +
  10042. +/*
  10043. + * Open loop voltage fuse reference voltages in microvolts for IPQ807x
  10044. + */
  10045. +static int ipq807x_apss_fuse_ref_volt
  10046. + [IPQ807x_APSS_FUSE_CORNERS] = {
  10047. + 720000,
  10048. + 864000,
  10049. + 992000,
  10050. + 1064000,
  10051. +};
  10052. +
  10053. +#define IPQ807x_APSS_FUSE_STEP_VOLT 8000
  10054. +#define IPQ807x_APSS_VOLTAGE_FUSE_SIZE 6
  10055. +#define IPQ807x_APSS_QUOT_OFFSET_SCALE 5
  10056. +
  10057. +#define IPQ807x_APSS_CPR_SENSOR_COUNT 6
  10058. +
  10059. +#define IPQ807x_APSS_CPR_CLOCK_RATE 19200000
  10060. +
  10061. +#define IPQ807x_APSS_MAX_TEMP_POINTS 3
  10062. +#define IPQ807x_APSS_TEMP_SENSOR_ID_START 4
  10063. +#define IPQ807x_APSS_TEMP_SENSOR_ID_END 13
  10064. +/*
  10065. + * Boost voltage fuse reference and ceiling voltages in microvolts for
  10066. + * IPQ807x.
  10067. + */
  10068. +#define IPQ807x_APSS_BOOST_FUSE_REF_VOLT 1140000
  10069. +#define IPQ807x_APSS_BOOST_CEILING_VOLT 1140000
  10070. +#define IPQ807x_APSS_BOOST_FLOOR_VOLT 900000
  10071. +#define MAX_BOOST_CONFIG_FUSE_VALUE 8
  10072. +
  10073. +#define IPQ807x_APSS_CPR_SDELTA_CORE_COUNT 15
  10074. +
  10075. +#define IPQ807x_APSS_CPR_TCSR_START 8
  10076. +#define IPQ807x_APSS_CPR_TCSR_END 9
  10077. +
  10078. +/*
  10079. + * Array of integer values mapped to each of the boost config fuse values to
  10080. + * indicate boost enable/disable status.
  10081. + */
  10082. +static bool boost_fuse[MAX_BOOST_CONFIG_FUSE_VALUE] = {0, 1, 1, 1, 1, 1, 1, 1};
  10083. +
  10084. +/*
  10085. + * IPQ6018 (Few parameters are changed, remaining are same as IPQ807x)
  10086. + */
  10087. +#define IPQ6018_APSS_FUSE_STEP_VOLT 12500
  10088. +#define IPQ6018_APSS_CPR_CLOCK_RATE 24000000
  10089. +
  10090. +static struct cpr3_fuse_param
  10091. +ipq6018_apss_ro_sel_param[IPQ6018_APSS_FUSE_CORNERS][2] = {
  10092. + {{75, 8, 11}, {} },
  10093. + {{75, 4, 7}, {} },
  10094. + {{75, 0, 3}, {} },
  10095. + {{75, 12, 15}, {} },
  10096. +};
  10097. +
  10098. +static struct cpr3_fuse_param
  10099. +ipq6018_apss_init_voltage_param[IPQ6018_APSS_FUSE_CORNERS][2] = {
  10100. + {{73, 18, 23}, {} },
  10101. + {{73, 12, 17}, {} },
  10102. + {{73, 6, 11}, {} },
  10103. + {{73, 0, 5}, {} },
  10104. +};
  10105. +
  10106. +static struct cpr3_fuse_param
  10107. +ipq6018_apss_target_quot_param[IPQ6018_APSS_FUSE_CORNERS][2] = {
  10108. + {{74, 32, 43}, {} },
  10109. + {{74, 20, 31}, {} },
  10110. + {{74, 8, 19}, {} },
  10111. + {{74, 44, 55}, {} },
  10112. +};
  10113. +
  10114. +static struct cpr3_fuse_param
  10115. +ipq6018_apss_quot_offset_param[IPQ6018_APSS_FUSE_CORNERS][2] = {
  10116. + {{} },
  10117. + {{73, 48, 55}, {} },
  10118. + {{73, 40, 47}, {} },
  10119. + {{73, 32, 39}, {} },
  10120. +};
  10121. +
  10122. +static struct cpr3_fuse_param ipq6018_cpr_fusing_rev_param[] = {
  10123. + {75, 16, 18},
  10124. + {},
  10125. +};
  10126. +
  10127. +static struct cpr3_fuse_param ipq6018_apss_speed_bin_param[] = {
  10128. + {36, 40, 42},
  10129. + {},
  10130. +};
  10131. +
  10132. +static struct cpr3_fuse_param ipq6018_cpr_boost_fuse_cfg_param[] = {
  10133. + {36, 43, 45},
  10134. + {},
  10135. +};
  10136. +
  10137. +static struct cpr3_fuse_param ipq6018_apss_boost_fuse_volt_param[] = {
  10138. + {73, 0, 5},
  10139. + {},
  10140. +};
  10141. +
  10142. +static struct cpr3_fuse_param ipq6018_misc_fuse_volt_adj_param[] = {
  10143. + {36, 54, 54},
  10144. + {},
  10145. +};
  10146. +
  10147. +static struct cpr3_fuse_parameters ipq6018_fuse_params = {
  10148. + .apss_ro_sel_param = ipq6018_apss_ro_sel_param,
  10149. + .apss_init_voltage_param = ipq6018_apss_init_voltage_param,
  10150. + .apss_target_quot_param = ipq6018_apss_target_quot_param,
  10151. + .apss_quot_offset_param = ipq6018_apss_quot_offset_param,
  10152. + .cpr_fusing_rev_param = ipq6018_cpr_fusing_rev_param,
  10153. + .apss_speed_bin_param = ipq6018_apss_speed_bin_param,
  10154. + .cpr_boost_fuse_cfg_param = ipq6018_cpr_boost_fuse_cfg_param,
  10155. + .apss_boost_fuse_volt_param = ipq6018_apss_boost_fuse_volt_param,
  10156. + .misc_fuse_volt_adj_param = ipq6018_misc_fuse_volt_adj_param
  10157. +};
  10158. +
  10159. +
  10160. +/*
  10161. + * Boost voltage fuse reference and ceiling voltages in microvolts for
  10162. + * IPQ6018.
  10163. + */
  10164. +#define IPQ6018_APSS_BOOST_FUSE_REF_VOLT 1140000
  10165. +#define IPQ6018_APSS_BOOST_CEILING_VOLT 1140000
  10166. +#define IPQ6018_APSS_BOOST_FLOOR_VOLT 900000
  10167. +
  10168. +/*
  10169. + * Open loop voltage fuse reference voltages in microvolts for IPQ807x
  10170. + */
  10171. +static int ipq6018_apss_fuse_ref_volt
  10172. + [IPQ6018_APSS_FUSE_CORNERS] = {
  10173. + 725000,
  10174. + 862500,
  10175. + 987500,
  10176. + 1062500,
  10177. +};
  10178. +
  10179. +/*
  10180. + * IPQ6018 Memory ACC settings on TCSR
  10181. + *
  10182. + * Turbo_L1: write TCSR_MEM_ACC_SW_OVERRIDE_LEGACY_APC0 0x10
  10183. + * write TCSR_CUSTOM_VDDAPC0_ACC_1 0x1
  10184. + * Other modes: write TCSR_MEM_ACC_SW_OVERRIDE_LEGACY_APC0 0x0
  10185. + * write TCSR_CUSTOM_VDDAPC0_ACC_1 0x0
  10186. + *
  10187. + */
  10188. +#define IPQ6018_APSS_MEM_ACC_TCSR_COUNT 2
  10189. +#define TCSR_MEM_ACC_SW_OVERRIDE_LEGACY_APC0 0x1946178
  10190. +#define TCSR_CUSTOM_VDDAPC0_ACC_1 0x1946124
  10191. +
  10192. +struct mem_acc_tcsr {
  10193. + u32 phy_addr;
  10194. + void __iomem *ioremap_addr;
  10195. + u32 value;
  10196. +};
  10197. +
  10198. +static struct mem_acc_tcsr ipq6018_mem_acc_tcsr[IPQ6018_APSS_MEM_ACC_TCSR_COUNT] = {
  10199. + {TCSR_MEM_ACC_SW_OVERRIDE_LEGACY_APC0, NULL, 0x10},
  10200. + {TCSR_CUSTOM_VDDAPC0_ACC_1, NULL, 0x1},
  10201. +};
  10202. +
  10203. +/*
  10204. + * IPQ9574 (Few parameters are changed, remaining are same as IPQ6018)
  10205. + */
  10206. +#define IPQ9574_APSS_FUSE_STEP_VOLT 10000
  10207. +
  10208. +static struct cpr3_fuse_param
  10209. +ipq9574_apss_ro_sel_param[IPQ9574_APSS_FUSE_CORNERS][2] = {
  10210. + {{107, 4, 7}, {} },
  10211. + {{107, 0, 3}, {} },
  10212. + {{106, 4, 7}, {} },
  10213. + {{106, 0, 3}, {} },
  10214. +};
  10215. +
  10216. +static struct cpr3_fuse_param
  10217. +ipq9574_apss_init_voltage_param[IPQ9574_APSS_FUSE_CORNERS][2] = {
  10218. + {{104, 24, 29}, {} },
  10219. + {{104, 18, 23}, {} },
  10220. + {{104, 12, 17}, {} },
  10221. + {{104, 6, 11}, {} },
  10222. +};
  10223. +
  10224. +static struct cpr3_fuse_param
  10225. +ipq9574_apss_target_quot_param[IPQ9574_APSS_FUSE_CORNERS][2] = {
  10226. + {{106, 32, 43}, {} },
  10227. + {{106, 20, 31}, {} },
  10228. + {{106, 8, 19}, {} },
  10229. + {{106, 44, 55}, {} },
  10230. +};
  10231. +
  10232. +static struct cpr3_fuse_param
  10233. +ipq9574_apss_quot_offset_param[IPQ9574_APSS_FUSE_CORNERS][2] = {
  10234. + {{} },
  10235. + {{105, 48, 55}, {} },
  10236. + {{105, 40, 47}, {} },
  10237. + {{105, 32, 39}, {} },
  10238. +};
  10239. +
  10240. +static struct cpr3_fuse_param ipq9574_cpr_fusing_rev_param[] = {
  10241. + {107, 8, 10},
  10242. + {},
  10243. +};
  10244. +
  10245. +static struct cpr3_fuse_param ipq9574_apss_speed_bin_param[] = {
  10246. + {0, 40, 42},
  10247. + {},
  10248. +};
  10249. +
  10250. +static struct cpr3_fuse_param ipq9574_cpr_boost_fuse_cfg_param[] = {
  10251. + {0, 43, 45},
  10252. + {},
  10253. +};
  10254. +
  10255. +static struct cpr3_fuse_param ipq9574_apss_boost_fuse_volt_param[] = {
  10256. + {104, 0, 5},
  10257. + {},
  10258. +};
  10259. +
  10260. +static struct cpr3_fuse_param ipq9574_misc_fuse_volt_adj_param[] = {
  10261. + {0, 54, 54},
  10262. + {},
  10263. +};
  10264. +
  10265. +static struct cpr3_fuse_parameters ipq9574_fuse_params = {
  10266. + .apss_ro_sel_param = ipq9574_apss_ro_sel_param,
  10267. + .apss_init_voltage_param = ipq9574_apss_init_voltage_param,
  10268. + .apss_target_quot_param = ipq9574_apss_target_quot_param,
  10269. + .apss_quot_offset_param = ipq9574_apss_quot_offset_param,
  10270. + .cpr_fusing_rev_param = ipq9574_cpr_fusing_rev_param,
  10271. + .apss_speed_bin_param = ipq9574_apss_speed_bin_param,
  10272. + .cpr_boost_fuse_cfg_param = ipq9574_cpr_boost_fuse_cfg_param,
  10273. + .apss_boost_fuse_volt_param = ipq9574_apss_boost_fuse_volt_param,
  10274. + .misc_fuse_volt_adj_param = ipq9574_misc_fuse_volt_adj_param
  10275. +};
  10276. +
  10277. +/*
  10278. + * Open loop voltage fuse reference voltages in microvolts for IPQ9574
  10279. + */
  10280. +static int ipq9574_apss_fuse_ref_volt
  10281. + [IPQ9574_APSS_FUSE_CORNERS] = {
  10282. + 725000,
  10283. + 862500,
  10284. + 987500,
  10285. + 1062500,
  10286. +};
  10287. +
  10288. +/**
  10289. + * cpr4_ipq807x_apss_read_fuse_data() - load APSS specific fuse parameter values
  10290. + * @vreg: Pointer to the CPR3 regulator
  10291. + *
  10292. + * This function allocates a cpr4_ipq807x_apss_fuses struct, fills it with
  10293. + * values read out of hardware fuses, and finally copies common fuse values
  10294. + * into the CPR3 regulator struct.
  10295. + *
  10296. + * Return: 0 on success, errno on failure
  10297. + */
  10298. +static int cpr4_ipq807x_apss_read_fuse_data(struct cpr3_regulator *vreg)
  10299. +{
  10300. + void __iomem *base = vreg->thread->ctrl->fuse_base;
  10301. + struct cpr4_ipq807x_apss_fuses *fuse;
  10302. + int i, rc;
  10303. +
  10304. + fuse = devm_kzalloc(vreg->thread->ctrl->dev, sizeof(*fuse), GFP_KERNEL);
  10305. + if (!fuse)
  10306. + return -ENOMEM;
  10307. +
  10308. + rc = cpr3_read_fuse_param(base, vreg->cpr4_regulator_data->cpr3_fuse_params->apss_speed_bin_param,
  10309. + &fuse->speed_bin);
  10310. + if (rc) {
  10311. + cpr3_err(vreg, "Unable to read speed bin fuse, rc=%d\n", rc);
  10312. + return rc;
  10313. + }
  10314. + cpr3_info(vreg, "speed bin = %llu\n", fuse->speed_bin);
  10315. +
  10316. + rc = cpr3_read_fuse_param(base, vreg->cpr4_regulator_data->cpr3_fuse_params->cpr_fusing_rev_param,
  10317. + &fuse->cpr_fusing_rev);
  10318. + if (rc) {
  10319. + cpr3_err(vreg, "Unable to read CPR fusing revision fuse, rc=%d\n",
  10320. + rc);
  10321. + return rc;
  10322. + }
  10323. + cpr3_info(vreg, "CPR fusing revision = %llu\n", fuse->cpr_fusing_rev);
  10324. +
  10325. + rc = cpr3_read_fuse_param(base, vreg->cpr4_regulator_data->cpr3_fuse_params->misc_fuse_volt_adj_param,
  10326. + &fuse->misc);
  10327. + if (rc) {
  10328. + cpr3_err(vreg, "Unable to read misc voltage adjustment fuse, rc=%d\n",
  10329. + rc);
  10330. + return rc;
  10331. + }
  10332. + cpr3_info(vreg, "CPR misc fuse value = %llu\n", fuse->misc);
  10333. + if (fuse->misc >= IPQ807x_MISC_FUSE_VAL_COUNT) {
  10334. + cpr3_err(vreg, "CPR misc fuse value = %llu, should be < %lu\n",
  10335. + fuse->misc, IPQ807x_MISC_FUSE_VAL_COUNT);
  10336. + return -EINVAL;
  10337. + }
  10338. +
  10339. + for (i = 0; i < g_valid_fuse_count; i++) {
  10340. + rc = cpr3_read_fuse_param(base,
  10341. + vreg->cpr4_regulator_data->cpr3_fuse_params->apss_init_voltage_param[i],
  10342. + &fuse->init_voltage[i]);
  10343. + if (rc) {
  10344. + cpr3_err(vreg, "Unable to read fuse-corner %d initial voltage fuse, rc=%d\n",
  10345. + i, rc);
  10346. + return rc;
  10347. + }
  10348. +
  10349. + rc = cpr3_read_fuse_param(base,
  10350. + vreg->cpr4_regulator_data->cpr3_fuse_params->apss_target_quot_param[i],
  10351. + &fuse->target_quot[i]);
  10352. + if (rc) {
  10353. + cpr3_err(vreg, "Unable to read fuse-corner %d target quotient fuse, rc=%d\n",
  10354. + i, rc);
  10355. + return rc;
  10356. + }
  10357. +
  10358. + rc = cpr3_read_fuse_param(base,
  10359. + vreg->cpr4_regulator_data->cpr3_fuse_params->apss_ro_sel_param[i],
  10360. + &fuse->ro_sel[i]);
  10361. + if (rc) {
  10362. + cpr3_err(vreg, "Unable to read fuse-corner %d RO select fuse, rc=%d\n",
  10363. + i, rc);
  10364. + return rc;
  10365. + }
  10366. +
  10367. + rc = cpr3_read_fuse_param(base,
  10368. + vreg->cpr4_regulator_data->cpr3_fuse_params->apss_quot_offset_param[i],
  10369. + &fuse->quot_offset[i]);
  10370. + if (rc) {
  10371. + cpr3_err(vreg, "Unable to read fuse-corner %d quotient offset fuse, rc=%d\n",
  10372. + i, rc);
  10373. + return rc;
  10374. + }
  10375. + }
  10376. +
  10377. + rc = cpr3_read_fuse_param(base, vreg->cpr4_regulator_data->cpr3_fuse_params->cpr_boost_fuse_cfg_param,
  10378. + &fuse->boost_cfg);
  10379. + if (rc) {
  10380. + cpr3_err(vreg, "Unable to read CPR boost config fuse, rc=%d\n",
  10381. + rc);
  10382. + return rc;
  10383. + }
  10384. + cpr3_info(vreg, "Voltage boost fuse config = %llu boost = %s\n",
  10385. + fuse->boost_cfg, boost_fuse[fuse->boost_cfg]
  10386. + ? "enable" : "disable");
  10387. +
  10388. + rc = cpr3_read_fuse_param(base,
  10389. + vreg->cpr4_regulator_data->cpr3_fuse_params->apss_boost_fuse_volt_param,
  10390. + &fuse->boost_voltage);
  10391. + if (rc) {
  10392. + cpr3_err(vreg, "failed to read boost fuse voltage, rc=%d\n",
  10393. + rc);
  10394. + return rc;
  10395. + }
  10396. +
  10397. + vreg->fuse_combo = fuse->cpr_fusing_rev + 8 * fuse->speed_bin;
  10398. + if (vreg->fuse_combo >= CPR4_IPQ807x_APSS_FUSE_COMBO_COUNT) {
  10399. + cpr3_err(vreg, "invalid CPR fuse combo = %d found\n",
  10400. + vreg->fuse_combo);
  10401. + return -EINVAL;
  10402. + }
  10403. +
  10404. + vreg->speed_bin_fuse = fuse->speed_bin;
  10405. + vreg->cpr_rev_fuse = fuse->cpr_fusing_rev;
  10406. + vreg->fuse_corner_count = g_valid_fuse_count;
  10407. + vreg->platform_fuses = fuse;
  10408. +
  10409. + return 0;
  10410. +}
  10411. +
  10412. +/**
  10413. + * cpr4_apss_parse_corner_data() - parse APSS corner data from device tree
  10414. + * properties of the CPR3 regulator's device node
  10415. + * @vreg: Pointer to the CPR3 regulator
  10416. + *
  10417. + * Return: 0 on success, errno on failure
  10418. + */
  10419. +static int cpr4_apss_parse_corner_data(struct cpr3_regulator *vreg)
  10420. +{
  10421. + struct device_node *node = vreg->of_node;
  10422. + struct cpr4_ipq807x_apss_fuses *fuse = vreg->platform_fuses;
  10423. + u32 *temp = NULL;
  10424. + int i, rc;
  10425. +
  10426. + rc = cpr3_parse_common_corner_data(vreg);
  10427. + if (rc) {
  10428. + cpr3_err(vreg, "error reading corner data, rc=%d\n", rc);
  10429. + return rc;
  10430. + }
  10431. +
  10432. + /* If fuse has incorrect RO Select values and dtsi has "qcom,cpr-ro-sel"
  10433. + * entry with RO select values other than zero, then dtsi values will
  10434. + * be used.
  10435. + */
  10436. + if (of_find_property(node, "qcom,cpr-ro-sel", NULL)) {
  10437. + temp = kcalloc(vreg->fuse_corner_count, sizeof(*temp),
  10438. + GFP_KERNEL);
  10439. + if (!temp)
  10440. + return -ENOMEM;
  10441. +
  10442. + rc = cpr3_parse_array_property(vreg, "qcom,cpr-ro-sel",
  10443. + vreg->fuse_corner_count, temp);
  10444. + if (rc)
  10445. + goto done;
  10446. +
  10447. + for (i = 0; i < vreg->fuse_corner_count; i++) {
  10448. + if (temp[i] != 0)
  10449. + fuse->ro_sel[i] = temp[i];
  10450. + }
  10451. + }
  10452. +done:
  10453. + kfree(temp);
  10454. + return rc;
  10455. +}
  10456. +
  10457. +/**
  10458. + * cpr4_apss_parse_misc_fuse_voltage_adjustments() - fill an array from a
  10459. + * portion of the voltage adjustments specified based on
  10460. + * miscellaneous fuse bits.
  10461. + * @vreg: Pointer to the CPR3 regulator
  10462. + * @volt_adjust: Voltage adjustment output data array which must be
  10463. + * of size vreg->corner_count
  10464. + *
  10465. + * cpr3_parse_common_corner_data() must be called for vreg before this function
  10466. + * is called so that speed bin size elements are initialized.
  10467. + *
  10468. + * Two formats are supported for the device tree property:
  10469. + * 1. Length == tuple_list_size * vreg->corner_count
  10470. + * (reading begins at index 0)
  10471. + * 2. Length == tuple_list_size * vreg->speed_bin_corner_sum
  10472. + * (reading begins at index tuple_list_size * vreg->speed_bin_offset)
  10473. + *
  10474. + * Here, tuple_list_size is the number of possible values for misc fuse.
  10475. + * All other property lengths are treated as errors.
  10476. + *
  10477. + * Return: 0 on success, errno on failure
  10478. + */
  10479. +static int cpr4_apss_parse_misc_fuse_voltage_adjustments(
  10480. + struct cpr3_regulator *vreg, u32 *volt_adjust)
  10481. +{
  10482. + struct device_node *node = vreg->of_node;
  10483. + struct cpr4_ipq807x_apss_fuses *fuse = vreg->platform_fuses;
  10484. + int tuple_list_size = IPQ807x_MISC_FUSE_VAL_COUNT;
  10485. + int i, offset, rc, len = 0;
  10486. + const char *prop_name = "qcom,cpr-misc-fuse-voltage-adjustment";
  10487. +
  10488. + if (!of_find_property(node, prop_name, &len)) {
  10489. + cpr3_err(vreg, "property %s is missing\n", prop_name);
  10490. + return -EINVAL;
  10491. + }
  10492. +
  10493. + if (len == tuple_list_size * vreg->corner_count * sizeof(u32)) {
  10494. + offset = 0;
  10495. + } else if (vreg->speed_bin_corner_sum > 0 &&
  10496. + len == tuple_list_size * vreg->speed_bin_corner_sum
  10497. + * sizeof(u32)) {
  10498. + offset = tuple_list_size * vreg->speed_bin_offset
  10499. + + fuse->misc * vreg->corner_count;
  10500. + } else {
  10501. + if (vreg->speed_bin_corner_sum > 0)
  10502. + cpr3_err(vreg, "property %s has invalid length=%d, should be %zu or %zu\n",
  10503. + prop_name, len,
  10504. + tuple_list_size * vreg->corner_count
  10505. + * sizeof(u32),
  10506. + tuple_list_size * vreg->speed_bin_corner_sum
  10507. + * sizeof(u32));
  10508. + else
  10509. + cpr3_err(vreg, "property %s has invalid length=%d, should be %zu\n",
  10510. + prop_name, len,
  10511. + tuple_list_size * vreg->corner_count
  10512. + * sizeof(u32));
  10513. + return -EINVAL;
  10514. + }
  10515. +
  10516. + for (i = 0; i < vreg->corner_count; i++) {
  10517. + rc = of_property_read_u32_index(node, prop_name, offset + i,
  10518. + &volt_adjust[i]);
  10519. + if (rc) {
  10520. + cpr3_err(vreg, "error reading property %s, rc=%d\n",
  10521. + prop_name, rc);
  10522. + return rc;
  10523. + }
  10524. + }
  10525. +
  10526. + return 0;
  10527. +}
  10528. +
  10529. +/**
  10530. + * cpr4_ipq807x_apss_calculate_open_loop_voltages() - calculate the open-loop
  10531. + * voltage for each corner of a CPR3 regulator
  10532. + * @vreg: Pointer to the CPR3 regulator
  10533. + *
  10534. + * If open-loop voltage interpolation is allowed in device tree, then
  10535. + * this function calculates the open-loop voltage for a given corner using
  10536. + * linear interpolation. This interpolation is performed using the processor
  10537. + * frequencies of the lower and higher Fmax corners along with their fused
  10538. + * open-loop voltages.
  10539. + *
  10540. + * If open-loop voltage interpolation is not allowed, then this function uses
  10541. + * the Fmax fused open-loop voltage for all of the corners associated with a
  10542. + * given fuse corner.
  10543. + *
  10544. + * Return: 0 on success, errno on failure
  10545. + */
  10546. +static int cpr4_ipq807x_apss_calculate_open_loop_voltages(
  10547. + struct cpr3_regulator *vreg)
  10548. +{
  10549. + struct device_node *node = vreg->of_node;
  10550. + struct cpr4_ipq807x_apss_fuses *fuse = vreg->platform_fuses;
  10551. + struct cpr3_controller *ctrl = vreg->thread->ctrl;
  10552. + int i, j, rc = 0;
  10553. + bool allow_interpolation;
  10554. + u64 freq_low, volt_low, freq_high, volt_high;
  10555. + int *fuse_volt, *misc_adj_volt;
  10556. + int *fmax_corner;
  10557. +
  10558. + fuse_volt = kcalloc(vreg->fuse_corner_count, sizeof(*fuse_volt),
  10559. + GFP_KERNEL);
  10560. + fmax_corner = kcalloc(vreg->fuse_corner_count, sizeof(*fmax_corner),
  10561. + GFP_KERNEL);
  10562. + if (!fuse_volt || !fmax_corner) {
  10563. + rc = -ENOMEM;
  10564. + goto done;
  10565. + }
  10566. +
  10567. + for (i = 0; i < vreg->fuse_corner_count; i++) {
  10568. + if (ctrl->cpr_global_setting == CPR_DISABLED)
  10569. + fuse_volt[i] = vreg->cpr4_regulator_data->fuse_ref_volt[i];
  10570. + else
  10571. + fuse_volt[i] = cpr3_convert_open_loop_voltage_fuse(
  10572. + vreg->cpr4_regulator_data->fuse_ref_volt[i],
  10573. + vreg->cpr4_regulator_data->fuse_step_volt,
  10574. + fuse->init_voltage[i],
  10575. + IPQ807x_APSS_VOLTAGE_FUSE_SIZE);
  10576. +
  10577. + /* Log fused open-loop voltage values for debugging purposes. */
  10578. + cpr3_info(vreg, "fused %8s: open-loop=%7d uV\n",
  10579. + cpr4_ipq807x_apss_fuse_corner_name[i],
  10580. + fuse_volt[i]);
  10581. + }
  10582. +
  10583. + rc = cpr3_determine_part_type(vreg,
  10584. + fuse_volt[vreg->fuse_corner_count - 1]);
  10585. + if (rc) {
  10586. + cpr3_err(vreg, "fused part type detection failed failed, rc=%d\n",
  10587. + rc);
  10588. + goto done;
  10589. + }
  10590. +
  10591. + rc = cpr3_adjust_fused_open_loop_voltages(vreg, fuse_volt);
  10592. + if (rc) {
  10593. + cpr3_err(vreg, "fused open-loop voltage adjustment failed, rc=%d\n",
  10594. + rc);
  10595. + goto done;
  10596. + }
  10597. +
  10598. + allow_interpolation = of_property_read_bool(node,
  10599. + "qcom,allow-voltage-interpolation");
  10600. +
  10601. + for (i = 1; i < vreg->fuse_corner_count; i++) {
  10602. + if (fuse_volt[i] < fuse_volt[i - 1]) {
  10603. + cpr3_info(vreg, "fuse corner %d voltage=%d uV < fuse corner %d voltage=%d uV; overriding: fuse corner %d voltage=%d\n",
  10604. + i, fuse_volt[i], i - 1, fuse_volt[i - 1],
  10605. + i, fuse_volt[i - 1]);
  10606. + fuse_volt[i] = fuse_volt[i - 1];
  10607. + }
  10608. + }
  10609. +
  10610. + if (!allow_interpolation) {
  10611. + /* Use fused open-loop voltage for lower frequencies. */
  10612. + for (i = 0; i < vreg->corner_count; i++)
  10613. + vreg->corner[i].open_loop_volt
  10614. + = fuse_volt[vreg->corner[i].cpr_fuse_corner];
  10615. + goto done;
  10616. + }
  10617. +
  10618. + /* Determine highest corner mapped to each fuse corner */
  10619. + j = vreg->fuse_corner_count - 1;
  10620. + for (i = vreg->corner_count - 1; i >= 0; i--) {
  10621. + if (vreg->corner[i].cpr_fuse_corner == j) {
  10622. + fmax_corner[j] = i;
  10623. + j--;
  10624. + }
  10625. + }
  10626. + if (j >= 0) {
  10627. + cpr3_err(vreg, "invalid fuse corner mapping\n");
  10628. + rc = -EINVAL;
  10629. + goto done;
  10630. + }
  10631. +
  10632. + /*
  10633. + * Interpolation is not possible for corners mapped to the lowest fuse
  10634. + * corner so use the fuse corner value directly.
  10635. + */
  10636. + for (i = 0; i <= fmax_corner[0]; i++)
  10637. + vreg->corner[i].open_loop_volt = fuse_volt[0];
  10638. +
  10639. + /* Interpolate voltages for the higher fuse corners. */
  10640. + for (i = 1; i < vreg->fuse_corner_count; i++) {
  10641. + freq_low = vreg->corner[fmax_corner[i - 1]].proc_freq;
  10642. + volt_low = fuse_volt[i - 1];
  10643. + freq_high = vreg->corner[fmax_corner[i]].proc_freq;
  10644. + volt_high = fuse_volt[i];
  10645. +
  10646. + for (j = fmax_corner[i - 1] + 1; j <= fmax_corner[i]; j++)
  10647. + vreg->corner[j].open_loop_volt = cpr3_interpolate(
  10648. + freq_low, volt_low, freq_high, volt_high,
  10649. + vreg->corner[j].proc_freq);
  10650. + }
  10651. +
  10652. +done:
  10653. + if (rc == 0) {
  10654. + cpr3_debug(vreg, "unadjusted per-corner open-loop voltages:\n");
  10655. + for (i = 0; i < vreg->corner_count; i++)
  10656. + cpr3_debug(vreg, "open-loop[%2d] = %d uV\n", i,
  10657. + vreg->corner[i].open_loop_volt);
  10658. +
  10659. + rc = cpr3_adjust_open_loop_voltages(vreg);
  10660. + if (rc)
  10661. + cpr3_err(vreg, "open-loop voltage adjustment failed, rc=%d\n",
  10662. + rc);
  10663. +
  10664. + if (of_find_property(node,
  10665. + "qcom,cpr-misc-fuse-voltage-adjustment",
  10666. + NULL)) {
  10667. + misc_adj_volt = kcalloc(vreg->corner_count,
  10668. + sizeof(*misc_adj_volt), GFP_KERNEL);
  10669. + if (!misc_adj_volt) {
  10670. + rc = -ENOMEM;
  10671. + goto _exit;
  10672. + }
  10673. +
  10674. + rc = cpr4_apss_parse_misc_fuse_voltage_adjustments(vreg,
  10675. + misc_adj_volt);
  10676. + if (rc) {
  10677. + cpr3_err(vreg, "qcom,cpr-misc-fuse-voltage-adjustment reading failed, rc=%d\n",
  10678. + rc);
  10679. + kfree(misc_adj_volt);
  10680. + goto _exit;
  10681. + }
  10682. +
  10683. + for (i = 0; i < vreg->corner_count; i++)
  10684. + vreg->corner[i].open_loop_volt
  10685. + += misc_adj_volt[i];
  10686. + kfree(misc_adj_volt);
  10687. + }
  10688. + }
  10689. +
  10690. +_exit:
  10691. + kfree(fuse_volt);
  10692. + kfree(fmax_corner);
  10693. + return rc;
  10694. +}
  10695. +
  10696. +/**
  10697. + * cpr4_ipq807x_apss_set_no_interpolation_quotients() - use the fused target
  10698. + * quotient values for lower frequencies.
  10699. + * @vreg: Pointer to the CPR3 regulator
  10700. + * @volt_adjust: Pointer to array of per-corner closed-loop adjustment
  10701. + * voltages
  10702. + * @volt_adjust_fuse: Pointer to array of per-fuse-corner closed-loop
  10703. + * adjustment voltages
  10704. + * @ro_scale: Pointer to array of per-fuse-corner RO scaling factor
  10705. + * values with units of QUOT/V
  10706. + *
  10707. + * Return: 0 on success, errno on failure
  10708. + */
  10709. +static int cpr4_ipq807x_apss_set_no_interpolation_quotients(
  10710. + struct cpr3_regulator *vreg, int *volt_adjust,
  10711. + int *volt_adjust_fuse, int *ro_scale)
  10712. +{
  10713. + struct cpr4_ipq807x_apss_fuses *fuse = vreg->platform_fuses;
  10714. + u32 quot, ro;
  10715. + int quot_adjust;
  10716. + int i, fuse_corner;
  10717. +
  10718. + for (i = 0; i < vreg->corner_count; i++) {
  10719. + fuse_corner = vreg->corner[i].cpr_fuse_corner;
  10720. + quot = fuse->target_quot[fuse_corner];
  10721. + quot_adjust = cpr3_quot_adjustment(ro_scale[fuse_corner],
  10722. + volt_adjust_fuse[fuse_corner] +
  10723. + volt_adjust[i]);
  10724. + ro = fuse->ro_sel[fuse_corner];
  10725. + vreg->corner[i].target_quot[ro] = quot + quot_adjust;
  10726. + cpr3_debug(vreg, "corner=%d RO=%u target quot=%u\n",
  10727. + i, ro, quot);
  10728. +
  10729. + if (quot_adjust)
  10730. + cpr3_debug(vreg, "adjusted corner %d RO%u target quot: %u --> %u (%d uV)\n",
  10731. + i, ro, quot, vreg->corner[i].target_quot[ro],
  10732. + volt_adjust_fuse[fuse_corner] +
  10733. + volt_adjust[i]);
  10734. + }
  10735. +
  10736. + return 0;
  10737. +}
  10738. +
  10739. +/**
  10740. + * cpr4_ipq807x_apss_calculate_target_quotients() - calculate the CPR target
  10741. + * quotient for each corner of a CPR3 regulator
  10742. + * @vreg: Pointer to the CPR3 regulator
  10743. + *
  10744. + * If target quotient interpolation is allowed in device tree, then this
  10745. + * function calculates the target quotient for a given corner using linear
  10746. + * interpolation. This interpolation is performed using the processor
  10747. + * frequencies of the lower and higher Fmax corners along with the fused
  10748. + * target quotient and quotient offset of the higher Fmax corner.
  10749. + *
  10750. + * If target quotient interpolation is not allowed, then this function uses
  10751. + * the Fmax fused target quotient for all of the corners associated with a
  10752. + * given fuse corner.
  10753. + *
  10754. + * Return: 0 on success, errno on failure
  10755. + */
  10756. +static int cpr4_ipq807x_apss_calculate_target_quotients(
  10757. + struct cpr3_regulator *vreg)
  10758. +{
  10759. + struct cpr4_ipq807x_apss_fuses *fuse = vreg->platform_fuses;
  10760. + int rc;
  10761. + bool allow_interpolation;
  10762. + u64 freq_low, freq_high, prev_quot;
  10763. + u64 *quot_low;
  10764. + u64 *quot_high;
  10765. + u32 quot, ro;
  10766. + int i, j, fuse_corner, quot_adjust;
  10767. + int *fmax_corner;
  10768. + int *volt_adjust, *volt_adjust_fuse, *ro_scale;
  10769. + int *voltage_adj_misc;
  10770. +
  10771. + /* Log fused quotient values for debugging purposes. */
  10772. + for (i = CPR4_IPQ807x_APSS_FUSE_CORNER_SVS;
  10773. + i < vreg->fuse_corner_count; i++)
  10774. + cpr3_info(vreg, "fused %8s: quot[%2llu]=%4llu, quot_offset[%2llu]=%4llu\n",
  10775. + cpr4_ipq807x_apss_fuse_corner_name[i],
  10776. + fuse->ro_sel[i], fuse->target_quot[i],
  10777. + fuse->ro_sel[i], fuse->quot_offset[i] *
  10778. + IPQ807x_APSS_QUOT_OFFSET_SCALE);
  10779. +
  10780. + allow_interpolation = of_property_read_bool(vreg->of_node,
  10781. + "qcom,allow-quotient-interpolation");
  10782. +
  10783. + volt_adjust = kcalloc(vreg->corner_count, sizeof(*volt_adjust),
  10784. + GFP_KERNEL);
  10785. + volt_adjust_fuse = kcalloc(vreg->fuse_corner_count,
  10786. + sizeof(*volt_adjust_fuse), GFP_KERNEL);
  10787. + ro_scale = kcalloc(vreg->fuse_corner_count, sizeof(*ro_scale),
  10788. + GFP_KERNEL);
  10789. + fmax_corner = kcalloc(vreg->fuse_corner_count, sizeof(*fmax_corner),
  10790. + GFP_KERNEL);
  10791. + quot_low = kcalloc(vreg->fuse_corner_count, sizeof(*quot_low),
  10792. + GFP_KERNEL);
  10793. + quot_high = kcalloc(vreg->fuse_corner_count, sizeof(*quot_high),
  10794. + GFP_KERNEL);
  10795. + if (!volt_adjust || !volt_adjust_fuse || !ro_scale ||
  10796. + !fmax_corner || !quot_low || !quot_high) {
  10797. + rc = -ENOMEM;
  10798. + goto done;
  10799. + }
  10800. +
  10801. + rc = cpr3_parse_closed_loop_voltage_adjustments(vreg, &fuse->ro_sel[0],
  10802. + volt_adjust, volt_adjust_fuse, ro_scale);
  10803. + if (rc) {
  10804. + cpr3_err(vreg, "could not load closed-loop voltage adjustments, rc=%d\n",
  10805. + rc);
  10806. + goto done;
  10807. + }
  10808. +
  10809. + if (of_find_property(vreg->of_node,
  10810. + "qcom,cpr-misc-fuse-voltage-adjustment", NULL)) {
  10811. + voltage_adj_misc = kcalloc(vreg->corner_count,
  10812. + sizeof(*voltage_adj_misc), GFP_KERNEL);
  10813. + if (!voltage_adj_misc) {
  10814. + rc = -ENOMEM;
  10815. + goto done;
  10816. + }
  10817. +
  10818. + rc = cpr4_apss_parse_misc_fuse_voltage_adjustments(vreg,
  10819. + voltage_adj_misc);
  10820. + if (rc) {
  10821. + cpr3_err(vreg, "qcom,cpr-misc-fuse-voltage-adjustment reading failed, rc=%d\n",
  10822. + rc);
  10823. + kfree(voltage_adj_misc);
  10824. + goto done;
  10825. + }
  10826. +
  10827. + for (i = 0; i < vreg->corner_count; i++)
  10828. + volt_adjust[i] += voltage_adj_misc[i];
  10829. +
  10830. + kfree(voltage_adj_misc);
  10831. + }
  10832. +
  10833. + if (!allow_interpolation) {
  10834. + /* Use fused target quotients for lower frequencies. */
  10835. + return cpr4_ipq807x_apss_set_no_interpolation_quotients(
  10836. + vreg, volt_adjust, volt_adjust_fuse, ro_scale);
  10837. + }
  10838. +
  10839. + /* Determine highest corner mapped to each fuse corner */
  10840. + j = vreg->fuse_corner_count - 1;
  10841. + for (i = vreg->corner_count - 1; i >= 0; i--) {
  10842. + if (vreg->corner[i].cpr_fuse_corner == j) {
  10843. + fmax_corner[j] = i;
  10844. + j--;
  10845. + }
  10846. + }
  10847. + if (j >= 0) {
  10848. + cpr3_err(vreg, "invalid fuse corner mapping\n");
  10849. + rc = -EINVAL;
  10850. + goto done;
  10851. + }
  10852. +
  10853. + /*
  10854. + * Interpolation is not possible for corners mapped to the lowest fuse
  10855. + * corner so use the fuse corner value directly.
  10856. + */
  10857. + i = CPR4_IPQ807x_APSS_FUSE_CORNER_SVS;
  10858. + quot_adjust = cpr3_quot_adjustment(ro_scale[i], volt_adjust_fuse[i]);
  10859. + quot = fuse->target_quot[i] + quot_adjust;
  10860. + quot_high[i] = quot_low[i] = quot;
  10861. + ro = fuse->ro_sel[i];
  10862. + if (quot_adjust)
  10863. + cpr3_debug(vreg, "adjusted fuse corner %d RO%u target quot: %llu --> %u (%d uV)\n",
  10864. + i, ro, fuse->target_quot[i], quot, volt_adjust_fuse[i]);
  10865. +
  10866. + for (i = 0; i <= fmax_corner[CPR4_IPQ807x_APSS_FUSE_CORNER_SVS];
  10867. + i++)
  10868. + vreg->corner[i].target_quot[ro] = quot;
  10869. +
  10870. + for (i = CPR4_IPQ807x_APSS_FUSE_CORNER_NOM;
  10871. + i < vreg->fuse_corner_count; i++) {
  10872. + quot_high[i] = fuse->target_quot[i];
  10873. + if (fuse->ro_sel[i] == fuse->ro_sel[i - 1])
  10874. + quot_low[i] = quot_high[i - 1];
  10875. + else
  10876. + quot_low[i] = quot_high[i]
  10877. + - fuse->quot_offset[i]
  10878. + * IPQ807x_APSS_QUOT_OFFSET_SCALE;
  10879. + if (quot_high[i] < quot_low[i]) {
  10880. + cpr3_debug(vreg, "quot_high[%d]=%llu < quot_low[%d]=%llu; overriding: quot_high[%d]=%llu\n",
  10881. + i, quot_high[i], i, quot_low[i],
  10882. + i, quot_low[i]);
  10883. + quot_high[i] = quot_low[i];
  10884. + }
  10885. + }
  10886. +
  10887. + /* Perform per-fuse-corner target quotient adjustment */
  10888. + for (i = 1; i < vreg->fuse_corner_count; i++) {
  10889. + quot_adjust = cpr3_quot_adjustment(ro_scale[i],
  10890. + volt_adjust_fuse[i]);
  10891. + if (quot_adjust) {
  10892. + prev_quot = quot_high[i];
  10893. + quot_high[i] += quot_adjust;
  10894. + cpr3_debug(vreg, "adjusted fuse corner %d RO%llu target quot: %llu --> %llu (%d uV)\n",
  10895. + i, fuse->ro_sel[i], prev_quot, quot_high[i],
  10896. + volt_adjust_fuse[i]);
  10897. + }
  10898. +
  10899. + if (fuse->ro_sel[i] == fuse->ro_sel[i - 1])
  10900. + quot_low[i] = quot_high[i - 1];
  10901. + else
  10902. + quot_low[i] += cpr3_quot_adjustment(ro_scale[i],
  10903. + volt_adjust_fuse[i - 1]);
  10904. +
  10905. + if (quot_high[i] < quot_low[i]) {
  10906. + cpr3_debug(vreg, "quot_high[%d]=%llu < quot_low[%d]=%llu after adjustment; overriding: quot_high[%d]=%llu\n",
  10907. + i, quot_high[i], i, quot_low[i],
  10908. + i, quot_low[i]);
  10909. + quot_high[i] = quot_low[i];
  10910. + }
  10911. + }
  10912. +
  10913. + /* Interpolate voltages for the higher fuse corners. */
  10914. + for (i = 1; i < vreg->fuse_corner_count; i++) {
  10915. + freq_low = vreg->corner[fmax_corner[i - 1]].proc_freq;
  10916. + freq_high = vreg->corner[fmax_corner[i]].proc_freq;
  10917. +
  10918. + ro = fuse->ro_sel[i];
  10919. + for (j = fmax_corner[i - 1] + 1; j <= fmax_corner[i]; j++)
  10920. + vreg->corner[j].target_quot[ro] = cpr3_interpolate(
  10921. + freq_low, quot_low[i], freq_high, quot_high[i],
  10922. + vreg->corner[j].proc_freq);
  10923. + }
  10924. +
  10925. + /* Perform per-corner target quotient adjustment */
  10926. + for (i = 0; i < vreg->corner_count; i++) {
  10927. + fuse_corner = vreg->corner[i].cpr_fuse_corner;
  10928. + ro = fuse->ro_sel[fuse_corner];
  10929. + quot_adjust = cpr3_quot_adjustment(ro_scale[fuse_corner],
  10930. + volt_adjust[i]);
  10931. + if (quot_adjust) {
  10932. + prev_quot = vreg->corner[i].target_quot[ro];
  10933. + vreg->corner[i].target_quot[ro] += quot_adjust;
  10934. + cpr3_debug(vreg, "adjusted corner %d RO%u target quot: %llu --> %u (%d uV)\n",
  10935. + i, ro, prev_quot,
  10936. + vreg->corner[i].target_quot[ro],
  10937. + volt_adjust[i]);
  10938. + }
  10939. + }
  10940. +
  10941. + /* Ensure that target quotients increase monotonically */
  10942. + for (i = 1; i < vreg->corner_count; i++) {
  10943. + ro = fuse->ro_sel[vreg->corner[i].cpr_fuse_corner];
  10944. + if (fuse->ro_sel[vreg->corner[i - 1].cpr_fuse_corner] == ro
  10945. + && vreg->corner[i].target_quot[ro]
  10946. + < vreg->corner[i - 1].target_quot[ro]) {
  10947. + cpr3_debug(vreg, "adjusted corner %d RO%u target quot=%u < adjusted corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
  10948. + i, ro, vreg->corner[i].target_quot[ro],
  10949. + i - 1, ro, vreg->corner[i - 1].target_quot[ro],
  10950. + i, ro, vreg->corner[i - 1].target_quot[ro]);
  10951. + vreg->corner[i].target_quot[ro]
  10952. + = vreg->corner[i - 1].target_quot[ro];
  10953. + }
  10954. + }
  10955. +
  10956. +done:
  10957. + kfree(volt_adjust);
  10958. + kfree(volt_adjust_fuse);
  10959. + kfree(ro_scale);
  10960. + kfree(fmax_corner);
  10961. + kfree(quot_low);
  10962. + kfree(quot_high);
  10963. + return rc;
  10964. +}
  10965. +
  10966. +/**
  10967. + * cpr4_apss_print_settings() - print out APSS CPR configuration settings into
  10968. + * the kernel log for debugging purposes
  10969. + * @vreg: Pointer to the CPR3 regulator
  10970. + */
  10971. +static void cpr4_apss_print_settings(struct cpr3_regulator *vreg)
  10972. +{
  10973. + struct cpr3_corner *corner;
  10974. + int i;
  10975. +
  10976. + cpr3_debug(vreg, "Corner: Frequency (Hz), Fuse Corner, Floor (uV), Open-Loop (uV), Ceiling (uV)\n");
  10977. + for (i = 0; i < vreg->corner_count; i++) {
  10978. + corner = &vreg->corner[i];
  10979. + cpr3_debug(vreg, "%3d: %10u, %2d, %7d, %7d, %7d\n",
  10980. + i, corner->proc_freq, corner->cpr_fuse_corner,
  10981. + corner->floor_volt, corner->open_loop_volt,
  10982. + corner->ceiling_volt);
  10983. + }
  10984. +
  10985. + if (vreg->thread->ctrl->apm)
  10986. + cpr3_debug(vreg, "APM threshold = %d uV, APM adjust = %d uV\n",
  10987. + vreg->thread->ctrl->apm_threshold_volt,
  10988. + vreg->thread->ctrl->apm_adj_volt);
  10989. +}
  10990. +
  10991. +/**
  10992. + * cpr4_apss_init_thread() - perform steps necessary to initialize the
  10993. + * configuration data for a CPR3 thread
  10994. + * @thread: Pointer to the CPR3 thread
  10995. + *
  10996. + * Return: 0 on success, errno on failure
  10997. + */
  10998. +static int cpr4_apss_init_thread(struct cpr3_thread *thread)
  10999. +{
  11000. + int rc;
  11001. +
  11002. + rc = cpr3_parse_common_thread_data(thread);
  11003. + if (rc) {
  11004. + cpr3_err(thread->ctrl, "thread %u unable to read CPR thread data from device tree, rc=%d\n",
  11005. + thread->thread_id, rc);
  11006. + return rc;
  11007. + }
  11008. +
  11009. + return 0;
  11010. +}
  11011. +
  11012. +/**
  11013. + * cpr4_apss_parse_temp_adj_properties() - parse temperature based
  11014. + * adjustment properties from device tree.
  11015. + * @ctrl: Pointer to the CPR3 controller
  11016. + *
  11017. + * Return: 0 on success, errno on failure
  11018. + */
  11019. +static int cpr4_apss_parse_temp_adj_properties(struct cpr3_controller *ctrl)
  11020. +{
  11021. + struct device_node *of_node = ctrl->dev->of_node;
  11022. + int rc, i, len, temp_point_count;
  11023. +
  11024. + if (!of_find_property(of_node, "qcom,cpr-temp-point-map", &len)) {
  11025. + /*
  11026. + * Temperature based adjustments are not defined. Single
  11027. + * temperature band is still valid for per-online-core
  11028. + * adjustments.
  11029. + */
  11030. + ctrl->temp_band_count = 1;
  11031. + return 0;
  11032. + }
  11033. +
  11034. + temp_point_count = len / sizeof(u32);
  11035. + if (temp_point_count <= 0 ||
  11036. + temp_point_count > IPQ807x_APSS_MAX_TEMP_POINTS) {
  11037. + cpr3_err(ctrl, "invalid number of temperature points %d > %d (max)\n",
  11038. + temp_point_count, IPQ807x_APSS_MAX_TEMP_POINTS);
  11039. + return -EINVAL;
  11040. + }
  11041. +
  11042. + ctrl->temp_points = devm_kcalloc(ctrl->dev, temp_point_count,
  11043. + sizeof(*ctrl->temp_points), GFP_KERNEL);
  11044. + if (!ctrl->temp_points)
  11045. + return -ENOMEM;
  11046. +
  11047. + rc = of_property_read_u32_array(of_node, "qcom,cpr-temp-point-map",
  11048. + ctrl->temp_points, temp_point_count);
  11049. + if (rc) {
  11050. + cpr3_err(ctrl, "error reading property qcom,cpr-temp-point-map, rc=%d\n",
  11051. + rc);
  11052. + return rc;
  11053. + }
  11054. +
  11055. + for (i = 0; i < temp_point_count; i++)
  11056. + cpr3_debug(ctrl, "Temperature Point %d=%d\n", i,
  11057. + ctrl->temp_points[i]);
  11058. +
  11059. + /*
  11060. + * If t1, t2, and t3 are the temperature points, then the temperature
  11061. + * bands are: (-inf, t1], (t1, t2], (t2, t3], and (t3, inf).
  11062. + */
  11063. + ctrl->temp_band_count = temp_point_count + 1;
  11064. + cpr3_debug(ctrl, "Number of temp bands =%d\n", ctrl->temp_band_count);
  11065. +
  11066. + rc = of_property_read_u32(of_node, "qcom,cpr-initial-temp-band",
  11067. + &ctrl->initial_temp_band);
  11068. + if (rc) {
  11069. + cpr3_err(ctrl, "error reading qcom,cpr-initial-temp-band, rc=%d\n",
  11070. + rc);
  11071. + return rc;
  11072. + }
  11073. +
  11074. + if (ctrl->initial_temp_band >= ctrl->temp_band_count) {
  11075. + cpr3_err(ctrl, "Initial temperature band value %d should be in range [0 - %d]\n",
  11076. + ctrl->initial_temp_band, ctrl->temp_band_count - 1);
  11077. + return -EINVAL;
  11078. + }
  11079. +
  11080. + ctrl->temp_sensor_id_start = IPQ807x_APSS_TEMP_SENSOR_ID_START;
  11081. + ctrl->temp_sensor_id_end = IPQ807x_APSS_TEMP_SENSOR_ID_END;
  11082. + ctrl->allow_temp_adj = true;
  11083. + return rc;
  11084. +}
  11085. +
  11086. +/**
  11087. + * cpr4_apss_parse_boost_properties() - parse configuration data for boost
  11088. + * voltage adjustment for CPR3 regulator from device tree.
  11089. + * @vreg: Pointer to the CPR3 regulator
  11090. + *
  11091. + * Return: 0 on success, errno on failure
  11092. + */
  11093. +static int cpr4_apss_parse_boost_properties(struct cpr3_regulator *vreg)
  11094. +{
  11095. + struct cpr3_controller *ctrl = vreg->thread->ctrl;
  11096. + struct cpr4_ipq807x_apss_fuses *fuse = vreg->platform_fuses;
  11097. + struct cpr3_corner *corner;
  11098. + int i, boost_voltage, final_boost_volt, rc = 0;
  11099. + int *boost_table = NULL, *boost_temp_adj = NULL;
  11100. + int boost_voltage_adjust = 0, boost_num_cores = 0;
  11101. + u32 boost_allowed = 0;
  11102. +
  11103. + if (!boost_fuse[fuse->boost_cfg])
  11104. + /* Voltage boost is disabled in fuse */
  11105. + return 0;
  11106. +
  11107. + if (of_find_property(vreg->of_node, "qcom,allow-boost", NULL)) {
  11108. + rc = cpr3_parse_array_property(vreg, "qcom,allow-boost", 1,
  11109. + &boost_allowed);
  11110. + if (rc)
  11111. + return rc;
  11112. + }
  11113. +
  11114. + if (!boost_allowed) {
  11115. + /* Voltage boost is not enabled for this regulator */
  11116. + return 0;
  11117. + }
  11118. +
  11119. + boost_voltage = cpr3_convert_open_loop_voltage_fuse(
  11120. + vreg->cpr4_regulator_data->boost_fuse_ref_volt,
  11121. + vreg->cpr4_regulator_data->fuse_step_volt,
  11122. + fuse->boost_voltage,
  11123. + IPQ807x_APSS_VOLTAGE_FUSE_SIZE);
  11124. +
  11125. + /* Log boost voltage value for debugging purposes. */
  11126. + cpr3_info(vreg, "Boost open-loop=%7d uV\n", boost_voltage);
  11127. +
  11128. + if (of_find_property(vreg->of_node,
  11129. + "qcom,cpr-boost-voltage-fuse-adjustment", NULL)) {
  11130. + rc = cpr3_parse_array_property(vreg,
  11131. + "qcom,cpr-boost-voltage-fuse-adjustment",
  11132. + 1, &boost_voltage_adjust);
  11133. + if (rc) {
  11134. + cpr3_err(vreg, "qcom,cpr-boost-voltage-fuse-adjustment reading failed, rc=%d\n",
  11135. + rc);
  11136. + return rc;
  11137. + }
  11138. +
  11139. + boost_voltage += boost_voltage_adjust;
  11140. + /* Log boost voltage value for debugging purposes. */
  11141. + cpr3_info(vreg, "Adjusted boost open-loop=%7d uV\n",
  11142. + boost_voltage);
  11143. + }
  11144. +
  11145. + /* Limit boost voltage value between ceiling and floor voltage limits */
  11146. + boost_voltage = min(boost_voltage, vreg->cpr4_regulator_data->boost_ceiling_volt);
  11147. + boost_voltage = max(boost_voltage, vreg->cpr4_regulator_data->boost_floor_volt);
  11148. +
  11149. + /*
  11150. + * The boost feature can only be used for the highest voltage corner.
  11151. + * Also, keep core-count adjustments disabled when the boost feature
  11152. + * is enabled.
  11153. + */
  11154. + corner = &vreg->corner[vreg->corner_count - 1];
  11155. + if (!corner->sdelta) {
  11156. + /*
  11157. + * If core-count/temp adjustments are not defined, the cpr4
  11158. + * sdelta for this corner will not be allocated. Allocate it
  11159. + * here for boost configuration.
  11160. + */
  11161. + corner->sdelta = devm_kzalloc(ctrl->dev,
  11162. + sizeof(*corner->sdelta), GFP_KERNEL);
  11163. + if (!corner->sdelta)
  11164. + return -ENOMEM;
  11165. + }
  11166. + corner->sdelta->temp_band_count = ctrl->temp_band_count;
  11167. +
  11168. + rc = of_property_read_u32(vreg->of_node, "qcom,cpr-num-boost-cores",
  11169. + &boost_num_cores);
  11170. + if (rc) {
  11171. + cpr3_err(vreg, "qcom,cpr-num-boost-cores reading failed, rc=%d\n",
  11172. + rc);
  11173. + return rc;
  11174. + }
  11175. +
  11176. + if (boost_num_cores <= 0 ||
  11177. + boost_num_cores > IPQ807x_APSS_CPR_SDELTA_CORE_COUNT) {
  11178. + cpr3_err(vreg, "Invalid boost number of cores = %d\n",
  11179. + boost_num_cores);
  11180. + return -EINVAL;
  11181. + }
  11182. + corner->sdelta->boost_num_cores = boost_num_cores;
  11183. +
  11184. + boost_table = devm_kcalloc(ctrl->dev, corner->sdelta->temp_band_count,
  11185. + sizeof(*boost_table), GFP_KERNEL);
  11186. + if (!boost_table)
  11187. + return -ENOMEM;
  11188. +
  11189. + if (of_find_property(vreg->of_node,
  11190. + "qcom,cpr-boost-temp-adjustment", NULL)) {
  11191. + boost_temp_adj = kcalloc(corner->sdelta->temp_band_count,
  11192. + sizeof(*boost_temp_adj), GFP_KERNEL);
  11193. + if (!boost_temp_adj)
  11194. + return -ENOMEM;
  11195. +
  11196. + rc = cpr3_parse_array_property(vreg,
  11197. + "qcom,cpr-boost-temp-adjustment",
  11198. + corner->sdelta->temp_band_count,
  11199. + boost_temp_adj);
  11200. + if (rc) {
  11201. + cpr3_err(vreg, "qcom,cpr-boost-temp-adjustment reading failed, rc=%d\n",
  11202. + rc);
  11203. + goto done;
  11204. + }
  11205. + }
  11206. +
  11207. + for (i = 0; i < corner->sdelta->temp_band_count; i++) {
  11208. + /* Apply static adjustments to boost voltage */
  11209. + final_boost_volt = boost_voltage + (boost_temp_adj == NULL
  11210. + ? 0 : boost_temp_adj[i]);
  11211. + /*
  11212. + * Limit final adjusted boost voltage value between ceiling
  11213. + * and floor voltage limits
  11214. + */
  11215. + final_boost_volt = min(final_boost_volt,
  11216. + vreg->cpr4_regulator_data->boost_ceiling_volt);
  11217. + final_boost_volt = max(final_boost_volt,
  11218. + vreg->cpr4_regulator_data->boost_floor_volt);
  11219. +
  11220. + boost_table[i] = (corner->open_loop_volt - final_boost_volt)
  11221. + / ctrl->step_volt;
  11222. + cpr3_debug(vreg, "Adjusted boost voltage margin for temp band %d = %d steps\n",
  11223. + i, boost_table[i]);
  11224. + }
  11225. +
  11226. + corner->ceiling_volt = vreg->cpr4_regulator_data->boost_ceiling_volt;
  11227. + corner->sdelta->boost_table = boost_table;
  11228. + corner->sdelta->allow_boost = true;
  11229. + corner->sdelta->allow_core_count_adj = false;
  11230. + vreg->allow_boost = true;
  11231. + ctrl->allow_boost = true;
  11232. +done:
  11233. + kfree(boost_temp_adj);
  11234. + return rc;
  11235. +}
  11236. +
  11237. +/**
  11238. + * cpr4_apss_init_regulator() - perform all steps necessary to initialize the
  11239. + * configuration data for a CPR3 regulator
  11240. + * @vreg: Pointer to the CPR3 regulator
  11241. + *
  11242. + * Return: 0 on success, errno on failure
  11243. + */
  11244. +static int cpr4_apss_init_regulator(struct cpr3_regulator *vreg)
  11245. +{
  11246. + struct cpr4_ipq807x_apss_fuses *fuse;
  11247. + int rc;
  11248. +
  11249. + rc = cpr4_ipq807x_apss_read_fuse_data(vreg);
  11250. + if (rc) {
  11251. + cpr3_err(vreg, "unable to read CPR fuse data, rc=%d\n", rc);
  11252. + return rc;
  11253. + }
  11254. +
  11255. + fuse = vreg->platform_fuses;
  11256. +
  11257. + rc = cpr4_apss_parse_corner_data(vreg);
  11258. + if (rc) {
  11259. + cpr3_err(vreg, "unable to read CPR corner data from device tree, rc=%d\n",
  11260. + rc);
  11261. + return rc;
  11262. + }
  11263. +
  11264. + rc = cpr3_mem_acc_init(vreg);
  11265. + if (rc) {
  11266. + if (rc != -EPROBE_DEFER)
  11267. + cpr3_err(vreg, "unable to initialize mem-acc regulator settings, rc=%d\n",
  11268. + rc);
  11269. + return rc;
  11270. + }
  11271. +
  11272. + rc = cpr4_ipq807x_apss_calculate_open_loop_voltages(vreg);
  11273. + if (rc) {
  11274. + cpr3_err(vreg, "unable to calculate open-loop voltages, rc=%d\n",
  11275. + rc);
  11276. + return rc;
  11277. + }
  11278. +
  11279. + rc = cpr3_limit_open_loop_voltages(vreg);
  11280. + if (rc) {
  11281. + cpr3_err(vreg, "unable to limit open-loop voltages, rc=%d\n",
  11282. + rc);
  11283. + return rc;
  11284. + }
  11285. +
  11286. + cpr3_open_loop_voltage_as_ceiling(vreg);
  11287. +
  11288. + rc = cpr3_limit_floor_voltages(vreg);
  11289. + if (rc) {
  11290. + cpr3_err(vreg, "unable to limit floor voltages, rc=%d\n", rc);
  11291. + return rc;
  11292. + }
  11293. +
  11294. + rc = cpr4_ipq807x_apss_calculate_target_quotients(vreg);
  11295. + if (rc) {
  11296. + cpr3_err(vreg, "unable to calculate target quotients, rc=%d\n",
  11297. + rc);
  11298. + return rc;
  11299. + }
  11300. +
  11301. + rc = cpr4_parse_core_count_temp_voltage_adj(vreg, false);
  11302. + if (rc) {
  11303. + cpr3_err(vreg, "unable to parse temperature and core count voltage adjustments, rc=%d\n",
  11304. + rc);
  11305. + return rc;
  11306. + }
  11307. +
  11308. + if (vreg->allow_core_count_adj && (vreg->max_core_count <= 0
  11309. + || vreg->max_core_count >
  11310. + IPQ807x_APSS_CPR_SDELTA_CORE_COUNT)) {
  11311. + cpr3_err(vreg, "qcom,max-core-count has invalid value = %d\n",
  11312. + vreg->max_core_count);
  11313. + return -EINVAL;
  11314. + }
  11315. +
  11316. + rc = cpr4_apss_parse_boost_properties(vreg);
  11317. + if (rc) {
  11318. + cpr3_err(vreg, "unable to parse boost adjustments, rc=%d\n",
  11319. + rc);
  11320. + return rc;
  11321. + }
  11322. +
  11323. + cpr4_apss_print_settings(vreg);
  11324. +
  11325. + return rc;
  11326. +}
  11327. +
  11328. +/**
  11329. + * cpr4_apss_init_controller() - perform APSS CPR4 controller specific
  11330. + * initializations
  11331. + * @ctrl: Pointer to the CPR3 controller
  11332. + *
  11333. + * Return: 0 on success, errno on failure
  11334. + */
  11335. +static int cpr4_apss_init_controller(struct cpr3_controller *ctrl)
  11336. +{
  11337. + int rc;
  11338. +
  11339. + rc = cpr3_parse_common_ctrl_data(ctrl);
  11340. + if (rc) {
  11341. + if (rc != -EPROBE_DEFER)
  11342. + cpr3_err(ctrl, "unable to parse common controller data, rc=%d\n",
  11343. + rc);
  11344. + return rc;
  11345. + }
  11346. +
  11347. + rc = of_property_read_u32(ctrl->dev->of_node,
  11348. + "qcom,cpr-down-error-step-limit",
  11349. + &ctrl->down_error_step_limit);
  11350. + if (rc) {
  11351. + cpr3_err(ctrl, "error reading qcom,cpr-down-error-step-limit, rc=%d\n",
  11352. + rc);
  11353. + return rc;
  11354. + }
  11355. +
  11356. + rc = of_property_read_u32(ctrl->dev->of_node,
  11357. + "qcom,cpr-up-error-step-limit",
  11358. + &ctrl->up_error_step_limit);
  11359. + if (rc) {
  11360. + cpr3_err(ctrl, "error reading qcom,cpr-up-error-step-limit, rc=%d\n",
  11361. + rc);
  11362. + return rc;
  11363. + }
  11364. +
  11365. + /*
  11366. + * Use fixed step quotient if specified otherwise use dynamic
  11367. + * calculated per RO step quotient
  11368. + */
  11369. + of_property_read_u32(ctrl->dev->of_node, "qcom,cpr-step-quot-fixed",
  11370. + &ctrl->step_quot_fixed);
  11371. + ctrl->use_dynamic_step_quot = ctrl->step_quot_fixed ? false : true;
  11372. +
  11373. + ctrl->saw_use_unit_mV = of_property_read_bool(ctrl->dev->of_node,
  11374. + "qcom,cpr-saw-use-unit-mV");
  11375. +
  11376. + of_property_read_u32(ctrl->dev->of_node,
  11377. + "qcom,cpr-voltage-settling-time",
  11378. + &ctrl->voltage_settling_time);
  11379. +
  11380. + if (of_find_property(ctrl->dev->of_node, "vdd-limit-supply", NULL)) {
  11381. + ctrl->vdd_limit_regulator =
  11382. + devm_regulator_get(ctrl->dev, "vdd-limit");
  11383. + if (IS_ERR(ctrl->vdd_limit_regulator)) {
  11384. + rc = PTR_ERR(ctrl->vdd_limit_regulator);
  11385. + if (rc != -EPROBE_DEFER)
  11386. + cpr3_err(ctrl, "unable to request vdd-limit regulator, rc=%d\n",
  11387. + rc);
  11388. + return rc;
  11389. + }
  11390. + }
  11391. +
  11392. + rc = cpr3_apm_init(ctrl);
  11393. + if (rc) {
  11394. + if (rc != -EPROBE_DEFER)
  11395. + cpr3_err(ctrl, "unable to initialize APM settings, rc=%d\n",
  11396. + rc);
  11397. + return rc;
  11398. + }
  11399. +
  11400. + rc = cpr4_apss_parse_temp_adj_properties(ctrl);
  11401. + if (rc) {
  11402. + cpr3_err(ctrl, "unable to parse temperature adjustment properties, rc=%d\n",
  11403. + rc);
  11404. + return rc;
  11405. + }
  11406. +
  11407. + ctrl->sensor_count = IPQ807x_APSS_CPR_SENSOR_COUNT;
  11408. +
  11409. + /*
  11410. + * APSS only has one thread (0) per controller so the zeroed
  11411. + * array does not need further modification.
  11412. + */
  11413. + ctrl->sensor_owner = devm_kcalloc(ctrl->dev, ctrl->sensor_count,
  11414. + sizeof(*ctrl->sensor_owner), GFP_KERNEL);
  11415. + if (!ctrl->sensor_owner)
  11416. + return -ENOMEM;
  11417. +
  11418. + ctrl->ctrl_type = CPR_CTRL_TYPE_CPR4;
  11419. + ctrl->supports_hw_closed_loop = false;
  11420. + ctrl->use_hw_closed_loop = of_property_read_bool(ctrl->dev->of_node,
  11421. + "qcom,cpr-hw-closed-loop");
  11422. + return 0;
  11423. +}
  11424. +
  11425. +static int cpr4_apss_regulator_suspend(struct platform_device *pdev,
  11426. + pm_message_t state)
  11427. +{
  11428. + struct cpr3_controller *ctrl = platform_get_drvdata(pdev);
  11429. +
  11430. + return cpr3_regulator_suspend(ctrl);
  11431. +}
  11432. +
  11433. +static int cpr4_apss_regulator_resume(struct platform_device *pdev)
  11434. +{
  11435. + struct cpr3_controller *ctrl = platform_get_drvdata(pdev);
  11436. +
  11437. + return cpr3_regulator_resume(ctrl);
  11438. +}
  11439. +
  11440. +static void ipq6018_set_mem_acc(struct regulator_dev *rdev)
  11441. +{
  11442. + struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
  11443. +
  11444. + ipq6018_mem_acc_tcsr[0].ioremap_addr =
  11445. + ioremap(ipq6018_mem_acc_tcsr[0].phy_addr, 0x4);
  11446. + ipq6018_mem_acc_tcsr[1].ioremap_addr =
  11447. + ioremap(ipq6018_mem_acc_tcsr[1].phy_addr, 0x4);
  11448. +
  11449. + if ((ipq6018_mem_acc_tcsr[0].ioremap_addr != NULL) &&
  11450. + (ipq6018_mem_acc_tcsr[1].ioremap_addr != NULL) &&
  11451. + (vreg->current_corner == (vreg->corner_count - CPR3_CORNER_OFFSET))) {
  11452. +
  11453. + writel_relaxed(ipq6018_mem_acc_tcsr[0].value,
  11454. + ipq6018_mem_acc_tcsr[0].ioremap_addr);
  11455. + writel_relaxed(ipq6018_mem_acc_tcsr[1].value,
  11456. + ipq6018_mem_acc_tcsr[1].ioremap_addr);
  11457. + }
  11458. +}
  11459. +
  11460. +static void ipq6018_clr_mem_acc(struct regulator_dev *rdev)
  11461. +{
  11462. + struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
  11463. +
  11464. + if ((ipq6018_mem_acc_tcsr[0].ioremap_addr != NULL) &&
  11465. + (ipq6018_mem_acc_tcsr[1].ioremap_addr != NULL) &&
  11466. + (vreg->current_corner != vreg->corner_count - CPR3_CORNER_OFFSET)) {
  11467. + writel_relaxed(0x0, ipq6018_mem_acc_tcsr[0].ioremap_addr);
  11468. + writel_relaxed(0x0, ipq6018_mem_acc_tcsr[1].ioremap_addr);
  11469. + }
  11470. +
  11471. + iounmap(ipq6018_mem_acc_tcsr[0].ioremap_addr);
  11472. + iounmap(ipq6018_mem_acc_tcsr[1].ioremap_addr);
  11473. +}
  11474. +
  11475. +static struct cpr4_mem_acc_func ipq6018_mem_acc_funcs = {
  11476. + .set_mem_acc = ipq6018_set_mem_acc,
  11477. + .clear_mem_acc = ipq6018_clr_mem_acc
  11478. +};
  11479. +
  11480. +static const struct cpr4_reg_data ipq807x_cpr_apss = {
  11481. + .cpr_valid_fuse_count = IPQ807x_APSS_FUSE_CORNERS,
  11482. + .fuse_ref_volt = ipq807x_apss_fuse_ref_volt,
  11483. + .fuse_step_volt = IPQ807x_APSS_FUSE_STEP_VOLT,
  11484. + .cpr_clk_rate = IPQ807x_APSS_CPR_CLOCK_RATE,
  11485. + .boost_fuse_ref_volt= IPQ807x_APSS_BOOST_FUSE_REF_VOLT,
  11486. + .boost_ceiling_volt= IPQ807x_APSS_BOOST_CEILING_VOLT,
  11487. + .boost_floor_volt= IPQ807x_APSS_BOOST_FLOOR_VOLT,
  11488. + .cpr3_fuse_params = &ipq807x_fuse_params,
  11489. + .mem_acc_funcs = NULL,
  11490. +};
  11491. +
  11492. +static const struct cpr4_reg_data ipq817x_cpr_apss = {
  11493. + .cpr_valid_fuse_count = IPQ817x_APPS_FUSE_CORNERS,
  11494. + .fuse_ref_volt = ipq807x_apss_fuse_ref_volt,
  11495. + .fuse_step_volt = IPQ807x_APSS_FUSE_STEP_VOLT,
  11496. + .cpr_clk_rate = IPQ807x_APSS_CPR_CLOCK_RATE,
  11497. + .boost_fuse_ref_volt= IPQ807x_APSS_BOOST_FUSE_REF_VOLT,
  11498. + .boost_ceiling_volt= IPQ807x_APSS_BOOST_CEILING_VOLT,
  11499. + .boost_floor_volt= IPQ807x_APSS_BOOST_FLOOR_VOLT,
  11500. + .cpr3_fuse_params = &ipq807x_fuse_params,
  11501. + .mem_acc_funcs = NULL,
  11502. +};
  11503. +
  11504. +static const struct cpr4_reg_data ipq6018_cpr_apss = {
  11505. + .cpr_valid_fuse_count = IPQ6018_APSS_FUSE_CORNERS,
  11506. + .fuse_ref_volt = ipq6018_apss_fuse_ref_volt,
  11507. + .fuse_step_volt = IPQ6018_APSS_FUSE_STEP_VOLT,
  11508. + .cpr_clk_rate = IPQ6018_APSS_CPR_CLOCK_RATE,
  11509. + .boost_fuse_ref_volt = IPQ6018_APSS_BOOST_FUSE_REF_VOLT,
  11510. + .boost_ceiling_volt = IPQ6018_APSS_BOOST_CEILING_VOLT,
  11511. + .boost_floor_volt = IPQ6018_APSS_BOOST_FLOOR_VOLT,
  11512. + .cpr3_fuse_params = &ipq6018_fuse_params,
  11513. + .mem_acc_funcs = &ipq6018_mem_acc_funcs,
  11514. +};
  11515. +
  11516. +static const struct cpr4_reg_data ipq9574_cpr_apss = {
  11517. + .cpr_valid_fuse_count = IPQ9574_APSS_FUSE_CORNERS,
  11518. + .fuse_ref_volt = ipq9574_apss_fuse_ref_volt,
  11519. + .fuse_step_volt = IPQ9574_APSS_FUSE_STEP_VOLT,
  11520. + .cpr_clk_rate = IPQ6018_APSS_CPR_CLOCK_RATE,
  11521. + .boost_fuse_ref_volt = IPQ6018_APSS_BOOST_FUSE_REF_VOLT,
  11522. + .boost_ceiling_volt = IPQ6018_APSS_BOOST_CEILING_VOLT,
  11523. + .boost_floor_volt = IPQ6018_APSS_BOOST_FLOOR_VOLT,
  11524. + .cpr3_fuse_params = &ipq9574_fuse_params,
  11525. + .mem_acc_funcs = NULL,
  11526. +};
  11527. +
  11528. +static struct of_device_id cpr4_regulator_match_table[] = {
  11529. + {
  11530. + .compatible = "qcom,cpr4-ipq807x-apss-regulator",
  11531. + .data = &ipq807x_cpr_apss
  11532. + },
  11533. + {
  11534. + .compatible = "qcom,cpr4-ipq817x-apss-regulator",
  11535. + .data = &ipq817x_cpr_apss
  11536. + },
  11537. + {
  11538. + .compatible = "qcom,cpr4-ipq6018-apss-regulator",
  11539. + .data = &ipq6018_cpr_apss
  11540. + },
  11541. + {
  11542. + .compatible = "qcom,cpr4-ipq9574-apss-regulator",
  11543. + .data = &ipq9574_cpr_apss
  11544. + },
  11545. + {}
  11546. +};
  11547. +
  11548. +static int cpr4_apss_regulator_probe(struct platform_device *pdev)
  11549. +{
  11550. + struct device *dev = &pdev->dev;
  11551. + struct cpr3_controller *ctrl;
  11552. + const struct of_device_id *match;
  11553. + struct cpr4_reg_data *cpr_data;
  11554. + int i, rc;
  11555. +
  11556. + if (!dev->of_node) {
  11557. + dev_err(dev, "Device tree node is missing\n");
  11558. + return -EINVAL;
  11559. + }
  11560. +
  11561. + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
  11562. + if (!ctrl)
  11563. + return -ENOMEM;
  11564. +
  11565. + match = of_match_device(cpr4_regulator_match_table, &pdev->dev);
  11566. + if (!match)
  11567. + return -ENODEV;
  11568. +
  11569. + cpr_data = (struct cpr4_reg_data *)match->data;
  11570. + g_valid_fuse_count = cpr_data->cpr_valid_fuse_count;
  11571. + dev_info(dev, "CPR valid fuse count: %d\n", g_valid_fuse_count);
  11572. + ctrl->cpr_clock_rate = cpr_data->cpr_clk_rate;
  11573. +
  11574. + ctrl->dev = dev;
  11575. + /* Set to false later if anything precludes CPR operation. */
  11576. + ctrl->cpr_allowed_hw = true;
  11577. +
  11578. + rc = of_property_read_string(dev->of_node, "qcom,cpr-ctrl-name",
  11579. + &ctrl->name);
  11580. + if (rc) {
  11581. + cpr3_err(ctrl, "unable to read qcom,cpr-ctrl-name, rc=%d\n",
  11582. + rc);
  11583. + return rc;
  11584. + }
  11585. +
  11586. + rc = cpr3_map_fuse_base(ctrl, pdev);
  11587. + if (rc) {
  11588. + cpr3_err(ctrl, "could not map fuse base address\n");
  11589. + return rc;
  11590. + }
  11591. +
  11592. + rc = cpr3_read_tcsr_setting(ctrl, pdev, IPQ807x_APSS_CPR_TCSR_START,
  11593. + IPQ807x_APSS_CPR_TCSR_END);
  11594. + if (rc) {
  11595. + cpr3_err(ctrl, "could not read CPR tcsr setting\n");
  11596. + return rc;
  11597. + }
  11598. +
  11599. + rc = cpr3_allocate_threads(ctrl, 0, 0);
  11600. + if (rc) {
  11601. + cpr3_err(ctrl, "failed to allocate CPR thread array, rc=%d\n",
  11602. + rc);
  11603. + return rc;
  11604. + }
  11605. +
  11606. + if (ctrl->thread_count != 1) {
  11607. + cpr3_err(ctrl, "expected 1 thread but found %d\n",
  11608. + ctrl->thread_count);
  11609. + return -EINVAL;
  11610. + }
  11611. +
  11612. + rc = cpr4_apss_init_controller(ctrl);
  11613. + if (rc) {
  11614. + if (rc != -EPROBE_DEFER)
  11615. + cpr3_err(ctrl, "failed to initialize CPR controller parameters, rc=%d\n",
  11616. + rc);
  11617. + return rc;
  11618. + }
  11619. +
  11620. + rc = cpr4_apss_init_thread(&ctrl->thread[0]);
  11621. + if (rc) {
  11622. + cpr3_err(ctrl, "thread initialization failed, rc=%d\n", rc);
  11623. + return rc;
  11624. + }
  11625. +
  11626. + for (i = 0; i < ctrl->thread[0].vreg_count; i++) {
  11627. + ctrl->thread[0].vreg[i].cpr4_regulator_data = cpr_data;
  11628. + rc = cpr4_apss_init_regulator(&ctrl->thread[0].vreg[i]);
  11629. + if (rc) {
  11630. + cpr3_err(&ctrl->thread[0].vreg[i], "regulator initialization failed, rc=%d\n",
  11631. + rc);
  11632. + return rc;
  11633. + }
  11634. + }
  11635. +
  11636. + platform_set_drvdata(pdev, ctrl);
  11637. +
  11638. + return cpr3_regulator_register(pdev, ctrl);
  11639. +}
  11640. +
  11641. +static int cpr4_apss_regulator_remove(struct platform_device *pdev)
  11642. +{
  11643. + struct cpr3_controller *ctrl = platform_get_drvdata(pdev);
  11644. +
  11645. + return cpr3_regulator_unregister(ctrl);
  11646. +}
  11647. +
  11648. +static struct platform_driver cpr4_apss_regulator_driver = {
  11649. + .driver = {
  11650. + .name = "qcom,cpr4-apss-regulator",
  11651. + .of_match_table = cpr4_regulator_match_table,
  11652. + .owner = THIS_MODULE,
  11653. + },
  11654. + .probe = cpr4_apss_regulator_probe,
  11655. + .remove = cpr4_apss_regulator_remove,
  11656. + .suspend = cpr4_apss_regulator_suspend,
  11657. + .resume = cpr4_apss_regulator_resume,
  11658. +};
  11659. +
  11660. +static int cpr4_regulator_init(void)
  11661. +{
  11662. + return platform_driver_register(&cpr4_apss_regulator_driver);
  11663. +}
  11664. +
  11665. +static void cpr4_regulator_exit(void)
  11666. +{
  11667. + platform_driver_unregister(&cpr4_apss_regulator_driver);
  11668. +}
  11669. +
  11670. +MODULE_DESCRIPTION("CPR4 APSS regulator driver");
  11671. +MODULE_LICENSE("GPL v2");
  11672. +
  11673. +arch_initcall(cpr4_regulator_init);
  11674. +module_exit(cpr4_regulator_exit);
  11675. --- /dev/null
  11676. +++ b/include/soc/qcom/socinfo.h
  11677. @@ -0,0 +1,463 @@
  11678. +/* Copyright (c) 2009-2014, 2016, 2020, The Linux Foundation. All rights reserved.
  11679. + *
  11680. + * This program is free software; you can redistribute it and/or modify
  11681. + * it under the terms of the GNU General Public License version 2 and
  11682. + * only version 2 as published by the Free Software Foundation.
  11683. + *
  11684. + * This program is distributed in the hope that it will be useful,
  11685. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11686. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11687. + * GNU General Public License for more details.
  11688. + *
  11689. + */
  11690. +
  11691. +#ifndef _ARCH_ARM_MACH_MSM_SOCINFO_H_
  11692. +#define _ARCH_ARM_MACH_MSM_SOCINFO_H_
  11693. +
  11694. +#include <linux/of.h>
  11695. +
  11696. +#define CPU_IPQ8074 323
  11697. +#define CPU_IPQ8072 342
  11698. +#define CPU_IPQ8076 343
  11699. +#define CPU_IPQ8078 344
  11700. +#define CPU_IPQ8070 375
  11701. +#define CPU_IPQ8071 376
  11702. +
  11703. +#define CPU_IPQ8072A 389
  11704. +#define CPU_IPQ8074A 390
  11705. +#define CPU_IPQ8076A 391
  11706. +#define CPU_IPQ8078A 392
  11707. +#define CPU_IPQ8070A 395
  11708. +#define CPU_IPQ8071A 396
  11709. +
  11710. +#define CPU_IPQ8172 397
  11711. +#define CPU_IPQ8173 398
  11712. +#define CPU_IPQ8174 399
  11713. +
  11714. +#define CPU_IPQ6018 402
  11715. +#define CPU_IPQ6028 403
  11716. +#define CPU_IPQ6000 421
  11717. +#define CPU_IPQ6010 422
  11718. +#define CPU_IPQ6005 453
  11719. +
  11720. +#define CPU_IPQ5010 446
  11721. +#define CPU_IPQ5018 447
  11722. +#define CPU_IPQ5028 448
  11723. +#define CPU_IPQ5000 503
  11724. +#define CPU_IPQ0509 504
  11725. +#define CPU_IPQ0518 505
  11726. +
  11727. +#define CPU_IPQ9514 510
  11728. +#define CPU_IPQ9554 512
  11729. +#define CPU_IPQ9570 513
  11730. +#define CPU_IPQ9574 514
  11731. +#define CPU_IPQ9550 511
  11732. +#define CPU_IPQ9510 521
  11733. +
  11734. +static inline int read_ipq_soc_version_major(void)
  11735. +{
  11736. + const int *prop;
  11737. + prop = of_get_property(of_find_node_by_path("/"), "soc_version_major",
  11738. + NULL);
  11739. +
  11740. + if (!prop)
  11741. + return -EINVAL;
  11742. +
  11743. + return le32_to_cpu(*prop);
  11744. +}
  11745. +
  11746. +static inline int read_ipq_cpu_type(void)
  11747. +{
  11748. + const int *prop;
  11749. + prop = of_get_property(of_find_node_by_path("/"), "cpu_type", NULL);
  11750. + /*
  11751. + * Return Default CPU type if "cpu_type" property is not found in DTSI
  11752. + */
  11753. + if (!prop)
  11754. + return CPU_IPQ8074;
  11755. +
  11756. + return le32_to_cpu(*prop);
  11757. +}
  11758. +
  11759. +static inline int cpu_is_ipq8070(void)
  11760. +{
  11761. +#ifdef CONFIG_ARCH_QCOM
  11762. + return read_ipq_cpu_type() == CPU_IPQ8070;
  11763. +#else
  11764. + return 0;
  11765. +#endif
  11766. +}
  11767. +
  11768. +static inline int cpu_is_ipq8071(void)
  11769. +{
  11770. +#ifdef CONFIG_ARCH_QCOM
  11771. + return read_ipq_cpu_type() == CPU_IPQ8071;
  11772. +#else
  11773. + return 0;
  11774. +#endif
  11775. +}
  11776. +
  11777. +static inline int cpu_is_ipq8072(void)
  11778. +{
  11779. +#ifdef CONFIG_ARCH_QCOM
  11780. + return read_ipq_cpu_type() == CPU_IPQ8072;
  11781. +#else
  11782. + return 0;
  11783. +#endif
  11784. +}
  11785. +
  11786. +static inline int cpu_is_ipq8074(void)
  11787. +{
  11788. +#ifdef CONFIG_ARCH_QCOM
  11789. + return read_ipq_cpu_type() == CPU_IPQ8074;
  11790. +#else
  11791. + return 0;
  11792. +#endif
  11793. +}
  11794. +
  11795. +static inline int cpu_is_ipq8076(void)
  11796. +{
  11797. +#ifdef CONFIG_ARCH_QCOM
  11798. + return read_ipq_cpu_type() == CPU_IPQ8076;
  11799. +#else
  11800. + return 0;
  11801. +#endif
  11802. +}
  11803. +
  11804. +static inline int cpu_is_ipq8078(void)
  11805. +{
  11806. +#ifdef CONFIG_ARCH_QCOM
  11807. + return read_ipq_cpu_type() == CPU_IPQ8078;
  11808. +#else
  11809. + return 0;
  11810. +#endif
  11811. +}
  11812. +
  11813. +static inline int cpu_is_ipq8072a(void)
  11814. +{
  11815. +#ifdef CONFIG_ARCH_QCOM
  11816. + return read_ipq_cpu_type() == CPU_IPQ8072A;
  11817. +#else
  11818. + return 0;
  11819. +#endif
  11820. +}
  11821. +
  11822. +static inline int cpu_is_ipq8074a(void)
  11823. +{
  11824. +#ifdef CONFIG_ARCH_QCOM
  11825. + return read_ipq_cpu_type() == CPU_IPQ8074A;
  11826. +#else
  11827. + return 0;
  11828. +#endif
  11829. +}
  11830. +
  11831. +static inline int cpu_is_ipq8076a(void)
  11832. +{
  11833. +#ifdef CONFIG_ARCH_QCOM
  11834. + return read_ipq_cpu_type() == CPU_IPQ8076A;
  11835. +#else
  11836. + return 0;
  11837. +#endif
  11838. +}
  11839. +
  11840. +static inline int cpu_is_ipq8078a(void)
  11841. +{
  11842. +#ifdef CONFIG_ARCH_QCOM
  11843. + return read_ipq_cpu_type() == CPU_IPQ8078A;
  11844. +#else
  11845. + return 0;
  11846. +#endif
  11847. +}
  11848. +
  11849. +static inline int cpu_is_ipq8070a(void)
  11850. +{
  11851. +#ifdef CONFIG_ARCH_QCOM
  11852. + return read_ipq_cpu_type() == CPU_IPQ8070A;
  11853. +#else
  11854. + return 0;
  11855. +#endif
  11856. +}
  11857. +
  11858. +static inline int cpu_is_ipq8071a(void)
  11859. +{
  11860. +#ifdef CONFIG_ARCH_QCOM
  11861. + return read_ipq_cpu_type() == CPU_IPQ8071A;
  11862. +#else
  11863. + return 0;
  11864. +#endif
  11865. +}
  11866. +
  11867. +static inline int cpu_is_ipq8172(void)
  11868. +{
  11869. +#ifdef CONFIG_ARCH_QCOM
  11870. + return read_ipq_cpu_type() == CPU_IPQ8172;
  11871. +#else
  11872. + return 0;
  11873. +#endif
  11874. +}
  11875. +
  11876. +static inline int cpu_is_ipq8173(void)
  11877. +{
  11878. +#ifdef CONFIG_ARCH_QCOM
  11879. + return read_ipq_cpu_type() == CPU_IPQ8173;
  11880. +#else
  11881. + return 0;
  11882. +#endif
  11883. +}
  11884. +
  11885. +static inline int cpu_is_ipq8174(void)
  11886. +{
  11887. +#ifdef CONFIG_ARCH_QCOM
  11888. + return read_ipq_cpu_type() == CPU_IPQ8174;
  11889. +#else
  11890. + return 0;
  11891. +#endif
  11892. +}
  11893. +
  11894. +static inline int cpu_is_ipq6018(void)
  11895. +{
  11896. +#ifdef CONFIG_ARCH_QCOM
  11897. + return read_ipq_cpu_type() == CPU_IPQ6018;
  11898. +#else
  11899. + return 0;
  11900. +#endif
  11901. +}
  11902. +
  11903. +static inline int cpu_is_ipq6028(void)
  11904. +{
  11905. +#ifdef CONFIG_ARCH_QCOM
  11906. + return read_ipq_cpu_type() == CPU_IPQ6028;
  11907. +#else
  11908. + return 0;
  11909. +#endif
  11910. +}
  11911. +
  11912. +static inline int cpu_is_ipq6000(void)
  11913. +{
  11914. +#ifdef CONFIG_ARCH_QCOM
  11915. + return read_ipq_cpu_type() == CPU_IPQ6000;
  11916. +#else
  11917. + return 0;
  11918. +#endif
  11919. +}
  11920. +
  11921. +static inline int cpu_is_ipq6010(void)
  11922. +{
  11923. +#ifdef CONFIG_ARCH_QCOM
  11924. + return read_ipq_cpu_type() == CPU_IPQ6010;
  11925. +#else
  11926. + return 0;
  11927. +#endif
  11928. +}
  11929. +
  11930. +static inline int cpu_is_ipq6005(void)
  11931. +{
  11932. +#ifdef CONFIG_ARCH_QCOM
  11933. + return read_ipq_cpu_type() == CPU_IPQ6005;
  11934. +#else
  11935. + return 0;
  11936. +#endif
  11937. +}
  11938. +
  11939. +static inline int cpu_is_ipq5010(void)
  11940. +{
  11941. +#ifdef CONFIG_ARCH_QCOM
  11942. + return read_ipq_cpu_type() == CPU_IPQ5010;
  11943. +#else
  11944. + return 0;
  11945. +#endif
  11946. +}
  11947. +
  11948. +static inline int cpu_is_ipq5018(void)
  11949. +{
  11950. +#ifdef CONFIG_ARCH_QCOM
  11951. + return read_ipq_cpu_type() == CPU_IPQ5018;
  11952. +#else
  11953. + return 0;
  11954. +#endif
  11955. +}
  11956. +
  11957. +static inline int cpu_is_ipq5028(void)
  11958. +{
  11959. +#ifdef CONFIG_ARCH_QCOM
  11960. + return read_ipq_cpu_type() == CPU_IPQ5028;
  11961. +#else
  11962. + return 0;
  11963. +#endif
  11964. +}
  11965. +
  11966. +static inline int cpu_is_ipq5000(void)
  11967. +{
  11968. +#ifdef CONFIG_ARCH_QCOM
  11969. + return read_ipq_cpu_type() == CPU_IPQ5000;
  11970. +#else
  11971. + return 0;
  11972. +#endif
  11973. +}
  11974. +
  11975. +static inline int cpu_is_ipq0509(void)
  11976. +{
  11977. +#ifdef CONFIG_ARCH_QCOM
  11978. + return read_ipq_cpu_type() == CPU_IPQ0509;
  11979. +#else
  11980. + return 0;
  11981. +#endif
  11982. +}
  11983. +
  11984. +static inline int cpu_is_ipq0518(void)
  11985. +{
  11986. +#ifdef CONFIG_ARCH_QCOM
  11987. + return read_ipq_cpu_type() == CPU_IPQ0518;
  11988. +#else
  11989. + return 0;
  11990. +#endif
  11991. +}
  11992. +
  11993. +static inline int cpu_is_ipq9514(void)
  11994. +{
  11995. +#ifdef CONFIG_ARCH_QCOM
  11996. + return read_ipq_cpu_type() == CPU_IPQ9514;
  11997. +#else
  11998. + return 0;
  11999. +#endif
  12000. +}
  12001. +
  12002. +static inline int cpu_is_ipq9554(void)
  12003. +{
  12004. +#ifdef CONFIG_ARCH_QCOM
  12005. + return read_ipq_cpu_type() == CPU_IPQ9554;
  12006. +#else
  12007. + return 0;
  12008. +#endif
  12009. +}
  12010. +
  12011. +static inline int cpu_is_ipq9570(void)
  12012. +{
  12013. +#ifdef CONFIG_ARCH_QCOM
  12014. + return read_ipq_cpu_type() == CPU_IPQ9570;
  12015. +#else
  12016. + return 0;
  12017. +#endif
  12018. +}
  12019. +
  12020. +static inline int cpu_is_ipq9574(void)
  12021. +{
  12022. +#ifdef CONFIG_ARCH_QCOM
  12023. + return read_ipq_cpu_type() == CPU_IPQ9574;
  12024. +#else
  12025. + return 0;
  12026. +#endif
  12027. +}
  12028. +
  12029. +static inline int cpu_is_ipq9550(void)
  12030. +{
  12031. +#ifdef CONFIG_ARCH_QCOM
  12032. + return read_ipq_cpu_type() == CPU_IPQ9550;
  12033. +#else
  12034. + return 0;
  12035. +#endif
  12036. +}
  12037. +
  12038. +static inline int cpu_is_ipq9510(void)
  12039. +{
  12040. +#ifdef CONFIG_ARCH_QCOM
  12041. + return read_ipq_cpu_type() == CPU_IPQ9510;
  12042. +#else
  12043. + return 0;
  12044. +#endif
  12045. +}
  12046. +
  12047. +static inline int cpu_is_ipq807x(void)
  12048. +{
  12049. +#ifdef CONFIG_ARCH_QCOM
  12050. + return cpu_is_ipq8072() || cpu_is_ipq8074() ||
  12051. + cpu_is_ipq8076() || cpu_is_ipq8078() ||
  12052. + cpu_is_ipq8070() || cpu_is_ipq8071() ||
  12053. + cpu_is_ipq8072a() || cpu_is_ipq8074a() ||
  12054. + cpu_is_ipq8076a() || cpu_is_ipq8078a() ||
  12055. + cpu_is_ipq8070a() || cpu_is_ipq8071a() ||
  12056. + cpu_is_ipq8172() || cpu_is_ipq8173() ||
  12057. + cpu_is_ipq8174();
  12058. +#else
  12059. + return 0;
  12060. +#endif
  12061. +}
  12062. +
  12063. +static inline int cpu_is_ipq60xx(void)
  12064. +{
  12065. +#ifdef CONFIG_ARCH_QCOM
  12066. + return cpu_is_ipq6018() || cpu_is_ipq6028() ||
  12067. + cpu_is_ipq6000() || cpu_is_ipq6010() ||
  12068. + cpu_is_ipq6005();
  12069. +#else
  12070. + return 0;
  12071. +#endif
  12072. +}
  12073. +
  12074. +static inline int cpu_is_ipq50xx(void)
  12075. +{
  12076. +#ifdef CONFIG_ARCH_QCOM
  12077. + return cpu_is_ipq5010() || cpu_is_ipq5018() ||
  12078. + cpu_is_ipq5028() || cpu_is_ipq5000() ||
  12079. + cpu_is_ipq0509() || cpu_is_ipq0518();
  12080. +#else
  12081. + return 0;
  12082. +#endif
  12083. +}
  12084. +
  12085. +static inline int cpu_is_ipq95xx(void)
  12086. +{
  12087. +#ifdef CONFIG_ARCH_QCOM
  12088. + return cpu_is_ipq9514() || cpu_is_ipq9554() ||
  12089. + cpu_is_ipq9570() || cpu_is_ipq9574() ||
  12090. + cpu_is_ipq9550() || cpu_is_ipq9510();
  12091. +#else
  12092. + return 0;
  12093. +#endif
  12094. +}
  12095. +
  12096. +static inline int cpu_is_nss_crypto_enabled(void)
  12097. +{
  12098. +#ifdef CONFIG_ARCH_QCOM
  12099. + return cpu_is_ipq807x() || cpu_is_ipq60xx() ||
  12100. + cpu_is_ipq50xx() || cpu_is_ipq9570() ||
  12101. + cpu_is_ipq9550() || cpu_is_ipq9574() ||
  12102. + cpu_is_ipq9554();
  12103. +#else
  12104. + return 0;
  12105. +#endif
  12106. +}
  12107. +
  12108. +static inline int cpu_is_internal_wifi_enabled(void)
  12109. +{
  12110. +#ifdef CONFIG_ARCH_QCOM
  12111. + return cpu_is_ipq807x() || cpu_is_ipq60xx() ||
  12112. + cpu_is_ipq50xx() || cpu_is_ipq9514() ||
  12113. + cpu_is_ipq9554() || cpu_is_ipq9574();
  12114. +#else
  12115. + return 0;
  12116. +#endif
  12117. +}
  12118. +
  12119. +static inline int cpu_is_uniphy1_enabled(void)
  12120. +{
  12121. +#ifdef CONFIG_ARCH_QCOM
  12122. + return cpu_is_ipq807x() || cpu_is_ipq60xx() ||
  12123. + cpu_is_ipq9554() || cpu_is_ipq9570() ||
  12124. + cpu_is_ipq9574() || cpu_is_ipq9550();
  12125. +#else
  12126. + return 0;
  12127. +#endif
  12128. +}
  12129. +
  12130. +static inline int cpu_is_uniphy2_enabled(void)
  12131. +{
  12132. +#ifdef CONFIG_ARCH_QCOM
  12133. + return cpu_is_ipq807x() || cpu_is_ipq9570() ||
  12134. + cpu_is_ipq9574();
  12135. +#else
  12136. + return 0;
  12137. +#endif
  12138. +}
  12139. +
  12140. +#endif /* _ARCH_ARM_MACH_MSM_SOCINFO_H_ */