1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682 |
- #define pr_fmt(fmt) "%s: " fmt, __func__
- #include <linux/bitops.h>
- #include <linux/debugfs.h>
- #include <linux/delay.h>
- #include <linux/err.h>
- #include <linux/init.h>
- #include <linux/interrupt.h>
- #include <linux/io.h>
- #include <linux/kernel.h>
- #include <linux/ktime.h>
- #include <linux/list.h>
- #include <linux/module.h>
- #include <linux/of.h>
- #include <linux/of_device.h>
- #include <linux/platform_device.h>
- #include <linux/pm_opp.h>
- #include <linux/slab.h>
- #include <linux/sort.h>
- #include <linux/string.h>
- #include <linux/uaccess.h>
- #include <linux/regulator/driver.h>
- #include <linux/regulator/machine.h>
- #include <linux/regulator/of_regulator.h>
- #include <linux/regulator/msm-ldo-regulator.h>
- #include <soc/qcom/spm.h>
- #include "cpr3-regulator.h"
- #define CPR3_REGULATOR_CORNER_INVALID (-1)
- #define CPR3_RO_MASK GENMASK(CPR3_RO_COUNT - 1, 0)
- #define CPR3_REG_CPR_VERSION 0x0
- #define CPRH_CPR_VERSION_4P5 0x40050000
- #define CPR3_REG_CPR_CTL 0x4
- #define CPR3_CPR_CTL_LOOP_EN_MASK BIT(0)
- #define CPR3_CPR_CTL_LOOP_ENABLE BIT(0)
- #define CPR3_CPR_CTL_LOOP_DISABLE 0
- #define CPR3_CPR_CTL_IDLE_CLOCKS_MASK GENMASK(5, 1)
- #define CPR3_CPR_CTL_IDLE_CLOCKS_SHIFT 1
- #define CPR3_CPR_CTL_COUNT_MODE_MASK GENMASK(7, 6)
- #define CPR3_CPR_CTL_COUNT_MODE_SHIFT 6
- #define CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_MIN 0
- #define CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_MAX 1
- #define CPR3_CPR_CTL_COUNT_MODE_STAGGERED 2
- #define CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_AGE 3
- #define CPR3_CPR_CTL_COUNT_REPEAT_MASK GENMASK(31, 9)
- #define CPR3_CPR_CTL_COUNT_REPEAT_SHIFT 9
- #define CPR3_REG_CPR_STATUS 0x8
- #define CPR3_CPR_STATUS_BUSY_MASK BIT(0)
- #define CPR3_CPR_STATUS_AGING_MEASUREMENT_MASK BIT(1)
- #define CPR3_REG_CPR_TIMER_AUTO_CONT 0xC
- #define CPR3_REG_CPR_STEP_QUOT 0x14
- #define CPR3_CPR_STEP_QUOT_MIN_MASK GENMASK(5, 0)
- #define CPR3_CPR_STEP_QUOT_MIN_SHIFT 0
- #define CPR3_CPR_STEP_QUOT_MAX_MASK GENMASK(11, 6)
- #define CPR3_CPR_STEP_QUOT_MAX_SHIFT 6
- #define CPR3_REG_GCNT(ro) (0xA0 + 0x4 * (ro))
- #define CPR3_REG_SENSOR_BYPASS_WRITE(sensor) (0xE0 + 0x4 * ((sensor) / 32))
- #define CPR3_REG_SENSOR_BYPASS_WRITE_BANK(bank) (0xE0 + 0x4 * (bank))
- #define CPR3_REG_SENSOR_MASK_WRITE(sensor) (0x120 + 0x4 * ((sensor) / 32))
- #define CPR3_REG_SENSOR_MASK_WRITE_BANK(bank) (0x120 + 0x4 * (bank))
- #define CPR3_REG_SENSOR_MASK_READ(sensor) (0x140 + 0x4 * ((sensor) / 32))
- #define CPR3_REG_SENSOR_OWNER(sensor) (0x200 + 0x4 * (sensor))
- #define CPR3_REG_CONT_CMD 0x800
- #define CPR3_CONT_CMD_ACK 0x1
- #define CPR3_CONT_CMD_NACK 0x0
- #define CPR3_REG_THRESH(thread) (0x808 + 0x440 * (thread))
- #define CPR3_THRESH_CONS_DOWN_MASK GENMASK(3, 0)
- #define CPR3_THRESH_CONS_DOWN_SHIFT 0
- #define CPR3_THRESH_CONS_UP_MASK GENMASK(7, 4)
- #define CPR3_THRESH_CONS_UP_SHIFT 4
- #define CPR3_THRESH_DOWN_THRESH_MASK GENMASK(12, 8)
- #define CPR3_THRESH_DOWN_THRESH_SHIFT 8
- #define CPR3_THRESH_UP_THRESH_MASK GENMASK(17, 13)
- #define CPR3_THRESH_UP_THRESH_SHIFT 13
- #define CPR3_REG_RO_MASK(thread) (0x80C + 0x440 * (thread))
- #define CPR3_REG_RESULT0(thread) (0x810 + 0x440 * (thread))
- #define CPR3_RESULT0_BUSY_MASK BIT(0)
- #define CPR3_RESULT0_STEP_DN_MASK BIT(1)
- #define CPR3_RESULT0_STEP_UP_MASK BIT(2)
- #define CPR3_RESULT0_ERROR_STEPS_MASK GENMASK(7, 3)
- #define CPR3_RESULT0_ERROR_STEPS_SHIFT 3
- #define CPR3_RESULT0_ERROR_MASK GENMASK(19, 8)
- #define CPR3_RESULT0_ERROR_SHIFT 8
- #define CPR3_RESULT0_NEGATIVE_MASK BIT(20)
- #define CPR3_REG_RESULT1(thread) (0x814 + 0x440 * (thread))
- #define CPR3_RESULT1_QUOT_MIN_MASK GENMASK(11, 0)
- #define CPR3_RESULT1_QUOT_MIN_SHIFT 0
- #define CPR3_RESULT1_QUOT_MAX_MASK GENMASK(23, 12)
- #define CPR3_RESULT1_QUOT_MAX_SHIFT 12
- #define CPR3_RESULT1_RO_MIN_MASK GENMASK(27, 24)
- #define CPR3_RESULT1_RO_MIN_SHIFT 24
- #define CPR3_RESULT1_RO_MAX_MASK GENMASK(31, 28)
- #define CPR3_RESULT1_RO_MAX_SHIFT 28
- #define CPR3_REG_RESULT2(thread) (0x818 + 0x440 * (thread))
- #define CPR3_RESULT2_STEP_QUOT_MIN_MASK GENMASK(5, 0)
- #define CPR3_RESULT2_STEP_QUOT_MIN_SHIFT 0
- #define CPR3_RESULT2_STEP_QUOT_MAX_MASK GENMASK(11, 6)
- #define CPR3_RESULT2_STEP_QUOT_MAX_SHIFT 6
- #define CPR3_RESULT2_SENSOR_MIN_MASK GENMASK(23, 16)
- #define CPR3_RESULT2_SENSOR_MIN_SHIFT 16
- #define CPR3_RESULT2_SENSOR_MAX_MASK GENMASK(31, 24)
- #define CPR3_RESULT2_SENSOR_MAX_SHIFT 24
- #define CPR3_REG_IRQ_EN 0x81C
- #define CPR3_REG_IRQ_CLEAR 0x820
- #define CPR3_REG_IRQ_STATUS 0x824
- #define CPR3_IRQ_UP BIT(3)
- #define CPR3_IRQ_MID BIT(2)
- #define CPR3_IRQ_DOWN BIT(1)
- #define CPR3_REG_TARGET_QUOT(thread, ro) \
- (0x840 + 0x440 * (thread) + 0x4 * (ro))
- #define CPR3_REG_PD_THROTTLE 0xE8
- #define CPR3_PD_THROTTLE_DISABLE 0x0
- #define CPR3_REG_HW_CLOSED_LOOP 0x3000
- #define CPR3_HW_CLOSED_LOOP_ENABLE 0x0
- #define CPR3_HW_CLOSED_LOOP_DISABLE 0x1
- #define CPR3_REG_CPR_TIMER_MID_CONT 0x3004
- #define CPR3_REG_CPR_TIMER_UP_DN_CONT 0x3008
- #define CPR3_REG_LAST_MEASUREMENT 0x7F8
- #define CPR3_LAST_MEASUREMENT_THREAD_DN_SHIFT 0
- #define CPR3_LAST_MEASUREMENT_THREAD_UP_SHIFT 4
- #define CPR3_LAST_MEASUREMENT_THREAD_DN(thread) \
- (BIT(thread) << CPR3_LAST_MEASUREMENT_THREAD_DN_SHIFT)
- #define CPR3_LAST_MEASUREMENT_THREAD_UP(thread) \
- (BIT(thread) << CPR3_LAST_MEASUREMENT_THREAD_UP_SHIFT)
- #define CPR3_LAST_MEASUREMENT_AGGR_DN BIT(8)
- #define CPR3_LAST_MEASUREMENT_AGGR_MID BIT(9)
- #define CPR3_LAST_MEASUREMENT_AGGR_UP BIT(10)
- #define CPR3_LAST_MEASUREMENT_VALID BIT(11)
- #define CPR3_LAST_MEASUREMENT_SAW_ERROR BIT(12)
- #define CPR3_LAST_MEASUREMENT_PD_BYPASS_MASK GENMASK(23, 16)
- #define CPR3_LAST_MEASUREMENT_PD_BYPASS_SHIFT 16
- #define CPR4_REG_CPR_TIMER_CLAMP 0x10
- #define CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN BIT(27)
- #define CPR4_REG_MISC 0x700
- #define CPR4_MISC_RESET_STEP_QUOT_LOOP_EN BIT(2)
- #define CPR4_MISC_THREAD_HAS_ALWAYS_VOTE_EN BIT(3)
- #define CPR4_MISC_MARGIN_TABLE_ROW_SELECT_MASK GENMASK(23, 20)
- #define CPR4_MISC_MARGIN_TABLE_ROW_SELECT_SHIFT 20
- #define CPR4_MISC_TEMP_SENSOR_ID_START_MASK GENMASK(27, 24)
- #define CPR4_MISC_TEMP_SENSOR_ID_START_SHIFT 24
- #define CPR4_MISC_TEMP_SENSOR_ID_END_MASK GENMASK(31, 28)
- #define CPR4_MISC_TEMP_SENSOR_ID_END_SHIFT 28
- #define CPR4_REG_SAW_ERROR_STEP_LIMIT 0x7A4
- #define CPR4_SAW_ERROR_STEP_LIMIT_UP_MASK GENMASK(4, 0)
- #define CPR4_SAW_ERROR_STEP_LIMIT_UP_SHIFT 0
- #define CPR4_SAW_ERROR_STEP_LIMIT_DN_MASK GENMASK(9, 5)
- #define CPR4_SAW_ERROR_STEP_LIMIT_DN_SHIFT 5
- #define CPR4_REG_MARGIN_TEMP_CORE_TIMERS 0x7A8
- #define CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_MASK GENMASK(28, 18)
- #define CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_SHIFT 18
- #define CPR4_REG_MARGIN_TEMP_CORE(core) (0x7AC + 0x4 * (core))
- #define CPR4_MARGIN_TEMP_CORE_ADJ_MASK GENMASK(7, 0)
- #define CPR4_MARGIN_TEMP_CORE_ADJ_SHIFT 8
- #define CPR4_REG_MARGIN_TEMP_POINT0N1 0x7F0
- #define CPR4_MARGIN_TEMP_POINT0_MASK GENMASK(11, 0)
- #define CPR4_MARGIN_TEMP_POINT0_SHIFT 0
- #define CPR4_MARGIN_TEMP_POINT1_MASK GENMASK(23, 12)
- #define CPR4_MARGIN_TEMP_POINT1_SHIFT 12
- #define CPR4_REG_MARGIN_TEMP_POINT2 0x7F4
- #define CPR4_MARGIN_TEMP_POINT2_MASK GENMASK(11, 0)
- #define CPR4_MARGIN_TEMP_POINT2_SHIFT 0
- #define CPR4_REG_MARGIN_ADJ_CTL 0x7F8
- #define CPR4_MARGIN_ADJ_CTL_BOOST_EN BIT(0)
- #define CPR4_MARGIN_ADJ_CTL_CORE_ADJ_EN BIT(1)
- #define CPR4_MARGIN_ADJ_CTL_TEMP_ADJ_EN BIT(2)
- #define CPR4_MARGIN_ADJ_CTL_TIMER_SETTLE_VOLTAGE_EN BIT(3)
- #define CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK BIT(4)
- #define CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE BIT(4)
- #define CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE 0
- #define CPR4_MARGIN_ADJ_CTL_PER_RO_KV_MARGIN_EN BIT(7)
- #define CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_EN BIT(8)
- #define CPR4_MARGIN_ADJ_CTL_PMIC_STEP_SIZE_MASK GENMASK(16, 12)
- #define CPR4_MARGIN_ADJ_CTL_PMIC_STEP_SIZE_SHIFT 12
- #define CPR4_MARGIN_ADJ_CTL_INITIAL_TEMP_BAND_MASK GENMASK(21, 19)
- #define CPR4_MARGIN_ADJ_CTL_INITIAL_TEMP_BAND_SHIFT 19
- #define CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_MASK GENMASK(25, 22)
- #define CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_SHIFT 22
- #define CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_STEP_QUOT_MASK GENMASK(31, 26)
- #define CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_STEP_QUOT_SHIFT 26
- #define CPR4_REG_CPR_MASK_THREAD(thread) (0x80C + 0x440 * (thread))
- #define CPR4_CPR_MASK_THREAD_DISABLE_THREAD BIT(31)
- #define CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK GENMASK(15, 0)
- #define CPRH_REG_CORNER(thread, corner) \
- ((thread)->ctrl->cpr_hw_version >= CPRH_CPR_VERSION_4P5 \
- ? 0x3500 + 0xA0 * (thread)->thread_id + 0x4 * (corner) \
- : 0x3A00 + 0x4 * (corner))
- #define CPRH_CORNER_INIT_VOLTAGE_MASK GENMASK(7, 0)
- #define CPRH_CORNER_INIT_VOLTAGE_SHIFT 0
- #define CPRH_CORNER_FLOOR_VOLTAGE_MASK GENMASK(15, 8)
- #define CPRH_CORNER_FLOOR_VOLTAGE_SHIFT 8
- #define CPRH_CORNER_QUOT_DELTA_MASK GENMASK(24, 16)
- #define CPRH_CORNER_QUOT_DELTA_SHIFT 16
- #define CPRH_CORNER_RO_SEL_MASK GENMASK(28, 25)
- #define CPRH_CORNER_RO_SEL_SHIFT 25
- #define CPRH_CORNER_CPR_CL_DISABLE BIT(29)
- #define CPRH_CORNER_CORE_TEMP_MARGIN_DISABLE BIT(30)
- #define CPRH_CORNER_LAST_KNOWN_VOLTAGE_ENABLE BIT(31)
- #define CPRH_CORNER_INIT_VOLTAGE_MAX_VALUE 255
- #define CPRH_CORNER_FLOOR_VOLTAGE_MAX_VALUE 255
- #define CPRH_CORNER_QUOT_DELTA_MAX_VALUE 511
- #define CPRH_REG_CTL(ctrl) \
- ((ctrl)->cpr_hw_version >= CPRH_CPR_VERSION_4P5 ? 0x3A80 : 0x3AA0)
- #define CPRH_CTL_OSM_ENABLED BIT(0)
- #define CPRH_CTL_BASE_VOLTAGE_MASK GENMASK(10, 1)
- #define CPRH_CTL_BASE_VOLTAGE_SHIFT 1
- #define CPRH_CTL_INIT_MODE_MASK GENMASK(16, 11)
- #define CPRH_CTL_INIT_MODE_SHIFT 11
- #define CPRH_CTL_MODE_SWITCH_DELAY_MASK GENMASK(24, 17)
- #define CPRH_CTL_MODE_SWITCH_DELAY_SHIFT 17
- #define CPRH_CTL_VOLTAGE_MULTIPLIER_MASK GENMASK(28, 25)
- #define CPRH_CTL_VOLTAGE_MULTIPLIER_SHIFT 25
- #define CPRH_CTL_LAST_KNOWN_VOLTAGE_MARGIN_MASK GENMASK(31, 29)
- #define CPRH_CTL_LAST_KNOWN_VOLTAGE_MARGIN_SHIFT 29
- #define CPRH_REG_STATUS(thread) \
- ((thread)->ctrl->cpr_hw_version >= CPRH_CPR_VERSION_4P5 \
- ? 0x3A84 + 0x4 * (thread)->thread_id : 0x3AA4)
- #define CPRH_STATUS_CORNER GENMASK(5, 0)
- #define CPRH_STATUS_CORNER_LAST_VOLT_MASK GENMASK(17, 6)
- #define CPRH_STATUS_CORNER_LAST_VOLT_SHIFT 6
- #define CPRH_REG_CORNER_BAND 0x3AA8
- #define CPRH_CORNER_BAND_MASK GENMASK(5, 0)
- #define CPRH_CORNER_BAND_SHIFT 6
- #define CPRH_CORNER_BAND_MAX_COUNT 4
- #define CPRH_MARGIN_TEMP_CORE_VBAND(core, vband) \
- ((vband) == 0 ? CPR4_REG_MARGIN_TEMP_CORE(core) \
- : 0x3AB0 + 0x40 * ((vband) - 1) + 0x4 * (core))
- #define CPRH_REG_MISC_REG2 0x3AAC
- #define CPRH_MISC_REG2_ACD_ADJ_STEP_UP_LIMIT_MASK GENMASK(31, 29)
- #define CPRH_MISC_REG2_ACD_ADJ_STEP_UP_LIMIT_SHIFT 29
- #define CPRH_MISC_REG2_ACD_ADJ_STEP_DOWN_LIMIT_MASK GENMASK(28, 24)
- #define CPRH_MISC_REG2_ACD_ADJ_STEP_DOWN_LIMIT_SHIFT 24
- #define CPRH_MISC_REG2_ACD_ADJ_STEP_SIZE_UP_MASK GENMASK(23, 22)
- #define CPRH_MISC_REG2_ACD_ADJ_STEP_SIZE_UP_SHIFT 22
- #define CPRH_MISC_REG2_ACD_ADJ_STEP_SIZE_DOWN_MASK GENMASK(21, 20)
- #define CPRH_MISC_REG2_ACD_ADJ_STEP_SIZE_DOWN_SHIFT 20
- #define CPRH_MISC_REG2_ACD_NOTWAIT_4_CL_SETTLE_MASK BIT(16)
- #define CPRH_MISC_REG2_ACD_NOTWAIT_4_CL_SETTLE_EN BIT(16)
- #define CPRH_MISC_REG2_ACD_AVG_FAST_UPDATE_EN_MASK BIT(13)
- #define CPRH_MISC_REG2_ACD_AVG_FAST_UPDATE_EN BIT(13)
- #define CPRH_MISC_REG2_ACD_AVG_EN_MASK BIT(12)
- #define CPRH_MISC_REG2_ACD_AVG_ENABLE BIT(12)
- #define SAW_REG_AVS_CTL 0x904
- #define SAW_REG_AVS_LIMIT 0x908
- #define CPR3_AGING_MEASUREMENT_TIMEOUT_NS 5000000
- #define CPR3_AGING_MEASUREMENT_ITERATIONS 16
- #define CPR3_AGING_MEASUREMENT_FILTER 3
- #define CPR3_AGING_RETRY_COUNT 5
- #define CPR3_REGISTER_WRITE_DELAY_US 200
- #define CPRH_MODE_SWITCH_DELAY_FACTOR 4
- #define CPRH_DELTA_QUOT_STEP_FACTOR 4
- static DEFINE_MUTEX(cpr3_controller_list_mutex);
- static LIST_HEAD(cpr3_controller_list);
- static struct dentry *cpr3_debugfs_base;
- static inline u32 cpr3_read(struct cpr3_controller *ctrl, u32 offset)
- {
- if (!ctrl->cpr_enabled) {
- cpr3_err(ctrl, "CPR register reads are not possible when CPR clocks are disabled\n");
- return 0;
- }
- return readl_relaxed(ctrl->cpr_ctrl_base + offset);
- }
- static inline void cpr3_write(struct cpr3_controller *ctrl, u32 offset,
- u32 value)
- {
- if (!ctrl->cpr_enabled) {
- cpr3_err(ctrl, "CPR register writes are not possible when CPR clocks are disabled\n");
- return;
- }
- writel_relaxed(value, ctrl->cpr_ctrl_base + offset);
- }
- static inline void cpr3_masked_write(struct cpr3_controller *ctrl, u32 offset,
- u32 mask, u32 value)
- {
- u32 reg_val, orig_val;
- if (!ctrl->cpr_enabled) {
- cpr3_err(ctrl, "CPR register writes are not possible when CPR clocks are disabled\n");
- return;
- }
- reg_val = orig_val = readl_relaxed(ctrl->cpr_ctrl_base + offset);
- reg_val &= ~mask;
- reg_val |= value & mask;
- if (reg_val != orig_val)
- writel_relaxed(reg_val, ctrl->cpr_ctrl_base + offset);
- }
- static inline void cpr3_ctrl_loop_enable(struct cpr3_controller *ctrl)
- {
- if (ctrl->cpr_enabled && !(ctrl->aggr_corner.sdelta
- && ctrl->aggr_corner.sdelta->allow_boost))
- cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL,
- CPR3_CPR_CTL_LOOP_EN_MASK, CPR3_CPR_CTL_LOOP_ENABLE);
- }
- static inline void cpr3_ctrl_loop_disable(struct cpr3_controller *ctrl)
- {
- if (ctrl->cpr_enabled)
- cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL,
- CPR3_CPR_CTL_LOOP_EN_MASK, CPR3_CPR_CTL_LOOP_DISABLE);
- }
- static int cpr3_clock_enable(struct cpr3_controller *ctrl)
- {
- int rc;
- rc = clk_prepare_enable(ctrl->bus_clk);
- if (rc) {
- cpr3_err(ctrl, "failed to enable bus clock, rc=%d\n", rc);
- return rc;
- }
- rc = clk_prepare_enable(ctrl->iface_clk);
- if (rc) {
- cpr3_err(ctrl, "failed to enable interface clock, rc=%d\n", rc);
- clk_disable_unprepare(ctrl->bus_clk);
- return rc;
- }
- rc = clk_prepare_enable(ctrl->core_clk);
- if (rc) {
- cpr3_err(ctrl, "failed to enable core clock, rc=%d\n", rc);
- clk_disable_unprepare(ctrl->iface_clk);
- clk_disable_unprepare(ctrl->bus_clk);
- return rc;
- }
- return 0;
- }
- static void cpr3_clock_disable(struct cpr3_controller *ctrl)
- {
- clk_disable_unprepare(ctrl->core_clk);
- clk_disable_unprepare(ctrl->iface_clk);
- clk_disable_unprepare(ctrl->bus_clk);
- }
- static inline int cpr3_ctrl_clear_cpr4_config(struct cpr3_controller *ctrl)
- {
- struct cpr4_sdelta *aggr_sdelta = ctrl->aggr_corner.sdelta;
- bool cpr_enabled = ctrl->cpr_enabled;
- int i, rc = 0;
- if (!aggr_sdelta || !(aggr_sdelta->allow_core_count_adj
- || aggr_sdelta->allow_temp_adj || aggr_sdelta->allow_boost))
-
- return 0;
-
- if (!cpr_enabled) {
- rc = cpr3_clock_enable(ctrl);
- if (rc) {
- cpr3_err(ctrl, "clock enable failed, rc=%d\n", rc);
- return rc;
- }
- ctrl->cpr_enabled = true;
- }
-
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
- CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_MASK
- | CPR4_MARGIN_ADJ_CTL_CORE_ADJ_EN
- | CPR4_MARGIN_ADJ_CTL_TEMP_ADJ_EN
- | CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_EN
- | CPR4_MARGIN_ADJ_CTL_BOOST_EN
- | CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK, 0);
- cpr3_masked_write(ctrl, CPR4_REG_MISC,
- CPR4_MISC_MARGIN_TABLE_ROW_SELECT_MASK,
- 0 << CPR4_MISC_MARGIN_TABLE_ROW_SELECT_SHIFT);
- for (i = 0; i <= aggr_sdelta->max_core_count; i++) {
-
- cpr3_write(ctrl, CPR4_REG_MARGIN_TEMP_CORE(i), 0);
- }
-
- if (!cpr_enabled) {
- cpr3_clock_disable(ctrl);
- ctrl->cpr_enabled = false;
- }
- return 0;
- }
- static int cpr3_closed_loop_enable(struct cpr3_controller *ctrl)
- {
- int rc;
- if (!ctrl->cpr_allowed_hw || !ctrl->cpr_allowed_sw) {
- cpr3_err(ctrl, "cannot enable closed-loop CPR operation because it is disallowed\n");
- return -EPERM;
- } else if (ctrl->cpr_enabled) {
-
- return 0;
- } else if (ctrl->cpr_suspended) {
-
- return 0;
- }
- rc = cpr3_clock_enable(ctrl);
- if (rc) {
- cpr3_err(ctrl, "unable to enable CPR clocks, rc=%d\n", rc);
- return rc;
- }
- ctrl->cpr_enabled = true;
- cpr3_debug(ctrl, "CPR closed-loop operation enabled\n");
- return 0;
- }
- static inline int cpr3_closed_loop_disable(struct cpr3_controller *ctrl)
- {
- if (!ctrl->cpr_enabled) {
-
- return 0;
- }
- cpr3_clock_disable(ctrl);
- ctrl->cpr_enabled = false;
- cpr3_debug(ctrl, "CPR closed-loop operation disabled\n");
- return 0;
- }
- static u32 cpr3_regulator_get_gcnt(struct cpr3_controller *ctrl)
- {
- u64 temp;
- unsigned int remainder;
- u32 gcnt;
- temp = (u64)ctrl->cpr_clock_rate * (u64)ctrl->sensor_time;
- remainder = do_div(temp, 1000000000);
- if (remainder)
- temp++;
-
- gcnt = temp - 1;
- return gcnt;
- }
- static int cpr3_regulator_init_thread(struct cpr3_thread *thread)
- {
- u32 reg;
- reg = (thread->consecutive_up << CPR3_THRESH_CONS_UP_SHIFT)
- & CPR3_THRESH_CONS_UP_MASK;
- reg |= (thread->consecutive_down << CPR3_THRESH_CONS_DOWN_SHIFT)
- & CPR3_THRESH_CONS_DOWN_MASK;
- reg |= (thread->up_threshold << CPR3_THRESH_UP_THRESH_SHIFT)
- & CPR3_THRESH_UP_THRESH_MASK;
- reg |= (thread->down_threshold << CPR3_THRESH_DOWN_THRESH_SHIFT)
- & CPR3_THRESH_DOWN_THRESH_MASK;
- cpr3_write(thread->ctrl, CPR3_REG_THRESH(thread->thread_id), reg);
-
- cpr3_write(thread->ctrl, CPR3_REG_RO_MASK(thread->thread_id),
- CPR3_RO_MASK);
- return 0;
- }
- static int cpr4_regulator_init_temp_points(struct cpr3_controller *ctrl)
- {
- if (!ctrl->allow_temp_adj)
- return 0;
- cpr3_masked_write(ctrl, CPR4_REG_MISC,
- CPR4_MISC_TEMP_SENSOR_ID_START_MASK,
- ctrl->temp_sensor_id_start
- << CPR4_MISC_TEMP_SENSOR_ID_START_SHIFT);
- cpr3_masked_write(ctrl, CPR4_REG_MISC,
- CPR4_MISC_TEMP_SENSOR_ID_END_MASK,
- ctrl->temp_sensor_id_end
- << CPR4_MISC_TEMP_SENSOR_ID_END_SHIFT);
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_TEMP_POINT2,
- CPR4_MARGIN_TEMP_POINT2_MASK,
- (ctrl->temp_band_count == 4 ? ctrl->temp_points[2] : 0x7FF)
- << CPR4_MARGIN_TEMP_POINT2_SHIFT);
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_TEMP_POINT0N1,
- CPR4_MARGIN_TEMP_POINT1_MASK,
- (ctrl->temp_band_count >= 3 ? ctrl->temp_points[1] : 0x7FF)
- << CPR4_MARGIN_TEMP_POINT1_SHIFT);
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_TEMP_POINT0N1,
- CPR4_MARGIN_TEMP_POINT0_MASK,
- (ctrl->temp_band_count >= 2 ? ctrl->temp_points[0] : 0x7FF)
- << CPR4_MARGIN_TEMP_POINT0_SHIFT);
- return 0;
- }
- static int cpr3_regulator_init_cpr4(struct cpr3_controller *ctrl)
- {
- struct cpr3_thread *thread;
- struct cpr3_regulator *vreg;
- struct cpr4_sdelta *sdelta;
- int i, j, ctrl_max_core_count, thread_max_core_count, rc = 0;
- bool ctrl_valid_sdelta, thread_valid_sdelta;
- u32 pmic_step_size = 1;
- int thread_id = 0;
- u64 temp;
- if (ctrl->reset_step_quot_loop_en)
- cpr3_masked_write(ctrl, CPR4_REG_MISC,
- CPR4_MISC_RESET_STEP_QUOT_LOOP_EN,
- CPR4_MISC_RESET_STEP_QUOT_LOOP_EN);
- if (ctrl->thread_has_always_vote_en)
- cpr3_masked_write(ctrl, CPR4_REG_MISC,
- CPR4_MISC_THREAD_HAS_ALWAYS_VOTE_EN,
- CPR4_MISC_THREAD_HAS_ALWAYS_VOTE_EN);
- if (ctrl->supports_hw_closed_loop) {
- if (ctrl->saw_use_unit_mV)
- pmic_step_size = ctrl->step_volt / 1000;
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
- CPR4_MARGIN_ADJ_CTL_PMIC_STEP_SIZE_MASK,
- (pmic_step_size
- << CPR4_MARGIN_ADJ_CTL_PMIC_STEP_SIZE_SHIFT));
- cpr3_masked_write(ctrl, CPR4_REG_SAW_ERROR_STEP_LIMIT,
- CPR4_SAW_ERROR_STEP_LIMIT_DN_MASK,
- (ctrl->down_error_step_limit
- << CPR4_SAW_ERROR_STEP_LIMIT_DN_SHIFT));
- cpr3_masked_write(ctrl, CPR4_REG_SAW_ERROR_STEP_LIMIT,
- CPR4_SAW_ERROR_STEP_LIMIT_UP_MASK,
- (ctrl->up_error_step_limit
- << CPR4_SAW_ERROR_STEP_LIMIT_UP_SHIFT));
-
- cpr3_masked_write(ctrl, CPR4_REG_CPR_TIMER_CLAMP,
- CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN,
- CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN);
- switch (ctrl->thread_count) {
- case 0:
-
- cpr3_masked_write(ctrl, CPR4_REG_CPR_MASK_THREAD(0),
- CPR4_CPR_MASK_THREAD_DISABLE_THREAD
- | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK,
- CPR4_CPR_MASK_THREAD_DISABLE_THREAD
- | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK);
- cpr3_masked_write(ctrl, CPR4_REG_CPR_MASK_THREAD(1),
- CPR4_CPR_MASK_THREAD_DISABLE_THREAD
- | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK,
- CPR4_CPR_MASK_THREAD_DISABLE_THREAD
- | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK);
- break;
- case 1:
-
- thread_id = ctrl->thread[0].thread_id ? 0 : 1;
- cpr3_masked_write(ctrl,
- CPR4_REG_CPR_MASK_THREAD(thread_id),
- CPR4_CPR_MASK_THREAD_DISABLE_THREAD
- | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK,
- CPR4_CPR_MASK_THREAD_DISABLE_THREAD
- | CPR4_CPR_MASK_THREAD_RO_MASK4THREAD_MASK);
- break;
- }
- }
- if (!ctrl->allow_core_count_adj && !ctrl->allow_temp_adj
- && !ctrl->allow_boost) {
-
- return rc;
- }
- if (ctrl->supports_hw_closed_loop)
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
- CPR4_MARGIN_ADJ_CTL_TIMER_SETTLE_VOLTAGE_EN,
- CPR4_MARGIN_ADJ_CTL_TIMER_SETTLE_VOLTAGE_EN);
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
- CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_STEP_QUOT_MASK,
- ctrl->step_quot_fixed
- << CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_STEP_QUOT_SHIFT);
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
- CPR4_MARGIN_ADJ_CTL_PER_RO_KV_MARGIN_EN,
- (ctrl->use_dynamic_step_quot
- ? CPR4_MARGIN_ADJ_CTL_PER_RO_KV_MARGIN_EN : 0));
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
- CPR4_MARGIN_ADJ_CTL_INITIAL_TEMP_BAND_MASK,
- ctrl->initial_temp_band
- << CPR4_MARGIN_ADJ_CTL_INITIAL_TEMP_BAND_SHIFT);
- rc = cpr4_regulator_init_temp_points(ctrl);
- if (rc) {
- cpr3_err(ctrl, "initialize temp points failed, rc=%d\n", rc);
- return rc;
- }
- if (ctrl->voltage_settling_time) {
-
- temp = (u64)ctrl->cpr_clock_rate
- * (u64)ctrl->voltage_settling_time;
- do_div(temp, 1000000000);
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_TEMP_CORE_TIMERS,
- CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_MASK,
- temp
- << CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_SHIFT);
- }
-
- ctrl_max_core_count = 1;
- ctrl_valid_sdelta = false;
- for (i = 0; i < ctrl->thread_count; i++) {
- thread = &ctrl->thread[i];
-
- thread_max_core_count = 1;
- thread_valid_sdelta = false;
- for (j = 0; j < thread->vreg_count; j++) {
- vreg = &thread->vreg[j];
- thread_max_core_count = max(thread_max_core_count,
- vreg->max_core_count);
- thread_valid_sdelta |= (vreg->allow_core_count_adj
- | vreg->allow_temp_adj
- | vreg->allow_boost);
- }
- if (thread_valid_sdelta) {
- sdelta = devm_kzalloc(ctrl->dev, sizeof(*sdelta),
- GFP_KERNEL);
- if (!sdelta)
- return -ENOMEM;
- sdelta->table = devm_kcalloc(ctrl->dev,
- thread_max_core_count
- * ctrl->temp_band_count,
- sizeof(*sdelta->table),
- GFP_KERNEL);
- if (!sdelta->table)
- return -ENOMEM;
- sdelta->boost_table = devm_kcalloc(ctrl->dev,
- ctrl->temp_band_count,
- sizeof(*sdelta->boost_table),
- GFP_KERNEL);
- if (!sdelta->boost_table)
- return -ENOMEM;
- thread->aggr_corner.sdelta = sdelta;
- }
- ctrl_valid_sdelta |= thread_valid_sdelta;
- ctrl_max_core_count = max(ctrl_max_core_count,
- thread_max_core_count);
- }
- if (ctrl_valid_sdelta) {
- sdelta = devm_kzalloc(ctrl->dev, sizeof(*sdelta), GFP_KERNEL);
- if (!sdelta)
- return -ENOMEM;
- sdelta->table = devm_kcalloc(ctrl->dev, ctrl_max_core_count
- * ctrl->temp_band_count,
- sizeof(*sdelta->table), GFP_KERNEL);
- if (!sdelta->table)
- return -ENOMEM;
- sdelta->boost_table = devm_kcalloc(ctrl->dev,
- ctrl->temp_band_count,
- sizeof(*sdelta->boost_table),
- GFP_KERNEL);
- if (!sdelta->boost_table)
- return -ENOMEM;
- ctrl->aggr_corner.sdelta = sdelta;
- }
- return 0;
- }
- static void cpr3_write_temp_core_margin(struct cpr3_controller *ctrl,
- int addr, int *temp_core_adj)
- {
- int i, margin_steps;
- u32 reg = 0;
- for (i = 0; i < ctrl->temp_band_count; i++) {
- margin_steps = max(min(temp_core_adj[i], 127), -128);
- reg |= (margin_steps & CPR4_MARGIN_TEMP_CORE_ADJ_MASK) <<
- (i * CPR4_MARGIN_TEMP_CORE_ADJ_SHIFT);
- }
- cpr3_write(ctrl, addr, reg);
- cpr3_debug(ctrl, "sdelta offset=0x%08x, val=0x%08x\n", addr, reg);
- }
- static int cpr3_controller_program_sdelta(struct cpr3_controller *ctrl)
- {
- struct cpr3_corner *corner = &ctrl->aggr_corner;
- struct cpr4_sdelta *sdelta = corner->sdelta;
- int i, index, max_core_count, rc = 0;
- bool cpr_enabled = ctrl->cpr_enabled;
- if (!sdelta)
-
- return 0;
- if (ctrl->supports_hw_closed_loop && ctrl->cpr_enabled) {
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
- CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK,
- (ctrl->use_hw_closed_loop && !sdelta->allow_boost)
- ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE : 0);
- }
- if (!sdelta->allow_core_count_adj && !sdelta->allow_temp_adj
- && !sdelta->allow_boost) {
-
- return 0;
- }
-
- if (!cpr_enabled) {
- rc = cpr3_clock_enable(ctrl);
- if (rc) {
- cpr3_err(ctrl, "clock enable failed, rc=%d\n", rc);
- return rc;
- }
- ctrl->cpr_enabled = true;
- }
- max_core_count = sdelta->max_core_count;
- if (sdelta->allow_core_count_adj || sdelta->allow_temp_adj) {
- if (sdelta->allow_core_count_adj) {
-
- cpr3_write_temp_core_margin(ctrl,
- CPR4_REG_MARGIN_TEMP_CORE(0),
- &sdelta->table[0]);
- }
- for (i = 0; i < max_core_count; i++) {
- index = i * sdelta->temp_band_count;
-
- cpr3_write_temp_core_margin(ctrl,
- CPR4_REG_MARGIN_TEMP_CORE(
- sdelta->allow_core_count_adj
- ? i + 1 : max_core_count),
- &sdelta->table[index]);
- }
- }
- if (sdelta->allow_boost) {
-
- cpr3_write_temp_core_margin(ctrl,
- CPR4_REG_MARGIN_TEMP_CORE(sdelta->boost_num_cores),
- &sdelta->boost_table[0]);
- }
- if (!sdelta->allow_core_count_adj && !sdelta->allow_boost) {
- cpr3_masked_write(ctrl, CPR4_REG_MISC,
- CPR4_MISC_MARGIN_TABLE_ROW_SELECT_MASK,
- max_core_count
- << CPR4_MISC_MARGIN_TABLE_ROW_SELECT_SHIFT);
- }
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
- CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_MASK
- | CPR4_MARGIN_ADJ_CTL_CORE_ADJ_EN
- | CPR4_MARGIN_ADJ_CTL_TEMP_ADJ_EN
- | CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_EN
- | CPR4_MARGIN_ADJ_CTL_BOOST_EN,
- max_core_count << CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_SHIFT
- | ((sdelta->allow_core_count_adj || sdelta->allow_boost)
- ? CPR4_MARGIN_ADJ_CTL_CORE_ADJ_EN : 0)
- | ((sdelta->allow_temp_adj && ctrl->supports_hw_closed_loop)
- ? CPR4_MARGIN_ADJ_CTL_TEMP_ADJ_EN : 0)
- | (((ctrl->use_hw_closed_loop && !sdelta->allow_boost)
- || !ctrl->supports_hw_closed_loop)
- ? CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_EN : 0)
- | (sdelta->allow_boost
- ? CPR4_MARGIN_ADJ_CTL_BOOST_EN : 0));
-
- mb();
-
- if (!cpr_enabled) {
- cpr3_clock_disable(ctrl);
- ctrl->cpr_enabled = false;
- }
- return 0;
- }
- static void cpr3_regulator_set_base_target_quot(struct cpr3_regulator *vreg,
- u32 *base_quots)
- {
- struct cpr3_controller *ctrl = vreg->thread->ctrl;
- int i, j, ro_mask = CPR3_RO_MASK;
- u32 min_quot;
- for (i = 0; i < vreg->corner_count; i++)
- ro_mask &= vreg->corner[i].ro_mask;
-
- cpr3_write(ctrl, CPR3_REG_RO_MASK(vreg->thread->thread_id),
- ro_mask);
- for (i = 0; i < CPR3_RO_COUNT; i++) {
- for (j = 0, min_quot = INT_MAX; j < vreg->corner_count; j++)
- if (vreg->corner[j].target_quot[i])
- min_quot = min(min_quot,
- vreg->corner[j].target_quot[i]);
- if (min_quot == INT_MAX)
- min_quot = 0;
- cpr3_write(ctrl,
- CPR3_REG_TARGET_QUOT(vreg->thread->thread_id, i),
- min_quot);
- base_quots[i] = min_quot;
- }
- }
- static int cpr3_regulator_init_cprh_corners(struct cpr3_regulator *vreg)
- {
- struct cpr3_controller *ctrl = vreg->thread->ctrl;
- struct cpr3_corner *corner;
- u32 reg, delta_quot_steps, ro_sel;
- u32 *base_quots;
- int open_loop_volt_steps, floor_volt_steps, i, j, rc = 0;
- base_quots = kcalloc(CPR3_RO_COUNT, sizeof(*base_quots),
- GFP_KERNEL);
- if (!base_quots)
- return -ENOMEM;
- cpr3_regulator_set_base_target_quot(vreg, base_quots);
- for (i = 0; i < vreg->corner_count; i++) {
- corner = &vreg->corner[i];
- for (j = 0, ro_sel = INT_MAX; j < CPR3_RO_COUNT; j++) {
- if (corner->target_quot[j]) {
- ro_sel = j;
- break;
- }
- }
- if (ro_sel == INT_MAX) {
- if (!corner->proc_freq) {
-
- ro_sel = 0;
- } else if (ctrl->ignore_invalid_fuses) {
-
- cpr3_debug(vreg, "ignored that corner=%d has invalid RO select value\n",
- i);
- ro_sel = 0;
- } else {
- cpr3_err(vreg, "corner=%d has invalid RO select value\n",
- i);
- rc = -EINVAL;
- goto free_base_quots;
- }
- }
- open_loop_volt_steps = DIV_ROUND_UP(corner->open_loop_volt -
- ctrl->base_volt,
- ctrl->step_volt);
- floor_volt_steps = DIV_ROUND_UP(corner->floor_volt -
- ctrl->base_volt,
- ctrl->step_volt);
- delta_quot_steps = corner->proc_freq ?
- DIV_ROUND_UP(corner->target_quot[ro_sel] -
- base_quots[ro_sel],
- CPRH_DELTA_QUOT_STEP_FACTOR) :
- 0;
- if (open_loop_volt_steps > CPRH_CORNER_INIT_VOLTAGE_MAX_VALUE ||
- floor_volt_steps > CPRH_CORNER_FLOOR_VOLTAGE_MAX_VALUE ||
- delta_quot_steps > CPRH_CORNER_QUOT_DELTA_MAX_VALUE) {
- cpr3_err(ctrl, "invalid CPRh corner configuration: open_loop_volt_steps=%d (%d max.), floor_volt_steps=%d (%d max), delta_quot_steps=%d (%d max)\n",
- open_loop_volt_steps,
- CPRH_CORNER_INIT_VOLTAGE_MAX_VALUE,
- floor_volt_steps,
- CPRH_CORNER_FLOOR_VOLTAGE_MAX_VALUE,
- delta_quot_steps,
- CPRH_CORNER_QUOT_DELTA_MAX_VALUE);
- rc = -EINVAL;
- goto free_base_quots;
- }
- reg = (open_loop_volt_steps << CPRH_CORNER_INIT_VOLTAGE_SHIFT)
- & CPRH_CORNER_INIT_VOLTAGE_MASK;
- reg |= (floor_volt_steps << CPRH_CORNER_FLOOR_VOLTAGE_SHIFT)
- & CPRH_CORNER_FLOOR_VOLTAGE_MASK;
- reg |= (delta_quot_steps << CPRH_CORNER_QUOT_DELTA_SHIFT)
- & CPRH_CORNER_QUOT_DELTA_MASK;
- reg |= (ro_sel << CPRH_CORNER_RO_SEL_SHIFT)
- & CPRH_CORNER_RO_SEL_MASK;
- if (corner->use_open_loop)
- reg |= CPRH_CORNER_CPR_CL_DISABLE;
- cpr3_debug(ctrl, "corner=%d open_loop_volt_steps=%d, floor_volt_steps=%d, delta_quot_steps=%d, base_volt=%d, step_volt=%d, base_quot=%d\n",
- i, open_loop_volt_steps, floor_volt_steps,
- delta_quot_steps, ctrl->base_volt,
- ctrl->step_volt, base_quots[ro_sel]);
- cpr3_write(ctrl, CPRH_REG_CORNER(vreg->thread, i), reg);
- }
- free_base_quots:
- kfree(base_quots);
- return rc;
- }
- static void cprh_controller_program_sdelta(
- struct cpr3_controller *ctrl)
- {
-
- struct cpr3_regulator *vreg = &ctrl->thread[0].vreg[0];
- struct cprh_corner_band *corner_band;
- struct cpr4_sdelta *sdelta;
- int i, j, index;
- u32 reg = 0;
- if (!vreg->allow_core_count_adj && !vreg->allow_temp_adj)
- return;
- if (vreg->thread->thread_id != 0) {
- cpr3_err(vreg, "core count and temperature based adjustments are only allowed for CPR thread 0\n");
- return;
- }
- cpr4_regulator_init_temp_points(ctrl);
- for (i = 0; i < CPRH_CORNER_BAND_MAX_COUNT; i++) {
- reg |= (i < vreg->corner_band_count ?
- vreg->corner_band[i].corner
- & CPRH_CORNER_BAND_MASK :
- vreg->corner_count + 1)
- << (i * CPRH_CORNER_BAND_SHIFT);
- }
- cpr3_write(ctrl, CPRH_REG_CORNER_BAND, reg);
- for (i = 0; i < vreg->corner_band_count; i++) {
- corner_band = &vreg->corner_band[i];
- sdelta = corner_band->sdelta;
- if (!sdelta->allow_core_count_adj && !sdelta->allow_temp_adj) {
-
- continue;
- }
- if (vreg->allow_core_count_adj)
- cpr3_write_temp_core_margin(ctrl,
- CPRH_MARGIN_TEMP_CORE_VBAND(0, i),
- &sdelta->table[0]);
- for (j = 0; j < sdelta->max_core_count; j++) {
- index = j * sdelta->temp_band_count;
- cpr3_write_temp_core_margin(ctrl,
- CPRH_MARGIN_TEMP_CORE_VBAND(
- sdelta->allow_core_count_adj
- ? j + 1 : vreg->max_core_count, i),
- &sdelta->table[index]);
- }
- }
- if (!vreg->allow_core_count_adj) {
- cpr3_masked_write(ctrl, CPR4_REG_MISC,
- CPR4_MISC_MARGIN_TABLE_ROW_SELECT_MASK,
- vreg->max_core_count
- << CPR4_MISC_MARGIN_TABLE_ROW_SELECT_SHIFT);
- }
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
- CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_MASK
- | CPR4_MARGIN_ADJ_CTL_CORE_ADJ_EN
- | CPR4_MARGIN_ADJ_CTL_TEMP_ADJ_EN
- | CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_EN
- | CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK,
- vreg->max_core_count << CPR4_MARGIN_ADJ_CTL_MAX_NUM_CORES_SHIFT
- | ((vreg->allow_core_count_adj)
- ? CPR4_MARGIN_ADJ_CTL_CORE_ADJ_EN : 0)
- | (vreg->allow_temp_adj ? CPR4_MARGIN_ADJ_CTL_TEMP_ADJ_EN : 0)
- | ((ctrl->use_hw_closed_loop)
- ? CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_EN : 0)
- | (ctrl->use_hw_closed_loop
- ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE : 0));
-
- mb();
- }
- static int cprh_regulator_aging_adjust(struct cpr3_controller *ctrl);
- static bool cpr3_regulator_cprh_initialized(struct cpr3_controller *ctrl)
- {
- u32 reg;
- if (ctrl->ctrl_type != CPR_CTRL_TYPE_CPRH)
- return false;
- ctrl->cpr_hw_version = readl_relaxed(ctrl->cpr_ctrl_base
- + CPR3_REG_CPR_VERSION);
- reg = readl_relaxed(ctrl->cpr_ctrl_base + CPRH_REG_CTL(ctrl));
- return reg & CPRH_CTL_OSM_ENABLED;
- }
- static int cpr3_regulator_init_cprh(struct cpr3_controller *ctrl)
- {
- u32 reg, pmic_step_size = 1;
- u64 temp;
- int i, rc;
-
- if (ctrl->thread_count < 1 || ctrl->thread_count > 2) {
- cpr3_err(ctrl, "expected 1 or 2 threads but found %d\n",
- ctrl->thread_count);
- return -EINVAL;
- } else if (ctrl->thread[0].vreg_count != 1) {
- cpr3_err(ctrl, "expected 1 regulator for thread 0 but found %d\n",
- ctrl->thread[0].vreg_count);
- return -EINVAL;
- } else if (ctrl->thread_count == 2 && ctrl->thread[1].vreg_count != 1) {
- cpr3_err(ctrl, "expected 1 regulator for thread 1 but found %d\n",
- ctrl->thread[1].vreg_count);
- return -EINVAL;
- }
- rc = cprh_regulator_aging_adjust(ctrl);
- if (rc && rc != -ETIMEDOUT) {
-
- cpr3_err(ctrl, "CPR aging adjustment failed, rc=%d\n", rc);
- return rc;
- }
- cprh_controller_program_sdelta(ctrl);
- for (i = 0; i < ctrl->thread_count; i++) {
- rc = cpr3_regulator_init_cprh_corners(&ctrl->thread[i].vreg[0]);
- if (rc) {
- cpr3_err(ctrl, "failed to initialize CPRh corner registers\n");
- return rc;
- }
- }
- if (ctrl->reset_step_quot_loop_en)
- cpr3_masked_write(ctrl, CPR4_REG_MISC,
- CPR4_MISC_RESET_STEP_QUOT_LOOP_EN,
- CPR4_MISC_RESET_STEP_QUOT_LOOP_EN);
- if (ctrl->saw_use_unit_mV)
- pmic_step_size = ctrl->step_volt / 1000;
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
- CPR4_MARGIN_ADJ_CTL_PMIC_STEP_SIZE_MASK,
- (pmic_step_size
- << CPR4_MARGIN_ADJ_CTL_PMIC_STEP_SIZE_SHIFT));
- cpr3_masked_write(ctrl, CPR4_REG_SAW_ERROR_STEP_LIMIT,
- CPR4_SAW_ERROR_STEP_LIMIT_DN_MASK,
- (ctrl->down_error_step_limit
- << CPR4_SAW_ERROR_STEP_LIMIT_DN_SHIFT));
- cpr3_masked_write(ctrl, CPR4_REG_SAW_ERROR_STEP_LIMIT,
- CPR4_SAW_ERROR_STEP_LIMIT_UP_MASK,
- (ctrl->up_error_step_limit
- << CPR4_SAW_ERROR_STEP_LIMIT_UP_SHIFT));
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
- CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_STEP_QUOT_MASK,
- ctrl->step_quot_fixed
- << CPR4_MARGIN_ADJ_CTL_KV_MARGIN_ADJ_STEP_QUOT_SHIFT);
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
- CPR4_MARGIN_ADJ_CTL_PER_RO_KV_MARGIN_EN,
- (ctrl->use_dynamic_step_quot
- ? CPR4_MARGIN_ADJ_CTL_PER_RO_KV_MARGIN_EN : 0));
- if (ctrl->thread_count > 1)
- cpr3_masked_write(ctrl, CPR4_REG_CPR_TIMER_CLAMP,
- CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN,
- CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN);
- if (ctrl->voltage_settling_time) {
-
- temp = (u64)ctrl->cpr_clock_rate
- * (u64)ctrl->voltage_settling_time;
- do_div(temp, 1000000000);
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_TEMP_CORE_TIMERS,
- CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_MASK,
- temp
- << CPR4_MARGIN_TEMP_CORE_TIMERS_SETTLE_VOLTAGE_COUNT_SHIFT);
- }
- if (ctrl->corner_switch_delay_time) {
-
- temp = (u64)ctrl->cpr_clock_rate
- * (u64)ctrl->corner_switch_delay_time;
- do_div(temp, 1000000000);
- do_div(temp, CPRH_MODE_SWITCH_DELAY_FACTOR);
- cpr3_masked_write(ctrl, CPRH_REG_CTL(ctrl),
- CPRH_CTL_MODE_SWITCH_DELAY_MASK,
- temp << CPRH_CTL_MODE_SWITCH_DELAY_SHIFT);
- }
-
- if (ctrl->cpr_hw_version >= CPRH_CPR_VERSION_4P5
- && ctrl->acd_avg_enabled) {
- cpr3_masked_write(ctrl, CPRH_REG_MISC_REG2,
- CPRH_MISC_REG2_ACD_ADJ_STEP_UP_LIMIT_MASK,
- ctrl->acd_adj_up_step_limit <<
- CPRH_MISC_REG2_ACD_ADJ_STEP_UP_LIMIT_SHIFT);
- cpr3_masked_write(ctrl, CPRH_REG_MISC_REG2,
- CPRH_MISC_REG2_ACD_ADJ_STEP_DOWN_LIMIT_MASK,
- ctrl->acd_adj_down_step_limit <<
- CPRH_MISC_REG2_ACD_ADJ_STEP_DOWN_LIMIT_SHIFT);
- cpr3_masked_write(ctrl, CPRH_REG_MISC_REG2,
- CPRH_MISC_REG2_ACD_ADJ_STEP_SIZE_UP_MASK,
- ctrl->acd_adj_up_step_size <<
- CPRH_MISC_REG2_ACD_ADJ_STEP_SIZE_UP_SHIFT);
- cpr3_masked_write(ctrl, CPRH_REG_MISC_REG2,
- CPRH_MISC_REG2_ACD_ADJ_STEP_SIZE_DOWN_MASK,
- ctrl->acd_adj_down_step_size <<
- CPRH_MISC_REG2_ACD_ADJ_STEP_SIZE_DOWN_SHIFT);
- cpr3_masked_write(ctrl, CPRH_REG_MISC_REG2,
- CPRH_MISC_REG2_ACD_NOTWAIT_4_CL_SETTLE_MASK,
- (ctrl->acd_notwait_for_cl_settled
- ? CPRH_MISC_REG2_ACD_NOTWAIT_4_CL_SETTLE_EN
- : 0));
- cpr3_masked_write(ctrl, CPRH_REG_MISC_REG2,
- CPRH_MISC_REG2_ACD_AVG_FAST_UPDATE_EN_MASK,
- (ctrl->acd_adj_avg_fast_update
- ? CPRH_MISC_REG2_ACD_AVG_FAST_UPDATE_EN
- : 0));
- cpr3_masked_write(ctrl, CPRH_REG_MISC_REG2,
- CPRH_MISC_REG2_ACD_AVG_EN_MASK,
- CPRH_MISC_REG2_ACD_AVG_ENABLE);
- }
-
- reg = (DIV_ROUND_UP(ctrl->base_volt, ctrl->step_volt)
- << CPRH_CTL_BASE_VOLTAGE_SHIFT)
- & CPRH_CTL_BASE_VOLTAGE_MASK;
- reg |= (DIV_ROUND_UP(ctrl->step_volt, 1000)
- << CPRH_CTL_VOLTAGE_MULTIPLIER_SHIFT)
- & CPRH_CTL_VOLTAGE_MULTIPLIER_MASK;
-
- reg |= CPRH_CTL_OSM_ENABLED;
- cpr3_masked_write(ctrl, CPRH_REG_CTL(ctrl), CPRH_CTL_BASE_VOLTAGE_MASK
- | CPRH_CTL_VOLTAGE_MULTIPLIER_MASK
- | CPRH_CTL_OSM_ENABLED, reg);
-
- cpr3_ctrl_loop_enable(ctrl);
- return 0;
- }
- static int cpr3_regulator_init_ctrl(struct cpr3_controller *ctrl)
- {
- int i, j, k, m, rc;
- u32 ro_used = 0;
- u32 gcnt, cont_dly, up_down_dly, val;
- u64 temp;
- char *mode;
- if (ctrl->core_clk) {
- rc = clk_set_rate(ctrl->core_clk, ctrl->cpr_clock_rate);
- if (rc) {
- cpr3_err(ctrl, "clk_set_rate(core_clk, %u) failed, rc=%d\n",
- ctrl->cpr_clock_rate, rc);
- return rc;
- }
- }
- rc = cpr3_clock_enable(ctrl);
- if (rc) {
- cpr3_err(ctrl, "clock enable failed, rc=%d\n", rc);
- return rc;
- }
- ctrl->cpr_enabled = true;
- ctrl->cpr_hw_version = cpr3_read(ctrl, CPR3_REG_CPR_VERSION);
-
- for (i = 0; i < ctrl->thread_count; i++)
- for (j = 0; j < ctrl->thread[i].vreg_count; j++)
- for (k = 0; k < ctrl->thread[i].vreg[j].corner_count;
- k++)
- for (m = 0; m < CPR3_RO_COUNT; m++)
- if (ctrl->thread[i].vreg[j].corner[k].
- target_quot[m])
- ro_used |= BIT(m);
-
- gcnt = cpr3_regulator_get_gcnt(ctrl);
- for (i = 0; i < CPR3_RO_COUNT; i++)
- if (ro_used & BIT(i))
- cpr3_write(ctrl, CPR3_REG_GCNT(i), gcnt);
-
- temp = (u64)ctrl->cpr_clock_rate * (u64)ctrl->loop_time;
- do_div(temp, 1000000000);
- cont_dly = temp;
- if (ctrl->supports_hw_closed_loop
- && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3)
- cpr3_write(ctrl, CPR3_REG_CPR_TIMER_MID_CONT, cont_dly);
- else
- cpr3_write(ctrl, CPR3_REG_CPR_TIMER_AUTO_CONT, cont_dly);
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
- temp = (u64)ctrl->cpr_clock_rate *
- (u64)ctrl->up_down_delay_time;
- do_div(temp, 1000000000);
- up_down_dly = temp;
- if (ctrl->supports_hw_closed_loop)
- cpr3_write(ctrl, CPR3_REG_CPR_TIMER_UP_DN_CONT,
- up_down_dly);
- cpr3_debug(ctrl, "up_down_dly=%u, up_down_delay_time=%u ns\n",
- up_down_dly, ctrl->up_down_delay_time);
- }
- cpr3_debug(ctrl, "cpr_clock_rate=%u HZ, sensor_time=%u ns, loop_time=%u ns, gcnt=%u, cont_dly=%u\n",
- ctrl->cpr_clock_rate, ctrl->sensor_time, ctrl->loop_time,
- gcnt, cont_dly);
-
- val = (ctrl->idle_clocks << CPR3_CPR_CTL_IDLE_CLOCKS_SHIFT)
- & CPR3_CPR_CTL_IDLE_CLOCKS_MASK;
- val |= (ctrl->count_mode << CPR3_CPR_CTL_COUNT_MODE_SHIFT)
- & CPR3_CPR_CTL_COUNT_MODE_MASK;
- val |= (ctrl->count_repeat << CPR3_CPR_CTL_COUNT_REPEAT_SHIFT)
- & CPR3_CPR_CTL_COUNT_REPEAT_MASK;
- cpr3_write(ctrl, CPR3_REG_CPR_CTL, val);
- cpr3_debug(ctrl, "idle_clocks=%u, count_mode=%u, count_repeat=%u; CPR_CTL=0x%08X\n",
- ctrl->idle_clocks, ctrl->count_mode, ctrl->count_repeat, val);
-
- val = (ctrl->step_quot_init_min << CPR3_CPR_STEP_QUOT_MIN_SHIFT)
- & CPR3_CPR_STEP_QUOT_MIN_MASK;
- val |= (ctrl->step_quot_init_max << CPR3_CPR_STEP_QUOT_MAX_SHIFT)
- & CPR3_CPR_STEP_QUOT_MAX_MASK;
- cpr3_write(ctrl, CPR3_REG_CPR_STEP_QUOT, val);
- cpr3_debug(ctrl, "step_quot_min=%u, step_quot_max=%u; STEP_QUOT=0x%08X\n",
- ctrl->step_quot_init_min, ctrl->step_quot_init_max, val);
-
- for (i = 0; i < ctrl->sensor_count; i++)
- cpr3_write(ctrl, CPR3_REG_SENSOR_OWNER(i),
- ctrl->sensor_owner[i]);
-
- for (i = 0; i < ctrl->thread_count; i++) {
- rc = cpr3_regulator_init_thread(&ctrl->thread[i]);
- if (rc) {
- cpr3_err(ctrl, "CPR thread register initialization failed, rc=%d\n",
- rc);
- return rc;
- }
- }
- if (ctrl->supports_hw_closed_loop) {
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4 ||
- ctrl->ctrl_type == CPR_CTRL_TYPE_CPRH) {
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
- CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK,
- ctrl->use_hw_closed_loop
- ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE
- : CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE);
- } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
- cpr3_write(ctrl, CPR3_REG_HW_CLOSED_LOOP,
- ctrl->use_hw_closed_loop
- ? CPR3_HW_CLOSED_LOOP_ENABLE
- : CPR3_HW_CLOSED_LOOP_DISABLE);
- cpr3_debug(ctrl, "PD_THROTTLE=0x%08X\n",
- ctrl->proc_clock_throttle);
- }
- if ((ctrl->use_hw_closed_loop ||
- ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) &&
- ctrl->ctrl_type != CPR_CTRL_TYPE_CPRH) {
- rc = regulator_enable(ctrl->vdd_limit_regulator);
- if (rc) {
- cpr3_err(ctrl, "CPR limit regulator enable failed, rc=%d\n",
- rc);
- return rc;
- }
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
- rc = msm_spm_avs_enable_irq(0,
- MSM_SPM_AVS_IRQ_MAX);
- if (rc) {
- cpr3_err(ctrl, "could not enable max IRQ, rc=%d\n",
- rc);
- return rc;
- }
- }
- }
- }
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
- rc = cpr3_regulator_init_cpr4(ctrl);
- if (rc) {
- cpr3_err(ctrl, "CPR4-specific controller initialization failed, rc=%d\n",
- rc);
- return rc;
- }
- } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPRH) {
- rc = cpr3_regulator_init_cprh(ctrl);
- if (rc) {
- cpr3_err(ctrl, "CPRh-specific controller initialization failed, rc=%d\n",
- rc);
- return rc;
- }
- }
-
- wmb();
-
- if (ctrl->ctrl_type != CPR_CTRL_TYPE_CPRH) {
- cpr3_clock_disable(ctrl);
- ctrl->cpr_enabled = false;
- }
- if (!ctrl->cpr_allowed_sw || !ctrl->cpr_allowed_hw)
- mode = "open-loop";
- else if (ctrl->supports_hw_closed_loop &&
- ctrl->ctrl_type != CPR_CTRL_TYPE_CPRH)
- mode = ctrl->use_hw_closed_loop
- ? "HW closed-loop" : "SW closed-loop";
- else if (ctrl->supports_hw_closed_loop &&
- ctrl->ctrl_type == CPR_CTRL_TYPE_CPRH)
- mode = ctrl->use_hw_closed_loop
- ? "full HW closed-loop" : "open-loop";
- else
- mode = "closed-loop";
- cpr3_info(ctrl, "Default CPR mode = %s", mode);
- return 0;
- }
- static int
- cpr3_regulator_init_hw_closed_loop_dependencies(struct platform_device *pdev,
- struct cpr3_controller *ctrl)
- {
- struct resource *res;
- int rc = 0;
- u32 val;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "saw");
- if (res && res->start)
- ctrl->saw_base = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
- if (ctrl->saw_base) {
-
- rc = of_property_read_u32(ctrl->dev->of_node,
- "qcom,saw-avs-ctrl", &val);
- if (rc) {
- cpr3_err(ctrl, "unable to read DT property qcom,saw-avs-ctrl, rc=%d\n",
- rc);
- return rc;
- }
- writel_relaxed(val, ctrl->saw_base + SAW_REG_AVS_CTL);
- rc = of_property_read_u32(ctrl->dev->of_node,
- "qcom,saw-avs-limit", &val);
- if (rc) {
- cpr3_err(ctrl, "unable to read DT property qcom,saw-avs-limit, rc=%d\n",
- rc);
- return rc;
- }
- writel_relaxed(val, ctrl->saw_base + SAW_REG_AVS_LIMIT);
- } else {
-
- rc = msm_spm_probe_done();
- if (rc) {
- if (rc != -EPROBE_DEFER)
- cpr3_err(ctrl, "spm unavailable, rc=%d\n", rc);
- return rc;
- }
- }
- return 0;
- }
- static void cpr3_regulator_set_target_quot(struct cpr3_thread *thread)
- {
- u32 new_quot, last_quot;
- int i;
- if (thread->aggr_corner.ro_mask == CPR3_RO_MASK
- && thread->last_closed_loop_aggr_corner.ro_mask == CPR3_RO_MASK) {
-
- return;
- } else if (thread->aggr_corner.ro_mask == CPR3_RO_MASK) {
- cpr3_write(thread->ctrl, CPR3_REG_RO_MASK(thread->thread_id),
- CPR3_RO_MASK);
- thread->last_closed_loop_aggr_corner.ro_mask = CPR3_RO_MASK;
-
- return;
- } else if (thread->aggr_corner.ro_mask
- != thread->last_closed_loop_aggr_corner.ro_mask) {
- cpr3_write(thread->ctrl, CPR3_REG_RO_MASK(thread->thread_id),
- thread->aggr_corner.ro_mask);
- }
- for (i = 0; i < CPR3_RO_COUNT; i++) {
- new_quot = thread->aggr_corner.target_quot[i];
- last_quot = thread->last_closed_loop_aggr_corner.target_quot[i];
- if (new_quot != last_quot)
- cpr3_write(thread->ctrl,
- CPR3_REG_TARGET_QUOT(thread->thread_id, i),
- new_quot);
- }
- thread->last_closed_loop_aggr_corner = thread->aggr_corner;
- }
- static void cpr3_update_vreg_closed_loop_volt(struct cpr3_regulator *vreg,
- int vdd_volt, u32 reg_last_measurement)
- {
- bool step_dn, step_up, aggr_step_up, aggr_step_dn, aggr_step_mid;
- bool valid, pd_valid, saw_error;
- struct cpr3_controller *ctrl = vreg->thread->ctrl;
- struct cpr3_corner *corner;
- u32 id;
- if (vreg->last_closed_loop_corner == CPR3_REGULATOR_CORNER_INVALID)
- return;
- corner = &vreg->corner[vreg->last_closed_loop_corner];
- if (vreg->thread->last_closed_loop_aggr_corner.ro_mask
- == CPR3_RO_MASK || !vreg->aggregated) {
- return;
- } else if (!ctrl->cpr_enabled || !ctrl->last_corner_was_closed_loop) {
- return;
- } else if (ctrl->thread_count == 1
- && vdd_volt >= corner->floor_volt
- && vdd_volt <= corner->ceiling_volt) {
- corner->last_volt = vdd_volt;
- cpr3_debug(vreg, "last_volt updated: last_volt[%d]=%d, ceiling_volt[%d]=%d, floor_volt[%d]=%d\n",
- vreg->last_closed_loop_corner, corner->last_volt,
- vreg->last_closed_loop_corner,
- corner->ceiling_volt,
- vreg->last_closed_loop_corner,
- corner->floor_volt);
- return;
- } else if (!ctrl->supports_hw_closed_loop) {
- return;
- } else if (ctrl->ctrl_type != CPR_CTRL_TYPE_CPR3) {
- corner->last_volt = vdd_volt;
- cpr3_debug(vreg, "last_volt updated: last_volt[%d]=%d, ceiling_volt[%d]=%d, floor_volt[%d]=%d\n",
- vreg->last_closed_loop_corner, corner->last_volt,
- vreg->last_closed_loop_corner,
- corner->ceiling_volt,
- vreg->last_closed_loop_corner,
- corner->floor_volt);
- return;
- }
-
- valid = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_VALID);
- if (!valid) {
- cpr3_debug(vreg, "CPR_LAST_VALID_MEASUREMENT=0x%X valid bit not set\n",
- reg_last_measurement);
- return;
- }
- id = vreg->thread->thread_id;
- step_dn
- = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_THREAD_DN(id));
- step_up
- = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_THREAD_UP(id));
- aggr_step_dn = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_AGGR_DN);
- aggr_step_mid
- = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_AGGR_MID);
- aggr_step_up = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_AGGR_UP);
- saw_error = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_SAW_ERROR);
- pd_valid
- = !((((reg_last_measurement & CPR3_LAST_MEASUREMENT_PD_BYPASS_MASK)
- >> CPR3_LAST_MEASUREMENT_PD_BYPASS_SHIFT)
- & vreg->pd_bypass_mask) == vreg->pd_bypass_mask);
- if (!pd_valid) {
- cpr3_debug(vreg, "CPR_LAST_VALID_MEASUREMENT=0x%X, all power domains bypassed\n",
- reg_last_measurement);
- return;
- } else if (step_dn && step_up) {
- cpr3_err(vreg, "both up and down status bits set, CPR_LAST_VALID_MEASUREMENT=0x%X\n",
- reg_last_measurement);
- return;
- } else if (aggr_step_dn && step_dn && vdd_volt < corner->last_volt
- && vdd_volt >= corner->floor_volt) {
- corner->last_volt = vdd_volt;
- } else if (aggr_step_up && step_up && vdd_volt > corner->last_volt
- && vdd_volt <= corner->ceiling_volt) {
- corner->last_volt = vdd_volt;
- } else if (aggr_step_mid
- && vdd_volt >= corner->floor_volt
- && vdd_volt <= corner->ceiling_volt) {
- corner->last_volt = vdd_volt;
- } else if (saw_error && (vdd_volt == corner->ceiling_volt
- || vdd_volt == corner->floor_volt)) {
- corner->last_volt = vdd_volt;
- } else {
- 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",
- vreg->last_closed_loop_corner, corner->last_volt,
- vreg->last_closed_loop_corner,
- corner->ceiling_volt,
- vreg->last_closed_loop_corner, corner->floor_volt,
- vdd_volt, reg_last_measurement);
- return;
- }
- 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",
- vreg->last_closed_loop_corner, corner->last_volt,
- vreg->last_closed_loop_corner, corner->ceiling_volt,
- vreg->last_closed_loop_corner, corner->floor_volt,
- reg_last_measurement);
- }
- static int cpr3_regulator_config_ldo_retention(struct cpr3_regulator *vreg,
- int ref_volt)
- {
- struct regulator *ldo_ret_reg = vreg->ldo_ret_regulator;
- int retention_volt, rc;
- enum msm_ldo_supply_mode mode;
- if (!ldo_ret_reg) {
-
- return 0;
- }
- retention_volt = regulator_get_voltage(ldo_ret_reg);
- if (retention_volt < 0) {
- cpr3_err(vreg, "regulator_get_voltage(ldo_ret) failed, rc=%d\n",
- retention_volt);
- return retention_volt;
- }
- mode = ref_volt >= retention_volt + vreg->ldo_min_headroom_volt
- ? LDO_MODE : BHS_MODE;
- rc = regulator_allow_bypass(ldo_ret_reg, mode);
- if (rc)
- cpr3_err(vreg, "regulator_allow_bypass(ldo_ret) == %s failed, rc=%d\n",
- mode ? "true" : "false", rc);
- return rc;
- }
- static int cpr3_regulator_config_kryo_ldo_mem_acc(struct cpr3_regulator *vreg,
- int new_volt)
- {
- struct cpr3_controller *ctrl = vreg->thread->ctrl;
- struct regulator *ldo_reg = vreg->ldo_regulator;
- struct regulator *mem_acc_reg = vreg->mem_acc_regulator;
- int mem_acc_volt = ctrl->mem_acc_threshold_volt;
- int last_volt, safe_volt, mem_acc_corn, rc;
- enum msm_apm_supply apm_mode;
- if (!mem_acc_reg || !mem_acc_volt || !ldo_reg)
- return 0;
- apm_mode = msm_apm_get_supply(ctrl->apm);
- if (apm_mode < 0) {
- cpr3_err(ctrl, "APM get supply failed, rc=%d\n",
- apm_mode);
- return apm_mode;
- }
- last_volt = regulator_get_voltage(ldo_reg);
- if (last_volt < 0) {
- cpr3_err(vreg, "regulator_get_voltage(ldo) failed, rc=%d\n",
- last_volt);
- return last_volt;
- }
- if (((last_volt < mem_acc_volt && mem_acc_volt <= new_volt)
- || (last_volt >= mem_acc_volt && mem_acc_volt > new_volt))) {
- if (apm_mode == ctrl->apm_high_supply)
- safe_volt = min(vreg->ldo_max_volt, mem_acc_volt);
- else
- safe_volt = min(max(ctrl->system_supply_max_volt -
- vreg->ldo_max_headroom_volt,
- mem_acc_volt), vreg->ldo_max_volt);
- rc = regulator_set_voltage(ldo_reg, safe_volt,
- max(new_volt, last_volt));
- if (rc) {
- cpr3_err(ctrl, "regulator_set_voltage(ldo) == %d failed, rc=%d\n",
- mem_acc_volt, rc);
- return rc;
- }
- mem_acc_corn = new_volt < mem_acc_volt ?
- ctrl->mem_acc_corner_map[CPR3_MEM_ACC_LOW_CORNER] :
- ctrl->mem_acc_corner_map[CPR3_MEM_ACC_HIGH_CORNER];
- rc = regulator_set_voltage(mem_acc_reg, mem_acc_corn,
- mem_acc_corn);
- if (rc) {
- cpr3_err(ctrl, "regulator_set_voltage(mem_acc) == %d failed, rc=%d\n",
- 0, rc);
- return rc;
- }
- }
- return 0;
- }
- static int cpr3_regulator_kryo_bhs_prepare(struct cpr3_regulator *vreg,
- int vdd_volt, int vdd_ceiling_volt)
- {
- struct regulator *ldo_reg = vreg->ldo_regulator;
- int bhs_volt, rc;
- bhs_volt = vdd_volt - vreg->ldo_min_headroom_volt;
- if (bhs_volt > vreg->ldo_max_volt) {
- cpr3_debug(vreg, "limited to LDO output of %d uV when switching to BHS mode\n",
- vreg->ldo_max_volt);
- bhs_volt = vreg->ldo_max_volt;
- }
- rc = cpr3_regulator_config_kryo_ldo_mem_acc(vreg, bhs_volt);
- if (rc) {
- cpr3_err(vreg, "failed to configure mem-acc settings\n");
- return rc;
- }
- rc = regulator_set_voltage(ldo_reg, bhs_volt, min(vdd_ceiling_volt,
- vreg->ldo_max_volt));
- if (rc) {
- cpr3_err(vreg, "regulator_set_voltage(ldo) == %d failed, rc=%d\n",
- bhs_volt, rc);
- return rc;
- }
- return rc;
- }
- static int cpr3_regulator_set_bhs_mode(struct cpr3_regulator *vreg,
- int vdd_volt, int vdd_ceiling_volt)
- {
- struct regulator *ldo_reg = vreg->ldo_regulator;
- int rc;
- if (vreg->ldo_type == CPR3_LDO_KRYO) {
- rc = cpr3_regulator_kryo_bhs_prepare(vreg, vdd_volt,
- vdd_ceiling_volt);
- if (rc) {
- cpr3_err(vreg, "cpr3 regulator bhs mode prepare failed, rc=%d\n",
- rc);
- return rc;
- }
- }
- rc = regulator_allow_bypass(ldo_reg, BHS_MODE);
- if (rc) {
- cpr3_err(vreg, "regulator_allow_bypass(bhs) == %s failed, rc=%d\n",
- BHS_MODE ? "true" : "false", rc);
- return rc;
- }
- vreg->ldo_regulator_bypass = BHS_MODE;
- return rc;
- }
- static int cpr3_regulator_ldo_apm_prepare(struct cpr3_controller *ctrl,
- int new_volt, int last_volt,
- struct cpr3_corner *aggr_corner)
- {
- struct cpr3_regulator *vreg;
- struct cpr3_corner *current_corner;
- enum msm_apm_supply apm_mode;
- int i, j, safe_volt, max_volt, ldo_volt, ref_volt, rc;
- apm_mode = msm_apm_get_supply(ctrl->apm);
- if (apm_mode < 0) {
- cpr3_err(ctrl, "APM get supply failed, rc=%d\n", apm_mode);
- return apm_mode;
- }
- if (apm_mode == ctrl->apm_low_supply ||
- new_volt >= ctrl->apm_threshold_volt)
- return 0;
-
- for (i = 0; i < ctrl->thread_count; i++) {
- for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
- vreg = &ctrl->thread[i].vreg[j];
- if (!vreg->vreg_enabled || vreg->current_corner
- == CPR3_REGULATOR_CORNER_INVALID)
- continue;
- if (!vreg->ldo_regulator || !vreg->ldo_mode_allowed ||
- vreg->ldo_regulator_bypass == BHS_MODE)
- continue;
-
- current_corner = &vreg->corner[vreg->current_corner];
- ldo_volt = current_corner->open_loop_volt
- - vreg->ldo_adjust_volt;
- ref_volt = ctrl->use_hw_closed_loop ?
- aggr_corner->floor_volt :
- new_volt;
- if (ref_volt < ldo_volt + vreg->ldo_min_headroom_volt
- || ldo_volt < ctrl->system_supply_max_volt -
- vreg->ldo_max_headroom_volt ||
- ldo_volt > vreg->ldo_max_volt) {
- rc = cpr3_regulator_set_bhs_mode(vreg,
- last_volt, aggr_corner->ceiling_volt);
- if (rc)
- return rc;
-
- continue;
- }
- safe_volt = min(max(ldo_volt,
- ctrl->system_supply_max_volt
- - vreg->ldo_max_headroom_volt),
- vreg->ldo_max_volt);
- max_volt = min(ctrl->system_supply_max_volt,
- vreg->ldo_max_volt);
- rc = regulator_set_voltage(vreg->ldo_regulator,
- safe_volt, max_volt);
- if (rc) {
- cpr3_err(vreg, "regulator_set_voltage(ldo) == %d failed, rc=%d\n",
- safe_volt, rc);
- return rc;
- }
- }
- }
- return 0;
- }
- static int cpr3_regulator_config_vreg_kryo_ldo(struct cpr3_regulator *vreg,
- int vdd_floor_volt, int vdd_ceiling_volt,
- int ref_volt, int last_volt)
- {
- struct cpr3_controller *ctrl = vreg->thread->ctrl;
- struct regulator *ldo_reg = vreg->ldo_regulator;
- struct cpr3_corner *current_corner;
- enum msm_apm_supply apm_mode;
- int rc, ldo_volt, final_ldo_volt, bhs_volt, max_volt, safe_volt;
- current_corner = &vreg->corner[vreg->current_corner];
- ldo_volt = current_corner->open_loop_volt
- - vreg->ldo_adjust_volt;
- bhs_volt = last_volt - vreg->ldo_min_headroom_volt;
- max_volt = min(vdd_ceiling_volt, vreg->ldo_max_volt);
- if (ref_volt >= ldo_volt + vreg->ldo_min_headroom_volt &&
- ldo_volt >= ctrl->system_supply_max_volt -
- vreg->ldo_max_headroom_volt &&
- bhs_volt >= ctrl->system_supply_max_volt -
- vreg->ldo_max_headroom_volt &&
- ldo_volt <= vreg->ldo_max_volt) {
-
- apm_mode = msm_apm_get_supply(ctrl->apm);
- if (apm_mode < 0) {
- cpr3_err(ctrl, "APM get supply failed, rc=%d\n",
- apm_mode);
- return apm_mode;
- }
- if (vreg->ldo_regulator_bypass == BHS_MODE) {
-
- if (apm_mode == ctrl->apm_high_supply)
- safe_volt = min(vreg->ldo_max_volt, bhs_volt);
- else
- safe_volt =
- min(max(ctrl->system_supply_max_volt -
- vreg->ldo_max_headroom_volt,
- bhs_volt),
- vreg->ldo_max_volt);
- rc = cpr3_regulator_config_kryo_ldo_mem_acc(vreg,
- safe_volt);
- if (rc) {
- cpr3_err(vreg, "failed to configure mem-acc settings\n");
- return rc;
- }
- rc = regulator_set_voltage(ldo_reg, safe_volt,
- max_volt);
- if (rc) {
- cpr3_err(vreg, "regulator_set_voltage(ldo) == %d failed, rc=%d\n",
- safe_volt, rc);
- return rc;
- }
- rc = regulator_allow_bypass(ldo_reg, LDO_MODE);
- if (rc) {
- cpr3_err(vreg, "regulator_allow_bypass(ldo) == %s failed, rc=%d\n",
- LDO_MODE ? "true" : "false", rc);
- return rc;
- }
- vreg->ldo_regulator_bypass = LDO_MODE;
- }
-
- if (apm_mode == ctrl->apm_high_supply)
- final_ldo_volt = max(ldo_volt,
- vdd_ceiling_volt -
- vreg->ldo_max_headroom_volt);
- else
- final_ldo_volt = ldo_volt;
- rc = cpr3_regulator_config_kryo_ldo_mem_acc(vreg,
- final_ldo_volt);
- if (rc) {
- cpr3_err(vreg, "failed to configure mem-acc settings\n");
- return rc;
- }
- rc = regulator_set_voltage(ldo_reg, final_ldo_volt, max_volt);
- if (rc) {
- cpr3_err(vreg, "regulator_set_voltage(ldo) == %d failed, rc=%d\n",
- final_ldo_volt, rc);
- return rc;
- }
- } else {
- if (vreg->ldo_regulator_bypass == LDO_MODE) {
-
- rc = cpr3_regulator_set_bhs_mode(vreg, last_volt,
- vdd_ceiling_volt);
- if (rc)
- return rc;
- }
- }
- return 0;
- }
- static int cpr3_regulator_config_vreg_ldo300(struct cpr3_regulator *vreg,
- int new_volt, int vdd_ceiling_volt)
- {
- struct regulator *ldo_reg = vreg->ldo_regulator;
- struct cpr3_corner *corner;
- bool mode;
- int rc = 0;
- corner = &vreg->corner[vreg->current_corner];
- mode = corner->ldo_mode_allowed ? LDO_MODE : BHS_MODE;
- if (mode == LDO_MODE) {
- rc = regulator_set_voltage(ldo_reg, new_volt, vdd_ceiling_volt);
- if (rc) {
- cpr3_err(vreg, "regulator_set_voltage(ldo) == %d failed, rc=%d\n",
- new_volt, rc);
- return rc;
- }
- }
- if (vreg->ldo_regulator_bypass != mode) {
- rc = regulator_allow_bypass(ldo_reg, mode);
- if (rc) {
- cpr3_err(vreg, "regulator_allow_bypass(%s) is failed, rc=%d\n",
- mode == LDO_MODE ? "ldo" : "bhs", rc);
- return rc;
- }
- vreg->ldo_regulator_bypass = mode;
- }
- return rc;
- }
- static int cpr3_regulator_config_vreg_ldo(struct cpr3_regulator *vreg,
- int vdd_floor_volt, int vdd_ceiling_volt,
- int new_volt, int last_volt)
- {
- struct cpr3_controller *ctrl = vreg->thread->ctrl;
- int ref_volt, rc;
- ref_volt = ctrl->use_hw_closed_loop ? vdd_floor_volt :
- new_volt;
- rc = cpr3_regulator_config_ldo_retention(vreg, ref_volt);
- if (rc)
- return rc;
- if (!vreg->vreg_enabled ||
- vreg->current_corner == CPR3_REGULATOR_CORNER_INVALID)
- return 0;
- switch (vreg->ldo_type) {
- case CPR3_LDO_KRYO:
- rc = cpr3_regulator_config_vreg_kryo_ldo(vreg, vdd_floor_volt,
- vdd_ceiling_volt, ref_volt, last_volt);
- if (rc)
- cpr3_err(vreg, "kryo ldo regulator config failed, rc=%d\n",
- rc);
- break;
- case CPR3_LDO300:
- rc = cpr3_regulator_config_vreg_ldo300(vreg, new_volt,
- vdd_ceiling_volt);
- if (rc)
- cpr3_err(vreg, "ldo300 regulator config failed, rc=%d\n",
- rc);
- break;
- default:
- cpr3_err(vreg, "invalid ldo regulator type = %d\n",
- vreg->ldo_type);
- rc = -EINVAL;
- }
- return rc;
- }
- static int cpr3_regulator_config_ldo(struct cpr3_controller *ctrl,
- int vdd_floor_volt, int vdd_ceiling_volt,
- int new_volt, int last_volt)
- {
- struct cpr3_regulator *vreg;
- int i, j, rc;
- for (i = 0; i < ctrl->thread_count; i++) {
- for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
- vreg = &ctrl->thread[i].vreg[j];
- if (!vreg->ldo_regulator || !vreg->ldo_mode_allowed)
- continue;
- rc = cpr3_regulator_config_vreg_ldo(vreg,
- vdd_floor_volt, vdd_ceiling_volt,
- new_volt, last_volt);
- if (rc)
- return rc;
- }
- }
- return 0;
- }
- static bool cpr3_regulator_mem_acc_bhs_used(struct cpr3_controller *ctrl)
- {
- struct cpr3_regulator *vreg;
- int i, j;
- if (!ctrl->mem_acc_threshold_volt)
- return false;
- if (ctrl->mem_acc_regulator)
- return true;
- for (i = 0; i < ctrl->thread_count; i++) {
- for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
- vreg = &ctrl->thread[i].vreg[j];
- if (vreg->mem_acc_regulator &&
- (!vreg->ldo_regulator ||
- vreg->ldo_regulator_bypass
- == BHS_MODE))
- return true;
- }
- }
- return false;
- }
- static int cpr3_regulator_config_bhs_mem_acc(struct cpr3_controller *ctrl,
- int new_volt, int *last_volt,
- struct cpr3_corner *aggr_corner)
- {
- struct cpr3_regulator *vreg;
- int i, j, rc, mem_acc_corn, safe_volt;
- int mem_acc_volt = ctrl->mem_acc_threshold_volt;
- int ref_volt;
- if (!cpr3_regulator_mem_acc_bhs_used(ctrl))
- return 0;
- ref_volt = ctrl->use_hw_closed_loop ? aggr_corner->floor_volt :
- new_volt;
- if (((*last_volt < mem_acc_volt && mem_acc_volt <= ref_volt) ||
- (*last_volt >= mem_acc_volt && mem_acc_volt > ref_volt))) {
- if (ref_volt < *last_volt)
- safe_volt = max(mem_acc_volt, aggr_corner->last_volt);
- else
- safe_volt = max(mem_acc_volt, *last_volt);
- rc = regulator_set_voltage(ctrl->vdd_regulator, safe_volt,
- new_volt < *last_volt ?
- ctrl->aggr_corner.ceiling_volt :
- new_volt);
- if (rc) {
- cpr3_err(ctrl, "regulator_set_voltage(vdd) == %d failed, rc=%d\n",
- safe_volt, rc);
- return rc;
- }
- *last_volt = safe_volt;
- mem_acc_corn = ref_volt < mem_acc_volt ?
- ctrl->mem_acc_corner_map[CPR3_MEM_ACC_LOW_CORNER] :
- ctrl->mem_acc_corner_map[CPR3_MEM_ACC_HIGH_CORNER];
- if (ctrl->mem_acc_regulator) {
- rc = regulator_set_voltage(ctrl->mem_acc_regulator,
- mem_acc_corn, mem_acc_corn);
- if (rc) {
- cpr3_err(ctrl, "regulator_set_voltage(mem_acc) == %d failed, rc=%d\n",
- mem_acc_corn, rc);
- return rc;
- }
- }
- for (i = 0; i < ctrl->thread_count; i++) {
- for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
- vreg = &ctrl->thread[i].vreg[j];
- if (!vreg->mem_acc_regulator ||
- (vreg->ldo_regulator &&
- vreg->ldo_regulator_bypass
- == LDO_MODE))
- continue;
- rc = regulator_set_voltage(
- vreg->mem_acc_regulator, mem_acc_corn,
- mem_acc_corn);
- if (rc) {
- cpr3_err(vreg, "regulator_set_voltage(mem_acc) == %d failed, rc=%d\n",
- mem_acc_corn, rc);
- return rc;
- }
- }
- }
- }
- return 0;
- }
- static int cpr3_regulator_switch_apm_mode(struct cpr3_controller *ctrl,
- int new_volt, int *last_volt,
- struct cpr3_corner *aggr_corner)
- {
- struct regulator *vdd = ctrl->vdd_regulator;
- int apm_volt = ctrl->apm_threshold_volt;
- int orig_last_volt = *last_volt;
- int rc;
- rc = regulator_set_voltage(vdd, apm_volt, apm_volt);
- if (rc) {
- cpr3_err(ctrl, "regulator_set_voltage(vdd) == %d failed, rc=%d\n",
- apm_volt, rc);
- return rc;
- }
- *last_volt = apm_volt;
- rc = cpr3_regulator_ldo_apm_prepare(ctrl, new_volt, *last_volt,
- aggr_corner);
- if (rc) {
- cpr3_err(ctrl, "unable to prepare LDO state for APM switch, rc=%d\n",
- rc);
- return rc;
- }
- rc = msm_apm_set_supply(ctrl->apm, new_volt >= apm_volt
- ? ctrl->apm_high_supply : ctrl->apm_low_supply);
- if (rc) {
- cpr3_err(ctrl, "APM switch failed, rc=%d\n", rc);
-
- regulator_set_voltage(vdd, orig_last_volt, INT_MAX);
- *last_volt = orig_last_volt;
- return rc;
- }
- return 0;
- }
- static int cpr3_regulator_config_voltage_crossings(struct cpr3_controller *ctrl,
- int new_volt, int *last_volt,
- struct cpr3_corner *aggr_corner)
- {
- bool apm_crossing = false, mem_acc_crossing = false;
- bool mem_acc_bhs_used;
- int apm_volt = ctrl->apm_threshold_volt;
- int mem_acc_volt = ctrl->mem_acc_threshold_volt;
- int ref_volt, rc;
- if (ctrl->apm && apm_volt > 0
- && ((*last_volt < apm_volt && apm_volt <= new_volt)
- || (*last_volt >= apm_volt && apm_volt > new_volt)))
- apm_crossing = true;
- mem_acc_bhs_used = cpr3_regulator_mem_acc_bhs_used(ctrl);
- ref_volt = ctrl->use_hw_closed_loop ? aggr_corner->floor_volt :
- new_volt;
- if (mem_acc_bhs_used &&
- (((*last_volt < mem_acc_volt && mem_acc_volt <= ref_volt) ||
- (*last_volt >= mem_acc_volt && mem_acc_volt > ref_volt))))
- mem_acc_crossing = true;
- if (apm_crossing && mem_acc_crossing) {
- if ((new_volt < *last_volt && apm_volt >= mem_acc_volt) ||
- (new_volt >= *last_volt && apm_volt < mem_acc_volt)) {
- rc = cpr3_regulator_switch_apm_mode(ctrl, new_volt,
- last_volt,
- aggr_corner);
- if (rc) {
- cpr3_err(ctrl, "unable to switch APM mode\n");
- return rc;
- }
- rc = cpr3_regulator_config_bhs_mem_acc(ctrl, new_volt,
- last_volt, aggr_corner);
- if (rc) {
- cpr3_err(ctrl, "unable to configure BHS mem-acc settings\n");
- return rc;
- }
- } else {
- rc = cpr3_regulator_config_bhs_mem_acc(ctrl, new_volt,
- last_volt, aggr_corner);
- if (rc) {
- cpr3_err(ctrl, "unable to configure BHS mem-acc settings\n");
- return rc;
- }
- rc = cpr3_regulator_switch_apm_mode(ctrl, new_volt,
- last_volt,
- aggr_corner);
- if (rc) {
- cpr3_err(ctrl, "unable to switch APM mode\n");
- return rc;
- }
- }
- } else if (apm_crossing) {
- rc = cpr3_regulator_switch_apm_mode(ctrl, new_volt, last_volt,
- aggr_corner);
- if (rc) {
- cpr3_err(ctrl, "unable to switch APM mode\n");
- return rc;
- }
- } else if (mem_acc_crossing) {
- rc = cpr3_regulator_config_bhs_mem_acc(ctrl, new_volt,
- last_volt, aggr_corner);
- if (rc) {
- cpr3_err(ctrl, "unable to configure BHS mem-acc settings\n");
- return rc;
- }
- }
- return 0;
- }
- static int cpr3_regulator_config_mem_acc(struct cpr3_controller *ctrl,
- struct cpr3_corner *aggr_corner)
- {
- int rc;
- if (ctrl->mem_acc_regulator && aggr_corner->mem_acc_volt) {
- rc = regulator_set_voltage(ctrl->mem_acc_regulator,
- aggr_corner->mem_acc_volt,
- aggr_corner->mem_acc_volt);
- if (rc) {
- cpr3_err(ctrl, "regulator_set_voltage(mem_acc) == %d failed, rc=%d\n",
- aggr_corner->mem_acc_volt, rc);
- return rc;
- }
- }
- return 0;
- }
- static int cpr3_regulator_scale_vdd_voltage(struct cpr3_controller *ctrl,
- int new_volt, int last_volt,
- struct cpr3_corner *aggr_corner)
- {
- struct regulator *vdd = ctrl->vdd_regulator;
- int rc;
- if (new_volt < last_volt) {
- if (ctrl->support_ldo300_vreg) {
- rc = cpr3_regulator_config_mem_acc(ctrl, aggr_corner);
- if (rc)
- return rc;
- }
-
- rc = cpr3_regulator_config_ldo(ctrl, aggr_corner->floor_volt,
- ctrl->aggr_corner.ceiling_volt,
- new_volt, last_volt);
- if (rc) {
- cpr3_err(ctrl, "unable to configure LDO state, rc=%d\n",
- rc);
- return rc;
- }
- if (!ctrl->support_ldo300_vreg) {
- rc = cpr3_regulator_config_mem_acc(ctrl, aggr_corner);
- if (rc)
- return rc;
- }
- } else {
-
- if (ctrl->system_regulator) {
- rc = regulator_set_voltage(ctrl->system_regulator,
- aggr_corner->system_volt, INT_MAX);
- if (rc) {
- cpr3_err(ctrl, "regulator_set_voltage(system) == %d failed, rc=%d\n",
- aggr_corner->system_volt, rc);
- return rc;
- }
- }
- }
- rc = cpr3_regulator_config_voltage_crossings(ctrl, new_volt, &last_volt,
- aggr_corner);
- if (rc) {
- cpr3_err(ctrl, "unable to handle voltage threshold crossing configurations, rc=%d\n",
- rc);
- return rc;
- }
-
- rc = regulator_set_voltage(vdd, new_volt - (ctrl->cpr_enabled ? 0 : 1),
- aggr_corner->ceiling_volt);
- if (rc) {
- cpr3_err(ctrl, "regulator_set_voltage(vdd) == %d failed, rc=%d\n",
- new_volt, rc);
- return rc;
- }
- if (new_volt == last_volt && ctrl->supports_hw_closed_loop
- && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
-
- rc = regulator_sync_voltage(vdd);
- if (rc) {
- cpr3_err(ctrl, "regulator_sync_voltage(vdd) == %d failed, rc=%d\n",
- new_volt, rc);
- return rc;
- }
- }
- if (new_volt >= last_volt) {
-
- rc = cpr3_regulator_config_ldo(ctrl, aggr_corner->floor_volt,
- aggr_corner->ceiling_volt,
- new_volt, new_volt);
- if (rc) {
- cpr3_err(ctrl, "unable to configure LDO state, rc=%d\n",
- rc);
- return rc;
- }
- rc = cpr3_regulator_config_mem_acc(ctrl, aggr_corner);
- if (rc)
- return rc;
- } else {
-
- if (ctrl->system_regulator) {
- rc = regulator_set_voltage(ctrl->system_regulator,
- aggr_corner->system_volt, INT_MAX);
- if (rc) {
- cpr3_err(ctrl, "regulator_set_voltage(system) == %d failed, rc=%d\n",
- aggr_corner->system_volt, rc);
- return rc;
- }
- }
- }
- return 0;
- }
- static int cpr3_regulator_get_dynamic_floor_volt(struct cpr3_controller *ctrl,
- u32 reg_last_measurement)
- {
- int dynamic_floor_volt = 0;
- struct cpr3_regulator *vreg;
- bool valid, pd_valid;
- u32 bypass_bits;
- int i, j;
- if (!ctrl->supports_hw_closed_loop)
- return 0;
- if (likely(!ctrl->use_hw_closed_loop)) {
- valid = !!(reg_last_measurement & CPR3_LAST_MEASUREMENT_VALID);
- bypass_bits
- = (reg_last_measurement & CPR3_LAST_MEASUREMENT_PD_BYPASS_MASK)
- >> CPR3_LAST_MEASUREMENT_PD_BYPASS_SHIFT;
- } else {
-
- valid = false;
- bypass_bits = 0;
- }
- for (i = 0; i < ctrl->thread_count; i++) {
- for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
- vreg = &ctrl->thread[i].vreg[j];
- if (!vreg->uses_dynamic_floor)
- continue;
- pd_valid = !((bypass_bits & vreg->pd_bypass_mask)
- == vreg->pd_bypass_mask);
- if (!valid || !pd_valid)
- dynamic_floor_volt = max(dynamic_floor_volt,
- vreg->corner[
- vreg->dynamic_floor_corner].last_volt);
- }
- }
- return dynamic_floor_volt;
- }
- static int cpr3_regulator_max_sdelta_diff(const struct cpr4_sdelta *sdelta,
- int step_volt)
- {
- int i, j, index, sdelta_min = INT_MAX, sdelta_max = INT_MIN;
- if (!sdelta || !sdelta->table)
- return 0;
- for (i = 0; i < sdelta->max_core_count; i++) {
- for (j = 0; j < sdelta->temp_band_count; j++) {
- index = i * sdelta->temp_band_count + j;
- sdelta_min = min(sdelta_min, sdelta->table[index]);
- sdelta_max = max(sdelta_max, sdelta->table[index]);
- }
- }
- return (sdelta_max - sdelta_min) * step_volt;
- }
- static void cpr3_regulator_aggregate_sdelta(
- struct cpr3_corner *aggr_corner,
- const struct cpr3_corner *corner, int step_volt)
- {
- struct cpr4_sdelta *aggr_sdelta, *sdelta;
- int aggr_core_count, core_count, temp_band_count;
- u32 aggr_index, index;
- int i, j, sdelta_size, cap_steps, adjust_sdelta;
- aggr_sdelta = aggr_corner->sdelta;
- sdelta = corner->sdelta;
- if (aggr_corner->open_loop_volt < corner->open_loop_volt) {
-
- aggr_sdelta->cap_volt = min(aggr_sdelta->cap_volt,
- (corner->open_loop_volt -
- aggr_corner->open_loop_volt));
-
- sdelta_size = aggr_sdelta->max_core_count
- * aggr_sdelta->temp_band_count;
- if (aggr_sdelta->allow_core_count_adj
- || aggr_sdelta->allow_temp_adj)
- memset(aggr_sdelta->table, 0, sdelta_size
- * sizeof(*aggr_sdelta->table));
- if (sdelta->allow_temp_adj || sdelta->allow_core_count_adj) {
-
- sdelta_size = sdelta->max_core_count
- * sdelta->temp_band_count;
- if (sdelta->table)
- memcpy(aggr_sdelta->table, sdelta->table,
- sdelta_size * sizeof(*sdelta->table));
- }
- if (sdelta->allow_boost) {
- memcpy(aggr_sdelta->boost_table, sdelta->boost_table,
- sdelta->temp_band_count
- * sizeof(*sdelta->boost_table));
- aggr_sdelta->boost_num_cores = sdelta->boost_num_cores;
- } else if (aggr_sdelta->allow_boost) {
- for (i = 0; i < aggr_sdelta->temp_band_count; i++) {
- adjust_sdelta = (corner->open_loop_volt
- - aggr_corner->open_loop_volt)
- / step_volt;
- aggr_sdelta->boost_table[i] += adjust_sdelta;
- aggr_sdelta->boost_table[i]
- = min(aggr_sdelta->boost_table[i], 0);
- }
- }
- aggr_corner->open_loop_volt = corner->open_loop_volt;
- aggr_sdelta->allow_temp_adj = sdelta->allow_temp_adj;
- aggr_sdelta->allow_core_count_adj
- = sdelta->allow_core_count_adj;
- aggr_sdelta->max_core_count = sdelta->max_core_count;
- aggr_sdelta->temp_band_count = sdelta->temp_band_count;
- } else if (aggr_corner->open_loop_volt > corner->open_loop_volt) {
-
- aggr_sdelta->cap_volt = min(aggr_sdelta->cap_volt,
- (aggr_corner->open_loop_volt
- - corner->open_loop_volt));
- if (sdelta->allow_boost) {
- for (i = 0; i < aggr_sdelta->temp_band_count; i++) {
- adjust_sdelta = (aggr_corner->open_loop_volt
- - corner->open_loop_volt)
- / step_volt;
- aggr_sdelta->boost_table[i] =
- sdelta->boost_table[i] + adjust_sdelta;
- aggr_sdelta->boost_table[i]
- = min(aggr_sdelta->boost_table[i], 0);
- }
- aggr_sdelta->boost_num_cores = sdelta->boost_num_cores;
- }
- } else {
-
- aggr_sdelta->cap_volt = 0;
- aggr_sdelta->allow_core_count_adj = false;
- if (aggr_sdelta->allow_temp_adj
- && sdelta->allow_temp_adj) {
- aggr_core_count = aggr_sdelta->max_core_count - 1;
- core_count = sdelta->max_core_count - 1;
- temp_band_count = sdelta->temp_band_count;
- for (j = 0; j < temp_band_count; j++) {
- aggr_index = aggr_core_count * temp_band_count
- + j;
- index = core_count * temp_band_count + j;
- aggr_sdelta->table[aggr_index] =
- min(aggr_sdelta->table[aggr_index],
- sdelta->table[index]);
- }
- } else {
- aggr_sdelta->allow_temp_adj = false;
- }
- if (sdelta->allow_boost) {
- memcpy(aggr_sdelta->boost_table, sdelta->boost_table,
- sdelta->temp_band_count
- * sizeof(*sdelta->boost_table));
- aggr_sdelta->boost_num_cores = sdelta->boost_num_cores;
- }
- }
-
- aggr_sdelta->allow_boost |= sdelta->allow_boost;
- if (aggr_sdelta->allow_boost)
- aggr_sdelta->allow_core_count_adj = false;
- if (aggr_sdelta->cap_volt && !(aggr_sdelta->cap_volt == INT_MAX)) {
- core_count = aggr_sdelta->max_core_count;
- temp_band_count = aggr_sdelta->temp_band_count;
-
- cap_steps = aggr_sdelta->cap_volt / step_volt;
- for (i = 0; i < core_count; i++)
- for (j = 0; j < temp_band_count; j++) {
- index = i * temp_band_count + j;
- aggr_sdelta->table[index] =
- min(aggr_sdelta->table[index],
- cap_steps);
- }
- }
- }
- static void cpr3_regulator_aggregate_corners(struct cpr3_corner *aggr_corner,
- const struct cpr3_corner *corner, bool aggr_quot,
- int step_volt)
- {
- int i;
- aggr_corner->ceiling_volt
- = max(aggr_corner->ceiling_volt, corner->ceiling_volt);
- aggr_corner->floor_volt
- = max(aggr_corner->floor_volt, corner->floor_volt);
- aggr_corner->last_volt
- = max(aggr_corner->last_volt, corner->last_volt);
- aggr_corner->system_volt
- = max(aggr_corner->system_volt, corner->system_volt);
- aggr_corner->mem_acc_volt
- = max(aggr_corner->mem_acc_volt, corner->mem_acc_volt);
- aggr_corner->irq_en |= corner->irq_en;
- aggr_corner->use_open_loop |= corner->use_open_loop;
- aggr_corner->ldo_mode_allowed |= corner->ldo_mode_allowed;
- if (aggr_quot) {
- aggr_corner->ro_mask &= corner->ro_mask;
- for (i = 0; i < CPR3_RO_COUNT; i++)
- aggr_corner->target_quot[i]
- = max(aggr_corner->target_quot[i],
- corner->target_quot[i]);
- }
- if (aggr_corner->sdelta && corner->sdelta
- && (aggr_corner->sdelta->table
- || aggr_corner->sdelta->boost_table)) {
- cpr3_regulator_aggregate_sdelta(aggr_corner, corner, step_volt);
- } else {
- aggr_corner->open_loop_volt
- = max(aggr_corner->open_loop_volt,
- corner->open_loop_volt);
- }
- }
- static int _cpr3_regulator_update_ctrl_state(struct cpr3_controller *ctrl)
- {
- struct cpr3_corner aggr_corner = {};
- struct cpr3_thread *thread;
- struct cpr3_regulator *vreg;
- struct cpr4_sdelta *sdelta;
- bool valid = false;
- bool thread_valid;
- int i, j, rc, new_volt, vdd_volt, dynamic_floor_volt;
- int last_corner_volt = 0;
- u32 reg_last_measurement = 0, sdelta_size;
- int *sdelta_table, *boost_table;
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
- rc = cpr3_ctrl_clear_cpr4_config(ctrl);
- if (rc) {
- cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
- rc);
- return rc;
- }
- }
- cpr3_ctrl_loop_disable(ctrl);
- vdd_volt = regulator_get_voltage(ctrl->vdd_regulator);
- if (vdd_volt < 0) {
- cpr3_err(ctrl, "regulator_get_voltage(vdd) failed, rc=%d\n",
- vdd_volt);
- return vdd_volt;
- }
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
-
- last_corner_volt = ctrl->aggr_corner.open_loop_volt;
- }
- if (ctrl->cpr_enabled && ctrl->use_hw_closed_loop &&
- ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3)
- reg_last_measurement
- = cpr3_read(ctrl, CPR3_REG_LAST_MEASUREMENT);
- aggr_corner.sdelta = ctrl->aggr_corner.sdelta;
- if (aggr_corner.sdelta) {
- sdelta = aggr_corner.sdelta;
- sdelta_table = sdelta->table;
- if (sdelta_table) {
- sdelta_size = sdelta->max_core_count *
- sdelta->temp_band_count;
- memset(sdelta_table, 0, sdelta_size
- * sizeof(*sdelta_table));
- }
- boost_table = sdelta->boost_table;
- if (boost_table)
- memset(boost_table, 0, sdelta->temp_band_count
- * sizeof(*boost_table));
- memset(sdelta, 0, sizeof(*sdelta));
- sdelta->table = sdelta_table;
- sdelta->cap_volt = INT_MAX;
- sdelta->boost_table = boost_table;
- }
-
- for (i = 0; i < ctrl->thread_count; i++) {
- thread = &ctrl->thread[i];
- thread_valid = false;
- sdelta = thread->aggr_corner.sdelta;
- if (sdelta) {
- sdelta_table = sdelta->table;
- if (sdelta_table) {
- sdelta_size = sdelta->max_core_count *
- sdelta->temp_band_count;
- memset(sdelta_table, 0, sdelta_size
- * sizeof(*sdelta_table));
- }
- boost_table = sdelta->boost_table;
- if (boost_table)
- memset(boost_table, 0, sdelta->temp_band_count
- * sizeof(*boost_table));
- memset(sdelta, 0, sizeof(*sdelta));
- sdelta->table = sdelta_table;
- sdelta->cap_volt = INT_MAX;
- sdelta->boost_table = boost_table;
- }
- memset(&thread->aggr_corner, 0, sizeof(thread->aggr_corner));
- thread->aggr_corner.sdelta = sdelta;
- thread->aggr_corner.ro_mask = CPR3_RO_MASK;
- for (j = 0; j < thread->vreg_count; j++) {
- vreg = &thread->vreg[j];
- if (ctrl->cpr_enabled && ctrl->use_hw_closed_loop)
- cpr3_update_vreg_closed_loop_volt(vreg,
- vdd_volt, reg_last_measurement);
- if (!vreg->vreg_enabled
- || vreg->current_corner
- == CPR3_REGULATOR_CORNER_INVALID) {
-
- vreg->aggregated = false;
- continue;
- } else {
- vreg->aggregated = true;
- thread_valid = true;
- }
- cpr3_regulator_aggregate_corners(&thread->aggr_corner,
- &vreg->corner[vreg->current_corner],
- true, ctrl->step_volt);
- }
- valid |= thread_valid;
- if (thread_valid)
- cpr3_regulator_aggregate_corners(&aggr_corner,
- &thread->aggr_corner,
- false, ctrl->step_volt);
- }
- if (valid && ctrl->cpr_allowed_hw && ctrl->cpr_allowed_sw) {
- rc = cpr3_closed_loop_enable(ctrl);
- if (rc) {
- cpr3_err(ctrl, "could not enable CPR, rc=%d\n", rc);
- return rc;
- }
- } else {
- rc = cpr3_closed_loop_disable(ctrl);
- if (rc) {
- cpr3_err(ctrl, "could not disable CPR, rc=%d\n", rc);
- return rc;
- }
- }
-
- if (!valid)
- return 0;
-
- if (ctrl->use_hw_closed_loop
- && aggr_corner.ceiling_volt >= ctrl->apm_threshold_volt
- && aggr_corner.floor_volt < ctrl->apm_threshold_volt) {
- if (aggr_corner.open_loop_volt
- >= ctrl->apm_threshold_volt - ctrl->apm_adj_volt)
- aggr_corner.floor_volt = ctrl->apm_threshold_volt;
- else
- aggr_corner.ceiling_volt
- = ctrl->apm_threshold_volt - ctrl->step_volt;
- aggr_corner.last_volt
- = max(aggr_corner.last_volt, aggr_corner.floor_volt);
- aggr_corner.last_volt
- = min(aggr_corner.last_volt, aggr_corner.ceiling_volt);
- aggr_corner.open_loop_volt
- = max(aggr_corner.open_loop_volt, aggr_corner.floor_volt);
- aggr_corner.open_loop_volt
- = min(aggr_corner.open_loop_volt, aggr_corner.ceiling_volt);
- }
- if (ctrl->use_hw_closed_loop
- && aggr_corner.ceiling_volt >= ctrl->mem_acc_threshold_volt
- && aggr_corner.floor_volt < ctrl->mem_acc_threshold_volt) {
- aggr_corner.floor_volt = ctrl->mem_acc_threshold_volt;
- aggr_corner.last_volt = max(aggr_corner.last_volt,
- aggr_corner.floor_volt);
- aggr_corner.open_loop_volt = max(aggr_corner.open_loop_volt,
- aggr_corner.floor_volt);
- }
- if (ctrl->use_hw_closed_loop) {
- dynamic_floor_volt
- = cpr3_regulator_get_dynamic_floor_volt(ctrl,
- reg_last_measurement);
- if (aggr_corner.floor_volt < dynamic_floor_volt) {
- aggr_corner.floor_volt = dynamic_floor_volt;
- aggr_corner.last_volt = max(aggr_corner.last_volt,
- aggr_corner.floor_volt);
- aggr_corner.open_loop_volt
- = max(aggr_corner.open_loop_volt,
- aggr_corner.floor_volt);
- aggr_corner.ceiling_volt = max(aggr_corner.ceiling_volt,
- aggr_corner.floor_volt);
- }
- }
- if (ctrl->cpr_enabled && ctrl->last_corner_was_closed_loop) {
-
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3)
- new_volt = aggr_corner.last_volt;
- else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4
- && ctrl->supports_hw_closed_loop)
- new_volt = aggr_corner.open_loop_volt;
- else
- new_volt = min(aggr_corner.last_volt +
- cpr3_regulator_max_sdelta_diff(aggr_corner.sdelta,
- ctrl->step_volt),
- aggr_corner.ceiling_volt);
- } else {
- new_volt = aggr_corner.open_loop_volt;
- aggr_corner.last_volt = aggr_corner.open_loop_volt;
- }
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4
- && ctrl->supports_hw_closed_loop) {
-
- vdd_volt = last_corner_volt;
- }
- cpr3_debug(ctrl, "setting new voltage=%d uV\n", new_volt);
- rc = cpr3_regulator_scale_vdd_voltage(ctrl, new_volt,
- vdd_volt, &aggr_corner);
- if (rc) {
- cpr3_err(ctrl, "vdd voltage scaling failed, rc=%d\n", rc);
- return rc;
- }
-
- if (ctrl->cpr_enabled) {
- if (ctrl->use_hw_closed_loop) {
-
-
- rc = regulator_set_voltage(ctrl->vdd_limit_regulator,
- aggr_corner.floor_volt,
- aggr_corner.ceiling_volt);
- if (rc) {
- cpr3_err(ctrl, "could not configure HW closed-loop voltage limits, rc=%d\n",
- rc);
- return rc;
- }
- } else {
-
-
- if (new_volt == aggr_corner.floor_volt)
- aggr_corner.irq_en &= ~CPR3_IRQ_DOWN;
- if (new_volt == aggr_corner.ceiling_volt)
- aggr_corner.irq_en &= ~CPR3_IRQ_UP;
- cpr3_write(ctrl, CPR3_REG_IRQ_CLEAR,
- CPR3_IRQ_UP | CPR3_IRQ_DOWN);
- cpr3_write(ctrl, CPR3_REG_IRQ_EN, aggr_corner.irq_en);
- }
- for (i = 0; i < ctrl->thread_count; i++) {
- cpr3_regulator_set_target_quot(&ctrl->thread[i]);
- for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
- vreg = &ctrl->thread[i].vreg[j];
- if (vreg->vreg_enabled)
- vreg->last_closed_loop_corner
- = vreg->current_corner;
- }
- }
- if (ctrl->proc_clock_throttle) {
- if (aggr_corner.ceiling_volt > aggr_corner.floor_volt
- && (ctrl->use_hw_closed_loop
- || new_volt < aggr_corner.ceiling_volt))
- cpr3_write(ctrl, CPR3_REG_PD_THROTTLE,
- ctrl->proc_clock_throttle);
- else
- cpr3_write(ctrl, CPR3_REG_PD_THROTTLE,
- CPR3_PD_THROTTLE_DISABLE);
- }
-
- wmb();
- } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4
- && ctrl->vdd_limit_regulator) {
-
- rc = regulator_set_voltage(ctrl->vdd_limit_regulator,
- aggr_corner.floor_volt,
- aggr_corner.ceiling_volt);
- if (rc) {
- cpr3_err(ctrl, "could not configure HW closed-loop voltage limits, rc=%d\n",
- rc);
- return rc;
- }
- }
- ctrl->aggr_corner = aggr_corner;
- if (ctrl->allow_core_count_adj || ctrl->allow_temp_adj
- || ctrl->allow_boost) {
- rc = cpr3_controller_program_sdelta(ctrl);
- if (rc) {
- cpr3_err(ctrl, "failed to program sdelta, rc=%d\n", rc);
- return rc;
- }
- }
-
- if (aggr_corner.ceiling_volt > aggr_corner.floor_volt &&
- !aggr_corner.use_open_loop)
- cpr3_ctrl_loop_enable(ctrl);
- ctrl->last_corner_was_closed_loop = ctrl->cpr_enabled;
- cpr3_debug(ctrl, "CPR configuration updated\n");
- return 0;
- }
- static int cpr3_regulator_wait_for_idle(struct cpr3_controller *ctrl,
- s64 max_wait_ns)
- {
- ktime_t start, end;
- s64 time_ns;
- u32 reg;
-
- mb();
- start = ktime_get();
- do {
- end = ktime_get();
- time_ns = ktime_to_ns(ktime_sub(end, start));
- if (time_ns > max_wait_ns) {
- cpr3_err(ctrl, "CPR controller still busy after %lld us\n",
- div_s64(time_ns, 1000));
- return -ETIMEDOUT;
- }
- usleep_range(50, 100);
- reg = cpr3_read(ctrl, CPR3_REG_CPR_STATUS);
- } while (reg & CPR3_CPR_STATUS_BUSY_MASK);
- return 0;
- }
- static int cmp_int(const void *a, const void *b)
- {
- return *(int *)a - *(int *)b;
- }
- static int cpr3_regulator_measure_aging(struct cpr3_controller *ctrl,
- struct cpr3_aging_sensor_info *aging_sensor)
- {
- u32 mask, reg, result, quot_min, quot_max, sel_min, sel_max;
- u32 quot_min_scaled, quot_max_scaled;
- u32 gcnt, gcnt_ref, gcnt0_restore, gcnt1_restore, irq_restore;
- u32 ro_mask_restore, cont_dly_restore, up_down_dly_restore = 0;
- int quot_delta, quot_delta_scaled, quot_delta_scaled_sum;
- int *quot_delta_results;
- int rc, rc2, i, aging_measurement_count, filtered_count;
- bool is_aging_measurement;
- quot_delta_results = kcalloc(CPR3_AGING_MEASUREMENT_ITERATIONS,
- sizeof(*quot_delta_results), GFP_KERNEL);
- if (!quot_delta_results)
- return -ENOMEM;
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
- rc = cpr3_ctrl_clear_cpr4_config(ctrl);
- if (rc) {
- cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
- rc);
- kfree(quot_delta_results);
- return rc;
- }
- }
- cpr3_ctrl_loop_disable(ctrl);
-
- irq_restore = cpr3_read(ctrl, CPR3_REG_IRQ_EN);
- cpr3_write(ctrl, CPR3_REG_IRQ_EN,
- CPR3_IRQ_UP | CPR3_IRQ_DOWN | CPR3_IRQ_MID);
-
- cpr3_write(ctrl, CPR3_REG_SENSOR_OWNER(aging_sensor->sensor_id), 0);
-
- if (ctrl->supports_hw_closed_loop) {
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4 ||
- ctrl->ctrl_type == CPR_CTRL_TYPE_CPRH) {
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
- CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK,
- CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE);
- } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
- cpr3_write(ctrl, CPR3_REG_HW_CLOSED_LOOP,
- CPR3_HW_CLOSED_LOOP_DISABLE);
- }
- }
-
- gcnt0_restore = cpr3_read(ctrl, CPR3_REG_GCNT(0));
- gcnt1_restore = cpr3_read(ctrl, CPR3_REG_GCNT(1));
- gcnt_ref = cpr3_regulator_get_gcnt(ctrl);
- gcnt = gcnt_ref * 3 / 2;
- cpr3_write(ctrl, CPR3_REG_GCNT(0), gcnt);
- cpr3_write(ctrl, CPR3_REG_GCNT(1), gcnt);
-
- ro_mask_restore = cpr3_read(ctrl, CPR3_REG_RO_MASK(0));
- cpr3_write(ctrl, CPR3_REG_RO_MASK(0), 0);
-
- for (i = 0; i <= ctrl->sensor_count / 32; i++) {
- mask = GENMASK(min(31, ctrl->sensor_count - i * 32), 0);
- if (aging_sensor->sensor_id / 32 >= i
- && aging_sensor->sensor_id / 32 < (i + 1))
- mask &= ~BIT(aging_sensor->sensor_id % 32);
- cpr3_write(ctrl, CPR3_REG_SENSOR_MASK_WRITE_BANK(i), mask);
- cpr3_write(ctrl, CPR3_REG_SENSOR_BYPASS_WRITE_BANK(i),
- aging_sensor->bypass_mask[i]);
- }
-
- if (ctrl->supports_hw_closed_loop
- && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
- cont_dly_restore = cpr3_read(ctrl, CPR3_REG_CPR_TIMER_MID_CONT);
- up_down_dly_restore = cpr3_read(ctrl,
- CPR3_REG_CPR_TIMER_UP_DN_CONT);
- cpr3_write(ctrl, CPR3_REG_CPR_TIMER_MID_CONT, 0);
- cpr3_write(ctrl, CPR3_REG_CPR_TIMER_UP_DN_CONT, 0);
- } else {
- cont_dly_restore = cpr3_read(ctrl,
- CPR3_REG_CPR_TIMER_AUTO_CONT);
- cpr3_write(ctrl, CPR3_REG_CPR_TIMER_AUTO_CONT, 0);
- }
-
- cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL,
- CPR3_CPR_CTL_COUNT_MODE_MASK | CPR3_CPR_CTL_COUNT_REPEAT_MASK,
- CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_MIN
- << CPR3_CPR_CTL_COUNT_MODE_SHIFT);
- cpr3_ctrl_loop_enable(ctrl);
- rc = cpr3_regulator_wait_for_idle(ctrl,
- CPR3_AGING_MEASUREMENT_TIMEOUT_NS);
- if (rc)
- goto cleanup;
-
- cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL, CPR3_CPR_CTL_COUNT_MODE_MASK,
- CPR3_CPR_CTL_COUNT_MODE_ALL_AT_ONCE_AGE
- << CPR3_CPR_CTL_COUNT_MODE_SHIFT);
- aging_measurement_count = 0;
- for (i = 0; i < CPR3_AGING_MEASUREMENT_ITERATIONS; i++) {
-
- cpr3_write(ctrl, CPR3_REG_CONT_CMD, CPR3_CONT_CMD_NACK);
- rc = cpr3_regulator_wait_for_idle(ctrl,
- CPR3_AGING_MEASUREMENT_TIMEOUT_NS);
- if (rc)
- goto cleanup;
-
- reg = cpr3_read(ctrl, CPR3_REG_CPR_STATUS);
- is_aging_measurement
- = reg & CPR3_CPR_STATUS_AGING_MEASUREMENT_MASK;
-
- result = cpr3_read(ctrl, CPR3_REG_RESULT1(0));
- quot_min = (result & CPR3_RESULT1_QUOT_MIN_MASK)
- >> CPR3_RESULT1_QUOT_MIN_SHIFT;
- quot_max = (result & CPR3_RESULT1_QUOT_MAX_MASK)
- >> CPR3_RESULT1_QUOT_MAX_SHIFT;
- sel_min = (result & CPR3_RESULT1_RO_MIN_MASK)
- >> CPR3_RESULT1_RO_MIN_SHIFT;
- sel_max = (result & CPR3_RESULT1_RO_MAX_MASK)
- >> CPR3_RESULT1_RO_MAX_SHIFT;
-
- quot_min_scaled = quot_min * (gcnt_ref + 1) / (gcnt + 1);
- quot_max_scaled = quot_max * (gcnt_ref + 1) / (gcnt + 1);
- if (sel_max == 1) {
- quot_delta = quot_max - quot_min;
- quot_delta_scaled = quot_max_scaled - quot_min_scaled;
- } else {
- quot_delta = quot_min - quot_max;
- quot_delta_scaled = quot_min_scaled - quot_max_scaled;
- }
- if (is_aging_measurement)
- quot_delta_results[aging_measurement_count++]
- = quot_delta_scaled;
- 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",
- is_aging_measurement, sel_min, sel_max, quot_min,
- quot_max, quot_delta, quot_min_scaled, quot_max_scaled,
- quot_delta_scaled);
- }
- filtered_count
- = aging_measurement_count - CPR3_AGING_MEASUREMENT_FILTER * 2;
- if (filtered_count > 0) {
- sort(quot_delta_results, aging_measurement_count,
- sizeof(*quot_delta_results), cmp_int, NULL);
- quot_delta_scaled_sum = 0;
- for (i = 0; i < filtered_count; i++)
- quot_delta_scaled_sum
- += quot_delta_results[i
- + CPR3_AGING_MEASUREMENT_FILTER];
- aging_sensor->measured_quot_diff
- = quot_delta_scaled_sum / filtered_count;
- cpr3_info(ctrl, "average quotient delta=%d (count=%d)\n",
- aging_sensor->measured_quot_diff,
- filtered_count);
- } else {
- cpr3_err(ctrl, "%d aging measurements completed after %d iterations\n",
- aging_measurement_count,
- CPR3_AGING_MEASUREMENT_ITERATIONS);
- rc = -EBUSY;
- }
- cleanup:
- kfree(quot_delta_results);
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
- rc2 = cpr3_ctrl_clear_cpr4_config(ctrl);
- if (rc2) {
- cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
- rc2);
- rc = rc2;
- }
- }
- cpr3_ctrl_loop_disable(ctrl);
- cpr3_write(ctrl, CPR3_REG_IRQ_EN, irq_restore);
- cpr3_write(ctrl, CPR3_REG_RO_MASK(0), ro_mask_restore);
- cpr3_write(ctrl, CPR3_REG_GCNT(0), gcnt0_restore);
- cpr3_write(ctrl, CPR3_REG_GCNT(1), gcnt1_restore);
- if (ctrl->supports_hw_closed_loop
- && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
- cpr3_write(ctrl, CPR3_REG_CPR_TIMER_MID_CONT, cont_dly_restore);
- cpr3_write(ctrl, CPR3_REG_CPR_TIMER_UP_DN_CONT,
- up_down_dly_restore);
- } else {
- cpr3_write(ctrl, CPR3_REG_CPR_TIMER_AUTO_CONT,
- cont_dly_restore);
- }
- for (i = 0; i <= ctrl->sensor_count / 32; i++) {
- cpr3_write(ctrl, CPR3_REG_SENSOR_MASK_WRITE_BANK(i), 0);
- cpr3_write(ctrl, CPR3_REG_SENSOR_BYPASS_WRITE_BANK(i), 0);
- }
- cpr3_masked_write(ctrl, CPR3_REG_CPR_CTL,
- CPR3_CPR_CTL_COUNT_MODE_MASK | CPR3_CPR_CTL_COUNT_REPEAT_MASK,
- (ctrl->count_mode << CPR3_CPR_CTL_COUNT_MODE_SHIFT)
- | (ctrl->count_repeat << CPR3_CPR_CTL_COUNT_REPEAT_SHIFT));
- cpr3_write(ctrl, CPR3_REG_SENSOR_OWNER(aging_sensor->sensor_id),
- ctrl->sensor_owner[aging_sensor->sensor_id]);
- cpr3_write(ctrl, CPR3_REG_IRQ_CLEAR,
- CPR3_IRQ_UP | CPR3_IRQ_DOWN | CPR3_IRQ_MID);
- if (ctrl->supports_hw_closed_loop) {
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4 ||
- ctrl->ctrl_type == CPR_CTRL_TYPE_CPRH) {
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
- CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK,
- ctrl->use_hw_closed_loop
- ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE
- : CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE);
- } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
- cpr3_write(ctrl, CPR3_REG_HW_CLOSED_LOOP,
- ctrl->use_hw_closed_loop
- ? CPR3_HW_CLOSED_LOOP_ENABLE
- : CPR3_HW_CLOSED_LOOP_DISABLE);
- }
- }
- return rc;
- }
- static void cpr3_regulator_readjust_volt_and_quot(struct cpr3_regulator *vreg,
- int old_adjust_volt, int new_adjust_volt)
- {
- unsigned long long temp;
- int i, j, old_volt, new_volt, rounded_volt;
- if (!vreg->aging_allowed)
- return;
- for (i = 0; i < vreg->corner_count; i++) {
- temp = (unsigned long long)old_adjust_volt
- * (unsigned long long)vreg->corner[i].aging_derate;
- do_div(temp, 1000);
- old_volt = temp;
- temp = (unsigned long long)new_adjust_volt
- * (unsigned long long)vreg->corner[i].aging_derate;
- do_div(temp, 1000);
- new_volt = temp;
- old_volt = min(vreg->aging_max_adjust_volt, old_volt);
- new_volt = min(vreg->aging_max_adjust_volt, new_volt);
- for (j = 0; j < CPR3_RO_COUNT; j++) {
- if (vreg->corner[i].target_quot[j] != 0) {
- vreg->corner[i].target_quot[j]
- += cpr3_quot_adjustment(
- vreg->corner[i].ro_scale[j],
- new_volt)
- - cpr3_quot_adjustment(
- vreg->corner[i].ro_scale[j],
- old_volt);
- }
- }
- rounded_volt = CPR3_ROUND(new_volt,
- vreg->thread->ctrl->step_volt);
- if (!vreg->aging_allow_open_loop_adj)
- rounded_volt = 0;
- vreg->corner[i].ceiling_volt
- = vreg->corner[i].unaged_ceiling_volt + rounded_volt;
- vreg->corner[i].ceiling_volt = min(vreg->corner[i].ceiling_volt,
- vreg->corner[i].abs_ceiling_volt);
- vreg->corner[i].floor_volt
- = vreg->corner[i].unaged_floor_volt + rounded_volt;
- vreg->corner[i].floor_volt = min(vreg->corner[i].floor_volt,
- vreg->corner[i].ceiling_volt);
- vreg->corner[i].open_loop_volt
- = vreg->corner[i].unaged_open_loop_volt + rounded_volt;
- vreg->corner[i].open_loop_volt
- = min(vreg->corner[i].open_loop_volt,
- vreg->corner[i].ceiling_volt);
- vreg->corner[i].last_volt = vreg->corner[i].open_loop_volt;
- cpr3_debug(vreg, "corner %d: applying %d uV closed-loop and %d uV open-loop voltage margin adjustment\n",
- i, new_volt, rounded_volt);
- }
- }
- static void cpr3_regulator_set_aging_ref_adjustment(
- struct cpr3_controller *ctrl, int ref_adjust_volt)
- {
- struct cpr3_regulator *vreg;
- int i, j;
- for (i = 0; i < ctrl->thread_count; i++) {
- for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
- vreg = &ctrl->thread[i].vreg[j];
- cpr3_regulator_readjust_volt_and_quot(vreg,
- ctrl->aging_ref_adjust_volt, ref_adjust_volt);
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPRH)
- cprh_adjust_voltages_for_apm(vreg);
- }
- }
- ctrl->aging_ref_adjust_volt = ref_adjust_volt;
- }
- static int cpr3_regulator_aging_adjust(struct cpr3_controller *ctrl)
- {
- struct cpr3_regulator *vreg;
- struct cpr3_corner restore_aging_corner;
- struct cpr3_corner *corner;
- int *restore_current_corner;
- bool *restore_vreg_enabled;
- int i, j, id, rc, rc2, vreg_count, aging_volt, max_aging_volt = 0;
- u32 reg;
- if (!ctrl->aging_required || !ctrl->cpr_enabled
- || ctrl->aggr_corner.ceiling_volt == 0
- || ctrl->aggr_corner.ceiling_volt > ctrl->aging_ref_volt)
- return 0;
- for (i = 0, vreg_count = 0; i < ctrl->thread_count; i++) {
- for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
- vreg = &ctrl->thread[i].vreg[j];
- vreg_count++;
- if (vreg->aging_allowed && vreg->vreg_enabled
- && vreg->current_corner > vreg->aging_corner)
- return 0;
- }
- }
-
- for (i = 0; i < ctrl->aging_sensor_count; i++) {
- id = ctrl->aging_sensor[i].sensor_id;
- reg = cpr3_read(ctrl, CPR3_REG_SENSOR_MASK_READ(id));
- if (reg & BIT(id % 32))
- return 0;
- }
-
- if (ctrl->aging_possible_reg) {
- reg = readl_relaxed(ctrl->aging_possible_reg);
- reg &= ctrl->aging_possible_mask;
- if (reg != ctrl->aging_possible_val)
- return 0;
- }
- restore_current_corner = kcalloc(vreg_count,
- sizeof(*restore_current_corner), GFP_KERNEL);
- restore_vreg_enabled = kcalloc(vreg_count,
- sizeof(*restore_vreg_enabled), GFP_KERNEL);
- if (!restore_current_corner || !restore_vreg_enabled) {
- kfree(restore_current_corner);
- kfree(restore_vreg_enabled);
- return -ENOMEM;
- }
-
- for (i = 0, vreg_count = 0; i < ctrl->thread_count; i++) {
- for (j = 0; j < ctrl->thread[i].vreg_count; j++, vreg_count++) {
- vreg = &ctrl->thread[i].vreg[j];
- restore_current_corner[vreg_count]
- = vreg->current_corner;
- restore_vreg_enabled[vreg_count]
- = vreg->vreg_enabled;
- vreg->current_corner = vreg->aging_corner;
- vreg->vreg_enabled = true;
- }
- }
-
- vreg = &ctrl->thread[0].vreg[0];
- corner = &vreg->corner[vreg->current_corner];
- restore_aging_corner = *corner;
- corner->ceiling_volt = ctrl->aging_ref_volt;
- corner->floor_volt = ctrl->aging_ref_volt;
- corner->open_loop_volt = ctrl->aging_ref_volt;
- corner->last_volt = ctrl->aging_ref_volt;
-
- ctrl->last_corner_was_closed_loop = false;
-
- rc = _cpr3_regulator_update_ctrl_state(ctrl);
- if (rc) {
- cpr3_err(ctrl, "unable to force vdd-supply to the aging reference voltage=%d uV, rc=%d\n",
- ctrl->aging_ref_volt, rc);
- goto cleanup;
- }
- if (ctrl->aging_vdd_mode) {
- rc = regulator_set_mode(ctrl->vdd_regulator,
- ctrl->aging_vdd_mode);
- if (rc) {
- cpr3_err(ctrl, "unable to configure vdd-supply for mode=%u, rc=%d\n",
- ctrl->aging_vdd_mode, rc);
- goto cleanup;
- }
- }
-
- for (i = 0; i < ctrl->aging_sensor_count; i++) {
- for (j = 0; j < CPR3_AGING_RETRY_COUNT; j++) {
- rc = cpr3_regulator_measure_aging(ctrl,
- &ctrl->aging_sensor[i]);
- if (!rc)
- break;
- }
- if (!rc) {
- aging_volt =
- cpr3_voltage_adjustment(
- ctrl->aging_sensor[i].ro_scale,
- ctrl->aging_sensor[i].measured_quot_diff
- - ctrl->aging_sensor[i].init_quot_diff);
- max_aging_volt = max(max_aging_volt, aging_volt);
- } else {
- cpr3_err(ctrl, "CPR aging measurement failed after %d tries, rc=%d\n",
- j, rc);
- ctrl->aging_failed = true;
- ctrl->aging_required = false;
- goto cleanup;
- }
- }
- cleanup:
- vreg = &ctrl->thread[0].vreg[0];
- vreg->corner[vreg->current_corner] = restore_aging_corner;
- for (i = 0, vreg_count = 0; i < ctrl->thread_count; i++) {
- for (j = 0; j < ctrl->thread[i].vreg_count; j++, vreg_count++) {
- vreg = &ctrl->thread[i].vreg[j];
- vreg->current_corner
- = restore_current_corner[vreg_count];
- vreg->vreg_enabled = restore_vreg_enabled[vreg_count];
- }
- }
- kfree(restore_current_corner);
- kfree(restore_vreg_enabled);
-
- if (!rc) {
- cpr3_regulator_set_aging_ref_adjustment(ctrl, max_aging_volt);
- cpr3_info(ctrl, "aging measurement successful; aging reference adjustment voltage=%d uV\n",
- ctrl->aging_ref_adjust_volt);
- ctrl->aging_succeeded = true;
- ctrl->aging_required = false;
- }
- if (ctrl->aging_complete_vdd_mode) {
- rc = regulator_set_mode(ctrl->vdd_regulator,
- ctrl->aging_complete_vdd_mode);
- if (rc)
- cpr3_err(ctrl, "unable to configure vdd-supply for mode=%u, rc=%d\n",
- ctrl->aging_complete_vdd_mode, rc);
- }
-
- ctrl->last_corner_was_closed_loop = false;
-
- rc2 = _cpr3_regulator_update_ctrl_state(ctrl);
-
- ctrl->last_corner_was_closed_loop = false;
- return rc ? rc : rc2;
- }
- static int cprh_regulator_aging_adjust(struct cpr3_controller *ctrl)
- {
- int i, j, id, rc, rc2, aging_volt, init_volt;
- int max_aging_volt = 0;
- u32 reg;
- if (!ctrl->aging_required || !ctrl->cpr_enabled)
- return 0;
- if (!ctrl->vdd_regulator) {
- cpr3_err(ctrl, "vdd-supply regulator missing\n");
- return -ENODEV;
- }
- init_volt = regulator_get_voltage(ctrl->vdd_regulator);
- if (init_volt < 0) {
- cpr3_err(ctrl, "could not get vdd-supply voltage, rc=%d\n",
- init_volt);
- return init_volt;
- }
- if (init_volt > ctrl->aging_ref_volt) {
- cpr3_info(ctrl, "unable to perform CPR aging measurement as vdd=%d uV > aging voltage=%d uV\n",
- init_volt, ctrl->aging_ref_volt);
- return 0;
- }
-
- for (i = 0; i < ctrl->aging_sensor_count; i++) {
- id = ctrl->aging_sensor[i].sensor_id;
- reg = cpr3_read(ctrl, CPR3_REG_SENSOR_MASK_READ(id));
- if (reg & BIT(id % 32)) {
- cpr3_info(ctrl, "unable to perform CPR aging measurement as CPR sensor %d is masked\n",
- id);
- return 0;
- }
- }
- rc = regulator_set_voltage(ctrl->vdd_regulator, ctrl->aging_ref_volt,
- INT_MAX);
- if (rc) {
- cpr3_err(ctrl, "unable to set vdd-supply to aging voltage=%d uV, rc=%d\n",
- ctrl->aging_ref_volt, rc);
- return rc;
- }
- if (ctrl->aging_vdd_mode) {
- rc = regulator_set_mode(ctrl->vdd_regulator,
- ctrl->aging_vdd_mode);
- if (rc) {
- cpr3_err(ctrl, "unable to configure vdd-supply for mode=%u, rc=%d\n",
- ctrl->aging_vdd_mode, rc);
- goto cleanup;
- }
- }
-
- for (i = 0; i < ctrl->aging_sensor_count; i++) {
- for (j = 0; j < CPR3_AGING_RETRY_COUNT; j++) {
- rc = cpr3_regulator_measure_aging(ctrl,
- &ctrl->aging_sensor[i]);
- if (!rc)
- break;
- }
- if (!rc) {
- aging_volt =
- cpr3_voltage_adjustment(
- ctrl->aging_sensor[i].ro_scale,
- ctrl->aging_sensor[i].measured_quot_diff
- - ctrl->aging_sensor[i].init_quot_diff);
- max_aging_volt = max(max_aging_volt, aging_volt);
- } else {
- cpr3_err(ctrl, "CPR aging measurement failed after %d tries, rc=%d\n",
- j, rc);
- ctrl->aging_failed = true;
- ctrl->aging_required = false;
- goto cleanup;
- }
- }
- cleanup:
-
- if (!rc) {
- cpr3_regulator_set_aging_ref_adjustment(ctrl, max_aging_volt);
- cpr3_info(ctrl, "aging measurement successful; aging reference adjustment voltage=%d uV\n",
- ctrl->aging_ref_adjust_volt);
- ctrl->aging_succeeded = true;
- ctrl->aging_required = false;
- }
- rc2 = regulator_set_voltage(ctrl->vdd_regulator, init_volt, INT_MAX);
- if (rc2) {
- cpr3_err(ctrl, "unable to reset vdd-supply to initial voltage=%d uV, rc=%d\n",
- init_volt, rc2);
- return rc2;
- }
- if (ctrl->aging_complete_vdd_mode) {
- rc2 = regulator_set_mode(ctrl->vdd_regulator,
- ctrl->aging_complete_vdd_mode);
- if (rc2) {
- cpr3_err(ctrl, "unable to configure vdd-supply for mode=%u, rc=%d\n",
- ctrl->aging_complete_vdd_mode, rc2);
- return rc2;
- }
- }
- return rc;
- }
- static int cpr3_regulator_update_ctrl_state(struct cpr3_controller *ctrl)
- {
- int rc;
- rc = _cpr3_regulator_update_ctrl_state(ctrl);
- if (rc)
- return rc;
- return cpr3_regulator_aging_adjust(ctrl);
- }
- static int cpr3_regulator_set_voltage(struct regulator_dev *rdev,
- int corner, int corner_max, unsigned int *selector)
- {
- struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
- struct cpr3_controller *ctrl = vreg->thread->ctrl;
- int rc = 0;
- int last_corner;
- corner -= CPR3_CORNER_OFFSET;
- corner_max -= CPR3_CORNER_OFFSET;
- *selector = corner;
- mutex_lock(&ctrl->lock);
- if (!vreg->vreg_enabled) {
- vreg->current_corner = corner;
- cpr3_debug(vreg, "stored corner=%d\n", corner);
- goto done;
- } else if (vreg->current_corner == corner) {
- goto done;
- }
- last_corner = vreg->current_corner;
- vreg->current_corner = corner;
- rc = cpr3_regulator_update_ctrl_state(ctrl);
- if (rc) {
- cpr3_err(vreg, "could not update CPR state, rc=%d\n", rc);
- vreg->current_corner = last_corner;
- }
- cpr3_debug(vreg, "set corner=%d\n", corner);
- done:
- mutex_unlock(&ctrl->lock);
- return rc;
- }
- static int cpr3_regulator_get_voltage(struct regulator_dev *rdev)
- {
- struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
- if (vreg->current_corner == CPR3_REGULATOR_CORNER_INVALID)
- return CPR3_CORNER_OFFSET;
- else
- return vreg->current_corner + CPR3_CORNER_OFFSET;
- }
- static int cpr3_regulator_list_voltage(struct regulator_dev *rdev,
- unsigned int selector)
- {
- struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
- if (selector < vreg->corner_count)
- return selector + CPR3_CORNER_OFFSET;
- else
- return 0;
- }
- static int cpr3_regulator_list_corner_voltage(struct regulator_dev *rdev,
- int corner)
- {
- struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
- corner -= CPR3_CORNER_OFFSET;
- if (corner >= 0 && corner < vreg->corner_count)
- return vreg->corner[corner].ceiling_volt;
- else
- return -EINVAL;
- }
- static int cpr3_regulator_is_enabled(struct regulator_dev *rdev)
- {
- struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
- return vreg->vreg_enabled;
- }
- static int cpr3_regulator_enable(struct regulator_dev *rdev)
- {
- struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
- struct cpr3_controller *ctrl = vreg->thread->ctrl;
- int rc = 0;
- if (vreg->vreg_enabled == true)
- return 0;
- mutex_lock(&ctrl->lock);
- if (ctrl->system_regulator) {
- rc = regulator_enable(ctrl->system_regulator);
- if (rc) {
- cpr3_err(ctrl, "regulator_enable(system) failed, rc=%d\n",
- rc);
- goto done;
- }
- }
- rc = regulator_enable(ctrl->vdd_regulator);
- if (rc) {
- cpr3_err(vreg, "regulator_enable(vdd) failed, rc=%d\n", rc);
- goto done;
- }
- if (vreg->ldo_regulator) {
- rc = regulator_enable(vreg->ldo_regulator);
- if (rc) {
- cpr3_err(vreg, "regulator_enable(ldo) failed, rc=%d\n",
- rc);
- goto done;
- }
- }
- vreg->vreg_enabled = true;
- rc = cpr3_regulator_update_ctrl_state(ctrl);
- if (rc) {
- cpr3_err(vreg, "could not update CPR state, rc=%d\n", rc);
- regulator_disable(ctrl->vdd_regulator);
- vreg->vreg_enabled = false;
- goto done;
- }
- cpr3_debug(vreg, "Enabled\n");
- done:
- mutex_unlock(&ctrl->lock);
- return rc;
- }
- static int cpr3_regulator_disable(struct regulator_dev *rdev)
- {
- struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
- struct cpr3_controller *ctrl = vreg->thread->ctrl;
- int rc, rc2;
- if (vreg->vreg_enabled == false)
- return 0;
- mutex_lock(&ctrl->lock);
- if (vreg->ldo_regulator && vreg->ldo_regulator_bypass == LDO_MODE) {
- rc = regulator_get_voltage(ctrl->vdd_regulator);
- if (rc < 0) {
- cpr3_err(vreg, "regulator_get_voltage(vdd) failed, rc=%d\n",
- rc);
- goto done;
- }
-
- rc = cpr3_regulator_set_bhs_mode(vreg, rc,
- ctrl->aggr_corner.ceiling_volt);
- if (rc) {
- cpr3_err(vreg, "unable to switch to BHS mode, rc=%d\n",
- rc);
- goto done;
- }
- }
- if (vreg->ldo_regulator) {
- rc = regulator_disable(vreg->ldo_regulator);
- if (rc) {
- cpr3_err(vreg, "regulator_disable(ldo) failed, rc=%d\n",
- rc);
- goto done;
- }
- }
- rc = regulator_disable(ctrl->vdd_regulator);
- if (rc) {
- cpr3_err(vreg, "regulator_disable(vdd) failed, rc=%d\n", rc);
- goto done;
- }
- vreg->vreg_enabled = false;
- rc = cpr3_regulator_update_ctrl_state(ctrl);
- if (rc) {
- cpr3_err(vreg, "could not update CPR state, rc=%d\n", rc);
- rc2 = regulator_enable(ctrl->vdd_regulator);
- vreg->vreg_enabled = true;
- goto done;
- }
- if (ctrl->system_regulator) {
- rc = regulator_disable(ctrl->system_regulator);
- if (rc) {
- cpr3_err(ctrl, "regulator_disable(system) failed, rc=%d\n",
- rc);
- goto done;
- }
- if (ctrl->support_ldo300_vreg) {
- rc = regulator_set_voltage(ctrl->system_regulator, 0,
- INT_MAX);
- if (rc)
- cpr3_err(ctrl, "failed to set voltage on system rc=%d\n",
- rc);
- goto done;
- }
- }
- cpr3_debug(vreg, "Disabled\n");
- done:
- mutex_unlock(&ctrl->lock);
- return rc;
- }
- static struct regulator_ops cpr3_regulator_ops = {
- .enable = cpr3_regulator_enable,
- .disable = cpr3_regulator_disable,
- .is_enabled = cpr3_regulator_is_enabled,
- .set_voltage = cpr3_regulator_set_voltage,
- .get_voltage = cpr3_regulator_get_voltage,
- .list_voltage = cpr3_regulator_list_voltage,
- .list_corner_voltage = cpr3_regulator_list_corner_voltage,
- };
- static int cprh_regulator_get_voltage(struct regulator_dev *rdev)
- {
- struct cpr3_regulator *vreg = rdev_get_drvdata(rdev);
- struct cpr3_controller *ctrl = vreg->thread->ctrl;
- bool cpr_enabled;
- u32 reg, rc;
- mutex_lock(&ctrl->lock);
- cpr_enabled = ctrl->cpr_enabled;
- if (!cpr_enabled) {
- rc = cpr3_clock_enable(ctrl);
- if (rc) {
- cpr3_err(ctrl, "clock enable failed, rc=%d\n", rc);
- mutex_unlock(&ctrl->lock);
- return CPR3_REGULATOR_CORNER_INVALID;
- }
- ctrl->cpr_enabled = true;
- }
- reg = cpr3_read(vreg->thread->ctrl, CPRH_REG_STATUS(vreg->thread));
- if (!cpr_enabled) {
- cpr3_clock_disable(ctrl);
- ctrl->cpr_enabled = false;
- }
- mutex_unlock(&ctrl->lock);
- return (reg & CPRH_STATUS_CORNER)
- + CPR3_CORNER_OFFSET;
- }
- static struct regulator_ops cprh_regulator_ops = {
- .get_voltage = cprh_regulator_get_voltage,
- .list_corner_voltage = cpr3_regulator_list_corner_voltage,
- };
- static void cpr3_print_result(struct cpr3_thread *thread)
- {
- struct cpr3_controller *ctrl = thread->ctrl;
- u32 result[3], busy, step_dn, step_up, error_steps, error, negative;
- u32 quot_min, quot_max, ro_min, ro_max, step_quot_min, step_quot_max;
- u32 sensor_min, sensor_max;
- char *sign;
- result[0] = cpr3_read(ctrl, CPR3_REG_RESULT0(thread->thread_id));
- result[1] = cpr3_read(ctrl, CPR3_REG_RESULT1(thread->thread_id));
- result[2] = cpr3_read(ctrl, CPR3_REG_RESULT2(thread->thread_id));
- busy = !!(result[0] & CPR3_RESULT0_BUSY_MASK);
- step_dn = !!(result[0] & CPR3_RESULT0_STEP_DN_MASK);
- step_up = !!(result[0] & CPR3_RESULT0_STEP_UP_MASK);
- error_steps = (result[0] & CPR3_RESULT0_ERROR_STEPS_MASK)
- >> CPR3_RESULT0_ERROR_STEPS_SHIFT;
- error = (result[0] & CPR3_RESULT0_ERROR_MASK)
- >> CPR3_RESULT0_ERROR_SHIFT;
- negative = !!(result[0] & CPR3_RESULT0_NEGATIVE_MASK);
- quot_min = (result[1] & CPR3_RESULT1_QUOT_MIN_MASK)
- >> CPR3_RESULT1_QUOT_MIN_SHIFT;
- quot_max = (result[1] & CPR3_RESULT1_QUOT_MAX_MASK)
- >> CPR3_RESULT1_QUOT_MAX_SHIFT;
- ro_min = (result[1] & CPR3_RESULT1_RO_MIN_MASK)
- >> CPR3_RESULT1_RO_MIN_SHIFT;
- ro_max = (result[1] & CPR3_RESULT1_RO_MAX_MASK)
- >> CPR3_RESULT1_RO_MAX_SHIFT;
- step_quot_min = (result[2] & CPR3_RESULT2_STEP_QUOT_MIN_MASK)
- >> CPR3_RESULT2_STEP_QUOT_MIN_SHIFT;
- step_quot_max = (result[2] & CPR3_RESULT2_STEP_QUOT_MAX_MASK)
- >> CPR3_RESULT2_STEP_QUOT_MAX_SHIFT;
- sensor_min = (result[2] & CPR3_RESULT2_SENSOR_MIN_MASK)
- >> CPR3_RESULT2_SENSOR_MIN_SHIFT;
- sensor_max = (result[2] & CPR3_RESULT2_SENSOR_MAX_MASK)
- >> CPR3_RESULT2_SENSOR_MAX_SHIFT;
- sign = negative ? "-" : "";
- cpr3_debug(ctrl, "thread %u: busy=%u, step_dn=%u, step_up=%u, error_steps=%s%u, error=%s%u\n",
- thread->thread_id, busy, step_dn, step_up, sign, error_steps,
- sign, error);
- cpr3_debug(ctrl, "thread %u: quot_min=%u, quot_max=%u, ro_min=%u, ro_max=%u\n",
- thread->thread_id, quot_min, quot_max, ro_min, ro_max);
- cpr3_debug(ctrl, "thread %u: step_quot_min=%u, step_quot_max=%u, sensor_min=%u, sensor_max=%u\n",
- thread->thread_id, step_quot_min, step_quot_max, sensor_min,
- sensor_max);
- }
- static bool cpr3_thread_busy(struct cpr3_thread *thread)
- {
- u32 result;
- result = cpr3_read(thread->ctrl, CPR3_REG_RESULT0(thread->thread_id));
- return !!(result & CPR3_RESULT0_BUSY_MASK);
- }
- static irqreturn_t cpr3_irq_handler(int irq, void *data)
- {
- struct cpr3_controller *ctrl = data;
- struct cpr3_corner *aggr = &ctrl->aggr_corner;
- u32 cont = CPR3_CONT_CMD_NACK;
- u32 reg_last_measurement = 0;
- struct cpr3_regulator *vreg;
- struct cpr3_corner *corner;
- unsigned long flags;
- int i, j, new_volt, last_volt, dynamic_floor_volt, rc;
- u32 irq_en, status, cpr_status, ctl;
- bool up, down;
- mutex_lock(&ctrl->lock);
- if (!ctrl->cpr_enabled) {
- cpr3_debug(ctrl, "CPR interrupt received but CPR is disabled\n");
- mutex_unlock(&ctrl->lock);
- return IRQ_HANDLED;
- } else if (ctrl->use_hw_closed_loop) {
- cpr3_debug(ctrl, "CPR interrupt received but CPR is using HW closed-loop\n");
- goto done;
- }
-
- local_irq_save(flags);
- preempt_disable();
- status = cpr3_read(ctrl, CPR3_REG_IRQ_STATUS);
- up = status & CPR3_IRQ_UP;
- down = status & CPR3_IRQ_DOWN;
- if (!up && !down) {
-
- cpr3_ctrl_loop_disable(ctrl);
- local_irq_restore(flags);
- preempt_enable();
-
- mb();
-
- for (i = 0; i < CPR3_REGISTER_WRITE_DELAY_US / 10; i++) {
- cpr_status = cpr3_read(ctrl, CPR3_REG_CPR_STATUS);
- ctl = cpr3_read(ctrl, CPR3_REG_CPR_CTL);
- if (cpr_status & CPR3_CPR_STATUS_BUSY_MASK
- && (ctl & CPR3_CPR_CTL_LOOP_EN_MASK)
- == CPR3_CPR_CTL_LOOP_DISABLE)
- break;
- udelay(10);
- }
- if (i == CPR3_REGISTER_WRITE_DELAY_US / 10)
- cpr3_debug(ctrl, "CPR controller not disabled after %d us\n",
- CPR3_REGISTER_WRITE_DELAY_US);
-
- cpr3_write(ctrl, CPR3_REG_IRQ_CLEAR,
- CPR3_IRQ_UP | CPR3_IRQ_DOWN);
-
- mb();
-
- for (i = 0; i < CPR3_REGISTER_WRITE_DELAY_US / 10; i++) {
- status = cpr3_read(ctrl, CPR3_REG_IRQ_STATUS);
- if (!(status & (CPR3_IRQ_UP | CPR3_IRQ_DOWN)))
- break;
- udelay(10);
- }
- if (i == CPR3_REGISTER_WRITE_DELAY_US / 10)
- cpr3_debug(ctrl, "CPR interrupts not cleared after %d us\n",
- CPR3_REGISTER_WRITE_DELAY_US);
- cpr3_ctrl_loop_enable(ctrl);
- cpr3_debug(ctrl, "CPR interrupt received but no up or down status bit is set\n");
- mutex_unlock(&ctrl->lock);
- return IRQ_HANDLED;
- } else if (up && down) {
- cpr3_debug(ctrl, "both up and down status bits set\n");
-
- down = false;
- }
- if (ctrl->supports_hw_closed_loop)
- reg_last_measurement
- = cpr3_read(ctrl, CPR3_REG_LAST_MEASUREMENT);
- dynamic_floor_volt = cpr3_regulator_get_dynamic_floor_volt(ctrl,
- reg_last_measurement);
- local_irq_restore(flags);
- preempt_enable();
- irq_en = aggr->irq_en;
- last_volt = aggr->last_volt;
- for (i = 0; i < ctrl->thread_count; i++) {
- if (cpr3_thread_busy(&ctrl->thread[i])) {
- cpr3_debug(ctrl, "CPR thread %u busy when it should be waiting for SW cont\n",
- ctrl->thread[i].thread_id);
- goto done;
- }
- }
- new_volt = up ? last_volt + ctrl->step_volt
- : last_volt - ctrl->step_volt;
-
- irq_en |= up ? CPR3_IRQ_DOWN : CPR3_IRQ_UP;
- if (new_volt > aggr->ceiling_volt) {
- new_volt = aggr->ceiling_volt;
- irq_en &= ~CPR3_IRQ_UP;
- cpr3_debug(ctrl, "limiting to ceiling=%d uV\n",
- aggr->ceiling_volt);
- } else if (new_volt < aggr->floor_volt) {
- new_volt = aggr->floor_volt;
- irq_en &= ~CPR3_IRQ_DOWN;
- cpr3_debug(ctrl, "limiting to floor=%d uV\n", aggr->floor_volt);
- }
- if (down && new_volt < dynamic_floor_volt) {
-
- new_volt = last_volt;
- irq_en &= ~CPR3_IRQ_DOWN;
- cpr3_debug(ctrl, "limiting to dynamic floor=%d uV\n",
- dynamic_floor_volt);
- }
- for (i = 0; i < ctrl->thread_count; i++)
- cpr3_print_result(&ctrl->thread[i]);
- cpr3_debug(ctrl, "%s: new_volt=%d uV, last_volt=%d uV\n",
- up ? "UP" : "DN", new_volt, last_volt);
- if (ctrl->proc_clock_throttle && last_volt == aggr->ceiling_volt
- && new_volt < last_volt)
- cpr3_write(ctrl, CPR3_REG_PD_THROTTLE,
- ctrl->proc_clock_throttle);
- if (new_volt != last_volt) {
- rc = cpr3_regulator_scale_vdd_voltage(ctrl, new_volt,
- last_volt,
- aggr);
- if (rc) {
- cpr3_err(ctrl, "scale_vdd() failed to set vdd=%d uV, rc=%d\n",
- new_volt, rc);
- goto done;
- }
- cont = CPR3_CONT_CMD_ACK;
-
- for (i = 0; i < ctrl->thread_count; i++) {
- for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
- vreg = &ctrl->thread[i].vreg[j];
- cpr3_update_vreg_closed_loop_volt(vreg,
- new_volt, reg_last_measurement);
- }
- }
- }
- if (ctrl->proc_clock_throttle && new_volt == aggr->ceiling_volt)
- cpr3_write(ctrl, CPR3_REG_PD_THROTTLE,
- CPR3_PD_THROTTLE_DISABLE);
- corner = &ctrl->thread[0].vreg[0].corner[
- ctrl->thread[0].vreg[0].current_corner];
- if (irq_en != aggr->irq_en) {
- aggr->irq_en = irq_en;
- cpr3_write(ctrl, CPR3_REG_IRQ_EN, irq_en);
- }
- aggr->last_volt = new_volt;
- done:
-
- cpr3_write(ctrl, CPR3_REG_IRQ_CLEAR, CPR3_IRQ_UP | CPR3_IRQ_DOWN);
-
- cpr3_write(ctrl, CPR3_REG_CONT_CMD, cont);
- mutex_unlock(&ctrl->lock);
- return IRQ_HANDLED;
- }
- static irqreturn_t cpr3_ceiling_irq_handler(int irq, void *data)
- {
- struct cpr3_controller *ctrl = data;
- int rc, volt;
- mutex_lock(&ctrl->lock);
- if (!ctrl->cpr_enabled) {
- cpr3_debug(ctrl, "CPR ceiling interrupt received but CPR is disabled\n");
- goto done;
- } else if (!ctrl->use_hw_closed_loop) {
- cpr3_debug(ctrl, "CPR ceiling interrupt received but CPR is using SW closed-loop\n");
- goto done;
- }
- volt = regulator_get_voltage(ctrl->vdd_regulator);
- if (volt < 0) {
- cpr3_err(ctrl, "could not get vdd voltage, rc=%d\n", volt);
- goto done;
- } else if (volt != ctrl->aggr_corner.ceiling_volt) {
- cpr3_debug(ctrl, "CPR ceiling interrupt received but vdd voltage: %d uV != ceiling voltage: %d uV\n",
- volt, ctrl->aggr_corner.ceiling_volt);
- goto done;
- }
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
-
- cpr3_write(ctrl, CPR3_REG_PD_THROTTLE,
- CPR3_PD_THROTTLE_DISABLE);
- cpr3_ctrl_loop_disable(ctrl);
- cpr3_debug(ctrl, "CPR closed-loop and throttling disabled\n");
- }
- done:
- rc = msm_spm_avs_clear_irq(0, MSM_SPM_AVS_IRQ_MAX);
- if (rc)
- cpr3_err(ctrl, "could not clear max IRQ, rc=%d\n", rc);
- mutex_unlock(&ctrl->lock);
- return IRQ_HANDLED;
- }
- static int cpr3_regulator_vreg_register(struct cpr3_regulator *vreg)
- {
- struct regulator_config config = {};
- struct regulator_desc *rdesc;
- struct regulator_init_data *init_data;
- int rc;
- init_data = of_get_regulator_init_data(vreg->thread->ctrl->dev,
- vreg->of_node, &vreg->rdesc);
- if (!init_data) {
- cpr3_err(vreg, "regulator init data is missing\n");
- return -EINVAL;
- }
- init_data->constraints.input_uV = init_data->constraints.max_uV;
- rdesc = &vreg->rdesc;
- if (vreg->thread->ctrl->ctrl_type == CPR_CTRL_TYPE_CPRH) {
-
- rdesc->ops = &cprh_regulator_ops;
- } else {
- init_data->constraints.valid_ops_mask
- |= REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS;
- rdesc->ops = &cpr3_regulator_ops;
- }
- rdesc->n_voltages = vreg->corner_count;
- rdesc->name = init_data->constraints.name;
- rdesc->owner = THIS_MODULE;
- rdesc->type = REGULATOR_VOLTAGE;
- config.dev = vreg->thread->ctrl->dev;
- config.driver_data = vreg;
- config.init_data = init_data;
- config.of_node = vreg->of_node;
- vreg->rdev = regulator_register(rdesc, &config);
- if (IS_ERR(vreg->rdev)) {
- rc = PTR_ERR(vreg->rdev);
- cpr3_err(vreg, "regulator_register failed, rc=%d\n", rc);
- return rc;
- }
- return 0;
- }
- static int debugfs_int_set(void *data, u64 val)
- {
- *(int *)data = val;
- return 0;
- }
- static int debugfs_int_get(void *data, u64 *val)
- {
- *val = *(int *)data;
- return 0;
- }
- DEFINE_SIMPLE_ATTRIBUTE(fops_int, debugfs_int_get, debugfs_int_set, "%lld\n");
- DEFINE_SIMPLE_ATTRIBUTE(fops_int_ro, debugfs_int_get, NULL, "%lld\n");
- DEFINE_SIMPLE_ATTRIBUTE(fops_int_wo, NULL, debugfs_int_set, "%lld\n");
- static struct dentry *debugfs_create_int(const char *name, umode_t mode,
- struct dentry *parent, int *value)
- {
-
- if (!(mode & 0222))
- return debugfs_create_file(name, mode, parent, value,
- &fops_int_ro);
-
- if (!(mode & 0444))
- return debugfs_create_file(name, mode, parent, value,
- &fops_int_wo);
- return debugfs_create_file(name, mode, parent, value, &fops_int);
- }
- static int debugfs_bool_get(void *data, u64 *val)
- {
- *val = *(bool *)data;
- return 0;
- }
- DEFINE_SIMPLE_ATTRIBUTE(fops_bool_ro, debugfs_bool_get, NULL, "%lld\n");
- static int cpr3_debug_ldo_mode_allowed_set(void *data, u64 val)
- {
- struct cpr3_regulator *vreg = data;
- struct cpr3_controller *ctrl = vreg->thread->ctrl;
- bool allow = !!val;
- int rc, vdd_volt;
- mutex_lock(&ctrl->lock);
- if (vreg->ldo_mode_allowed == allow)
- goto done;
- vreg->ldo_mode_allowed = allow;
- if (!allow && vreg->ldo_regulator_bypass == LDO_MODE) {
- vdd_volt = regulator_get_voltage(ctrl->vdd_regulator);
- if (vdd_volt < 0) {
- cpr3_err(vreg, "regulator_get_voltage(vdd) failed, rc=%d\n",
- vdd_volt);
- goto done;
- }
-
- rc = cpr3_regulator_set_bhs_mode(vreg, vdd_volt,
- ctrl->aggr_corner.ceiling_volt);
- if (rc) {
- cpr3_err(vreg, "unable to switch to BHS mode, rc=%d\n",
- rc);
- goto done;
- }
- } else {
- rc = cpr3_regulator_update_ctrl_state(ctrl);
- if (rc) {
- cpr3_err(vreg, "could not change LDO mode=%s, rc=%d\n",
- allow ? "allowed" : "disallowed", rc);
- goto done;
- }
- }
- cpr3_debug(vreg, "LDO mode=%s\n", allow ? "allowed" : "disallowed");
- done:
- mutex_unlock(&ctrl->lock);
- return 0;
- }
- static int cpr3_debug_ldo_mode_allowed_get(void *data, u64 *val)
- {
- struct cpr3_regulator *vreg = data;
- *val = vreg->ldo_mode_allowed;
- return 0;
- }
- DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_ldo_mode_allowed_fops,
- cpr3_debug_ldo_mode_allowed_get,
- cpr3_debug_ldo_mode_allowed_set,
- "%llu\n");
- static int cpr3_debug_ldo_mode_get(void *data, u64 *val)
- {
- struct cpr3_regulator *vreg = data;
- *val = (vreg->ldo_regulator_bypass == LDO_MODE);
- return 0;
- }
- DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_ldo_mode_fops, cpr3_debug_ldo_mode_get,
- NULL, "%llu\n");
- struct cpr3_debug_corner_info {
- struct cpr3_regulator *vreg;
- int *index;
- size_t member_offset;
- struct cpr3_corner *corner;
- };
- static int cpr3_debug_corner_int_get(void *data, u64 *val)
- {
- struct cpr3_debug_corner_info *info = data;
- struct cpr3_controller *ctrl = info->vreg->thread->ctrl;
- int i;
- mutex_lock(&ctrl->lock);
- i = *info->index;
- if (i < 0)
- i = 0;
- *val = *(int *)((char *)&info->vreg->corner[i] + info->member_offset);
- mutex_unlock(&ctrl->lock);
- return 0;
- }
- DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_corner_int_fops, cpr3_debug_corner_int_get,
- NULL, "%lld\n");
- static struct dentry *cpr3_debugfs_create_corner_int(
- struct cpr3_regulator *vreg, const char *name, umode_t mode,
- struct dentry *parent, int *index, size_t member_offset)
- {
- struct cpr3_debug_corner_info *info;
- info = devm_kzalloc(vreg->thread->ctrl->dev, sizeof(*info), GFP_KERNEL);
- if (!info)
- return NULL;
- info->vreg = vreg;
- info->index = index;
- info->member_offset = member_offset;
- return debugfs_create_file(name, mode, parent, info,
- &cpr3_debug_corner_int_fops);
- }
- static int cpr3_debug_quot_open(struct inode *inode, struct file *file)
- {
- struct cpr3_debug_corner_info *info = inode->i_private;
- struct cpr3_thread *thread = info->vreg->thread;
- int size, i, pos;
- u32 *quot;
- char *buf;
-
- size = CPR3_RO_COUNT * 11;
- buf = kzalloc(size + 1, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
- file->private_data = buf;
- mutex_lock(&thread->ctrl->lock);
- quot = info->corner[*info->index].target_quot;
- for (i = 0, pos = 0; i < CPR3_RO_COUNT; i++)
- pos += scnprintf(buf + pos, size - pos, "%u%c",
- quot[i], i < CPR3_RO_COUNT - 1 ? ' ' : '\n');
- mutex_unlock(&thread->ctrl->lock);
- return nonseekable_open(inode, file);
- }
- static ssize_t cpr3_debug_quot_read(struct file *file, char __user *buf,
- size_t len, loff_t *ppos)
- {
- return simple_read_from_buffer(buf, len, ppos, file->private_data,
- strlen(file->private_data));
- }
- static int cpr3_debug_quot_release(struct inode *inode, struct file *file)
- {
- kfree(file->private_data);
- return 0;
- }
- static const struct file_operations cpr3_debug_quot_fops = {
- .owner = THIS_MODULE,
- .open = cpr3_debug_quot_open,
- .release = cpr3_debug_quot_release,
- .read = cpr3_debug_quot_read,
- .llseek = no_llseek,
- };
- static void cpr3_regulator_debugfs_corner_add(struct cpr3_regulator *vreg,
- struct dentry *corner_dir, int *index)
- {
- struct cpr3_debug_corner_info *info;
- struct dentry *temp;
- temp = cpr3_debugfs_create_corner_int(vreg, "floor_volt", 0444,
- corner_dir, index, offsetof(struct cpr3_corner, floor_volt));
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(vreg, "floor_volt debugfs file creation failed\n");
- return;
- }
- temp = cpr3_debugfs_create_corner_int(vreg, "ceiling_volt", 0444,
- corner_dir, index, offsetof(struct cpr3_corner, ceiling_volt));
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(vreg, "ceiling_volt debugfs file creation failed\n");
- return;
- }
- temp = cpr3_debugfs_create_corner_int(vreg, "open_loop_volt", 0444,
- corner_dir, index,
- offsetof(struct cpr3_corner, open_loop_volt));
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(vreg, "open_loop_volt debugfs file creation failed\n");
- return;
- }
- temp = cpr3_debugfs_create_corner_int(vreg, "last_volt", 0444,
- corner_dir, index, offsetof(struct cpr3_corner, last_volt));
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(vreg, "last_volt debugfs file creation failed\n");
- return;
- }
- info = devm_kzalloc(vreg->thread->ctrl->dev, sizeof(*info), GFP_KERNEL);
- if (!info)
- return;
- info->vreg = vreg;
- info->index = index;
- info->corner = vreg->corner;
- temp = debugfs_create_file("target_quots", 0444, corner_dir, info,
- &cpr3_debug_quot_fops);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(vreg, "target_quots debugfs file creation failed\n");
- return;
- }
- }
- static int cpr3_debug_corner_index_set(void *data, u64 val)
- {
- struct cpr3_regulator *vreg = data;
- if (val < CPR3_CORNER_OFFSET || val > vreg->corner_count) {
- cpr3_err(vreg, "invalid corner index %llu; allowed values: %d-%d\n",
- val, CPR3_CORNER_OFFSET, vreg->corner_count);
- return -EINVAL;
- }
- mutex_lock(&vreg->thread->ctrl->lock);
- vreg->debug_corner = val - CPR3_CORNER_OFFSET;
- mutex_unlock(&vreg->thread->ctrl->lock);
- return 0;
- }
- static int cpr3_debug_corner_index_get(void *data, u64 *val)
- {
- struct cpr3_regulator *vreg = data;
- *val = vreg->debug_corner + CPR3_CORNER_OFFSET;
- return 0;
- }
- DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_corner_index_fops,
- cpr3_debug_corner_index_get,
- cpr3_debug_corner_index_set,
- "%llu\n");
- static int cpr3_debug_current_corner_index_get(void *data, u64 *val)
- {
- struct cpr3_regulator *vreg = data;
- *val = vreg->current_corner + CPR3_CORNER_OFFSET;
- return 0;
- }
- DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_current_corner_index_fops,
- cpr3_debug_current_corner_index_get,
- NULL, "%llu\n");
- static void cpr3_regulator_debugfs_vreg_add(struct cpr3_regulator *vreg,
- struct dentry *thread_dir)
- {
- struct dentry *temp, *corner_dir, *vreg_dir;
- vreg_dir = debugfs_create_dir(vreg->name, thread_dir);
- if (IS_ERR_OR_NULL(vreg_dir)) {
- cpr3_err(vreg, "%s debugfs directory creation failed\n",
- vreg->name);
- return;
- }
- temp = debugfs_create_int("speed_bin_fuse", 0444, vreg_dir,
- &vreg->speed_bin_fuse);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(vreg, "speed_bin_fuse debugfs file creation failed\n");
- return;
- }
- temp = debugfs_create_int("cpr_rev_fuse", 0444, vreg_dir,
- &vreg->cpr_rev_fuse);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(vreg, "cpr_rev_fuse debugfs file creation failed\n");
- return;
- }
- temp = debugfs_create_int("fuse_combo", 0444, vreg_dir,
- &vreg->fuse_combo);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(vreg, "fuse_combo debugfs file creation failed\n");
- return;
- }
- if (vreg->ldo_regulator) {
- temp = debugfs_create_file("ldo_mode", 0444, vreg_dir, vreg,
- &cpr3_debug_ldo_mode_fops);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(vreg, "ldo_mode debugfs file creation failed\n");
- return;
- }
- temp = debugfs_create_file("ldo_mode_allowed",
- 0644, vreg_dir, vreg,
- &cpr3_debug_ldo_mode_allowed_fops);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(vreg, "ldo_mode_allowed debugfs file creation failed\n");
- return;
- }
- }
- temp = debugfs_create_int("corner_count", 0444, vreg_dir,
- &vreg->corner_count);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(vreg, "corner_count debugfs file creation failed\n");
- return;
- }
- corner_dir = debugfs_create_dir("corner", vreg_dir);
- if (IS_ERR_OR_NULL(corner_dir)) {
- cpr3_err(vreg, "corner debugfs directory creation failed\n");
- return;
- }
- temp = debugfs_create_file("index", 0644, corner_dir, vreg,
- &cpr3_debug_corner_index_fops);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(vreg, "index debugfs file creation failed\n");
- return;
- }
- cpr3_regulator_debugfs_corner_add(vreg, corner_dir,
- &vreg->debug_corner);
- corner_dir = debugfs_create_dir("current_corner", vreg_dir);
- if (IS_ERR_OR_NULL(corner_dir)) {
- cpr3_err(vreg, "current_corner debugfs directory creation failed\n");
- return;
- }
- temp = debugfs_create_file("index", 0444, corner_dir, vreg,
- &cpr3_debug_current_corner_index_fops);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(vreg, "index debugfs file creation failed\n");
- return;
- }
- cpr3_regulator_debugfs_corner_add(vreg, corner_dir,
- &vreg->current_corner);
- }
- static void cpr3_regulator_debugfs_thread_add(struct cpr3_thread *thread)
- {
- struct cpr3_controller *ctrl = thread->ctrl;
- struct dentry *aggr_dir, *temp, *thread_dir;
- struct cpr3_debug_corner_info *info;
- char buf[20];
- int *index;
- int i;
- scnprintf(buf, sizeof(buf), "thread%u", thread->thread_id);
- thread_dir = debugfs_create_dir(buf, thread->ctrl->debugfs);
- if (IS_ERR_OR_NULL(thread_dir)) {
- cpr3_err(ctrl, "thread %u %s debugfs directory creation failed\n",
- thread->thread_id, buf);
- return;
- }
- aggr_dir = debugfs_create_dir("max_aggregated_params", thread_dir);
- if (IS_ERR_OR_NULL(aggr_dir)) {
- cpr3_err(ctrl, "thread %u max_aggregated_params debugfs directory creation failed\n",
- thread->thread_id);
- return;
- }
- temp = debugfs_create_int("floor_volt", 0444, aggr_dir,
- &thread->aggr_corner.floor_volt);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(ctrl, "thread %u aggr floor_volt debugfs file creation failed\n",
- thread->thread_id);
- return;
- }
- temp = debugfs_create_int("ceiling_volt", 0444, aggr_dir,
- &thread->aggr_corner.ceiling_volt);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(ctrl, "thread %u aggr ceiling_volt debugfs file creation failed\n",
- thread->thread_id);
- return;
- }
- temp = debugfs_create_int("open_loop_volt", 0444, aggr_dir,
- &thread->aggr_corner.open_loop_volt);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(ctrl, "thread %u aggr open_loop_volt debugfs file creation failed\n",
- thread->thread_id);
- return;
- }
- temp = debugfs_create_int("last_volt", 0444, aggr_dir,
- &thread->aggr_corner.last_volt);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(ctrl, "thread %u aggr last_volt debugfs file creation failed\n",
- thread->thread_id);
- return;
- }
- info = devm_kzalloc(thread->ctrl->dev, sizeof(*info), GFP_KERNEL);
- index = devm_kzalloc(thread->ctrl->dev, sizeof(*index), GFP_KERNEL);
- if (!info || !index)
- return;
- *index = 0;
- info->vreg = &thread->vreg[0];
- info->index = index;
- info->corner = &thread->aggr_corner;
- temp = debugfs_create_file("target_quots", 0444, aggr_dir, info,
- &cpr3_debug_quot_fops);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(ctrl, "thread %u target_quots debugfs file creation failed\n",
- thread->thread_id);
- return;
- }
- for (i = 0; i < thread->vreg_count; i++)
- cpr3_regulator_debugfs_vreg_add(&thread->vreg[i], thread_dir);
- }
- static int cpr3_debug_closed_loop_enable_set(void *data, u64 val)
- {
- struct cpr3_controller *ctrl = data;
- bool enable = !!val;
- int rc;
- mutex_lock(&ctrl->lock);
- if (ctrl->cpr_allowed_sw == enable)
- goto done;
- if (enable && !ctrl->cpr_allowed_hw) {
- cpr3_err(ctrl, "CPR closed-loop operation is not allowed\n");
- goto done;
- }
- ctrl->cpr_allowed_sw = enable;
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPRH) {
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
- CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK,
- ctrl->cpr_allowed_sw && ctrl->use_hw_closed_loop
- ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE
- : CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE);
- } else {
- rc = cpr3_regulator_update_ctrl_state(ctrl);
- if (rc) {
- cpr3_err(ctrl, "could not change CPR enable state=%u, rc=%d\n",
- enable, rc);
- goto done;
- }
- if (ctrl->proc_clock_throttle && !ctrl->cpr_enabled) {
- rc = cpr3_clock_enable(ctrl);
- if (rc) {
- cpr3_err(ctrl, "clock enable failed, rc=%d\n",
- rc);
- goto done;
- }
- ctrl->cpr_enabled = true;
- cpr3_write(ctrl, CPR3_REG_PD_THROTTLE,
- CPR3_PD_THROTTLE_DISABLE);
- cpr3_clock_disable(ctrl);
- ctrl->cpr_enabled = false;
- }
- }
- if (ctrl->ctrl_type != CPR_CTRL_TYPE_CPRH) {
- cpr3_debug(ctrl, "closed-loop=%s\n", enable ?
- "enabled" : "disabled");
- } else {
- cpr3_debug(ctrl, "closed-loop=%s\n", enable &&
- ctrl->use_hw_closed_loop ? "enabled" : "disabled");
- }
- done:
- mutex_unlock(&ctrl->lock);
- return 0;
- }
- static int cpr3_debug_closed_loop_enable_get(void *data, u64 *val)
- {
- struct cpr3_controller *ctrl = data;
- *val = ctrl->cpr_allowed_sw;
- return 0;
- }
- DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_closed_loop_enable_fops,
- cpr3_debug_closed_loop_enable_get,
- cpr3_debug_closed_loop_enable_set,
- "%llu\n");
- static int cpr3_debug_hw_closed_loop_enable_set(void *data, u64 val)
- {
- struct cpr3_controller *ctrl = data;
- bool use_hw_closed_loop = !!val;
- struct cpr3_regulator *vreg;
- bool cpr_enabled;
- int i, j, k, rc;
- mutex_lock(&ctrl->lock);
- if (ctrl->use_hw_closed_loop == use_hw_closed_loop)
- goto done;
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
- rc = cpr3_ctrl_clear_cpr4_config(ctrl);
- if (rc) {
- cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
- rc);
- goto done;
- }
- }
- if (ctrl->ctrl_type != CPR_CTRL_TYPE_CPRH)
- cpr3_ctrl_loop_disable(ctrl);
- ctrl->use_hw_closed_loop = use_hw_closed_loop;
- cpr_enabled = ctrl->cpr_enabled;
-
- if (!cpr_enabled) {
- rc = cpr3_clock_enable(ctrl);
- if (rc) {
- cpr3_err(ctrl, "clock enable failed, rc=%d\n", rc);
- goto done;
- }
- ctrl->cpr_enabled = true;
- }
- if (ctrl->use_hw_closed_loop && ctrl->ctrl_type != CPR_CTRL_TYPE_CPRH)
- cpr3_write(ctrl, CPR3_REG_IRQ_EN, 0);
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
- CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK,
- ctrl->use_hw_closed_loop
- ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE
- : CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE);
- } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPRH) {
- cpr3_masked_write(ctrl, CPR4_REG_MARGIN_ADJ_CTL,
- CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_EN_MASK,
- ctrl->cpr_allowed_sw && ctrl->use_hw_closed_loop
- ? CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_ENABLE
- : CPR4_MARGIN_ADJ_CTL_HW_CLOSED_LOOP_DISABLE);
- } else if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
- cpr3_write(ctrl, CPR3_REG_HW_CLOSED_LOOP,
- ctrl->use_hw_closed_loop
- ? CPR3_HW_CLOSED_LOOP_ENABLE
- : CPR3_HW_CLOSED_LOOP_DISABLE);
- }
-
- if (!cpr_enabled) {
- cpr3_clock_disable(ctrl);
- ctrl->cpr_enabled = false;
- }
- if (ctrl->use_hw_closed_loop && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
- rc = regulator_enable(ctrl->vdd_limit_regulator);
- if (rc) {
- cpr3_err(ctrl, "CPR limit regulator enable failed, rc=%d\n",
- rc);
- goto done;
- }
- rc = msm_spm_avs_enable_irq(0, MSM_SPM_AVS_IRQ_MAX);
- if (rc) {
- cpr3_err(ctrl, "could not enable max IRQ, rc=%d\n", rc);
- goto done;
- }
- } else if (!ctrl->use_hw_closed_loop
- && ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
- rc = regulator_disable(ctrl->vdd_limit_regulator);
- if (rc) {
- cpr3_err(ctrl, "CPR limit regulator disable failed, rc=%d\n",
- rc);
- goto done;
- }
- rc = msm_spm_avs_disable_irq(0, MSM_SPM_AVS_IRQ_MAX);
- if (rc) {
- cpr3_err(ctrl, "could not disable max IRQ, rc=%d\n",
- rc);
- goto done;
- }
- }
- if (ctrl->ctrl_type != CPR_CTRL_TYPE_CPRH) {
-
- for (i = 0; i < ctrl->thread_count; i++) {
- for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
- vreg = &ctrl->thread[i].vreg[j];
- for (k = 0; k < vreg->corner_count; k++)
- vreg->corner[k].last_volt
- = vreg->corner[k].open_loop_volt;
- }
- }
-
- ctrl->last_corner_was_closed_loop = false;
- rc = cpr3_regulator_update_ctrl_state(ctrl);
- if (rc) {
- cpr3_err(ctrl, "could not change CPR HW closed-loop enable state=%u, rc=%d\n",
- use_hw_closed_loop, rc);
- goto done;
- }
- cpr3_debug(ctrl, "CPR mode=%s\n",
- use_hw_closed_loop ?
- "HW closed-loop" : "SW closed-loop");
- } else {
- cpr3_debug(ctrl, "CPR mode=%s\n",
- ctrl->cpr_allowed_sw && use_hw_closed_loop ?
- "full HW closed-loop" : "open-loop");
- }
- done:
- mutex_unlock(&ctrl->lock);
- return 0;
- }
- static int cpr3_debug_hw_closed_loop_enable_get(void *data, u64 *val)
- {
- struct cpr3_controller *ctrl = data;
- *val = ctrl->use_hw_closed_loop;
- return 0;
- }
- DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_hw_closed_loop_enable_fops,
- cpr3_debug_hw_closed_loop_enable_get,
- cpr3_debug_hw_closed_loop_enable_set,
- "%llu\n");
- static int cpr3_debug_trigger_aging_measurement_set(void *data, u64 val)
- {
- struct cpr3_controller *ctrl = data;
- int rc;
- mutex_lock(&ctrl->lock);
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
- rc = cpr3_ctrl_clear_cpr4_config(ctrl);
- if (rc) {
- cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
- rc);
- goto done;
- }
- }
- cpr3_ctrl_loop_disable(ctrl);
- cpr3_regulator_set_aging_ref_adjustment(ctrl, INT_MAX);
- ctrl->aging_required = true;
- ctrl->aging_succeeded = false;
- ctrl->aging_failed = false;
- rc = cpr3_regulator_update_ctrl_state(ctrl);
- if (rc) {
- cpr3_err(ctrl, "could not update the CPR controller state, rc=%d\n",
- rc);
- goto done;
- }
- done:
- mutex_unlock(&ctrl->lock);
- return 0;
- }
- DEFINE_SIMPLE_ATTRIBUTE(cpr3_debug_trigger_aging_measurement_fops,
- NULL,
- cpr3_debug_trigger_aging_measurement_set,
- "%llu\n");
- static void cpr3_regulator_debugfs_ctrl_add(struct cpr3_controller *ctrl)
- {
- struct dentry *temp, *aggr_dir;
- int i;
-
- if (cpr3_debugfs_base == NULL) {
- cpr3_debugfs_base = debugfs_create_dir("cpr3-regulator", NULL);
- if (IS_ERR_OR_NULL(cpr3_debugfs_base)) {
- cpr3_err(ctrl, "cpr3-regulator debugfs base directory creation failed\n");
- cpr3_debugfs_base = NULL;
- return;
- }
- }
- ctrl->debugfs = debugfs_create_dir(ctrl->name, cpr3_debugfs_base);
- if (IS_ERR_OR_NULL(ctrl->debugfs)) {
- cpr3_err(ctrl, "cpr3-regulator controller debugfs directory creation failed\n");
- return;
- }
- temp = debugfs_create_file("cpr_closed_loop_enable", 0644,
- ctrl->debugfs, ctrl,
- &cpr3_debug_closed_loop_enable_fops);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(ctrl, "cpr_closed_loop_enable debugfs file creation failed\n");
- return;
- }
- if (ctrl->supports_hw_closed_loop) {
- temp = debugfs_create_file("use_hw_closed_loop", 0644,
- ctrl->debugfs, ctrl,
- &cpr3_debug_hw_closed_loop_enable_fops);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(ctrl, "use_hw_closed_loop debugfs file creation failed\n");
- return;
- }
- }
- temp = debugfs_create_int("thread_count", 0444, ctrl->debugfs,
- &ctrl->thread_count);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(ctrl, "thread_count debugfs file creation failed\n");
- return;
- }
- if (ctrl->apm) {
- temp = debugfs_create_int("apm_threshold_volt", 0444,
- ctrl->debugfs, &ctrl->apm_threshold_volt);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(ctrl, "apm_threshold_volt debugfs file creation failed\n");
- return;
- }
- }
- if (ctrl->aging_required || ctrl->aging_succeeded
- || ctrl->aging_failed) {
- temp = debugfs_create_int("aging_adj_volt", 0444,
- ctrl->debugfs, &ctrl->aging_ref_adjust_volt);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(ctrl, "aging_adj_volt debugfs file creation failed\n");
- return;
- }
- temp = debugfs_create_file("aging_succeeded", 0444,
- ctrl->debugfs, &ctrl->aging_succeeded, &fops_bool_ro);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(ctrl, "aging_succeeded debugfs file creation failed\n");
- return;
- }
- temp = debugfs_create_file("aging_failed", 0444,
- ctrl->debugfs, &ctrl->aging_failed, &fops_bool_ro);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(ctrl, "aging_failed debugfs file creation failed\n");
- return;
- }
- temp = debugfs_create_file("aging_trigger", 0200,
- ctrl->debugfs, ctrl,
- &cpr3_debug_trigger_aging_measurement_fops);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(ctrl, "aging_trigger debugfs file creation failed\n");
- return;
- }
- }
- aggr_dir = debugfs_create_dir("max_aggregated_voltages", ctrl->debugfs);
- if (IS_ERR_OR_NULL(aggr_dir)) {
- cpr3_err(ctrl, "max_aggregated_voltages debugfs directory creation failed\n");
- return;
- }
- temp = debugfs_create_int("floor_volt", 0444, aggr_dir,
- &ctrl->aggr_corner.floor_volt);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(ctrl, "aggr floor_volt debugfs file creation failed\n");
- return;
- }
- temp = debugfs_create_int("ceiling_volt", 0444, aggr_dir,
- &ctrl->aggr_corner.ceiling_volt);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(ctrl, "aggr ceiling_volt debugfs file creation failed\n");
- return;
- }
- temp = debugfs_create_int("open_loop_volt", 0444, aggr_dir,
- &ctrl->aggr_corner.open_loop_volt);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(ctrl, "aggr open_loop_volt debugfs file creation failed\n");
- return;
- }
- temp = debugfs_create_int("last_volt", 0444, aggr_dir,
- &ctrl->aggr_corner.last_volt);
- if (IS_ERR_OR_NULL(temp)) {
- cpr3_err(ctrl, "aggr last_volt debugfs file creation failed\n");
- return;
- }
- for (i = 0; i < ctrl->thread_count; i++)
- cpr3_regulator_debugfs_thread_add(&ctrl->thread[i]);
- }
- static void cpr3_regulator_debugfs_ctrl_remove(struct cpr3_controller *ctrl)
- {
- if (list_empty(&cpr3_controller_list)) {
- debugfs_remove_recursive(cpr3_debugfs_base);
- cpr3_debugfs_base = NULL;
- } else {
- debugfs_remove_recursive(ctrl->debugfs);
- }
- }
- static int cpr3_regulator_init_ctrl_data(struct cpr3_controller *ctrl)
- {
-
- ctrl->aggr_corner.last_volt
- = regulator_get_voltage(ctrl->vdd_regulator);
- if (ctrl->aggr_corner.last_volt < 0) {
- cpr3_err(ctrl, "regulator_get_voltage(vdd) failed, rc=%d\n",
- ctrl->aggr_corner.last_volt);
- return ctrl->aggr_corner.last_volt;
- }
- ctrl->aggr_corner.open_loop_volt = ctrl->aggr_corner.last_volt;
- return 0;
- }
- static int cpr3_regulator_init_vreg_data(struct cpr3_regulator *vreg)
- {
- int i, j;
- bool init_aging;
- vreg->current_corner = CPR3_REGULATOR_CORNER_INVALID;
- vreg->last_closed_loop_corner = CPR3_REGULATOR_CORNER_INVALID;
- init_aging = vreg->aging_allowed && vreg->thread->ctrl->aging_required;
- for (i = 0; i < vreg->corner_count; i++) {
- vreg->corner[i].last_volt = vreg->corner[i].open_loop_volt;
- vreg->corner[i].irq_en = CPR3_IRQ_UP | CPR3_IRQ_DOWN;
- vreg->corner[i].ro_mask = 0;
- for (j = 0; j < CPR3_RO_COUNT; j++) {
- if (vreg->corner[i].target_quot[j] == 0)
- vreg->corner[i].ro_mask |= BIT(j);
- }
- if (init_aging) {
- vreg->corner[i].unaged_floor_volt
- = vreg->corner[i].floor_volt;
- vreg->corner[i].unaged_ceiling_volt
- = vreg->corner[i].ceiling_volt;
- vreg->corner[i].unaged_open_loop_volt
- = vreg->corner[i].open_loop_volt;
- }
- if (vreg->aging_allowed) {
- if (vreg->corner[i].unaged_floor_volt <= 0) {
- cpr3_err(vreg, "invalid unaged_floor_volt[%d] = %d\n",
- i, vreg->corner[i].unaged_floor_volt);
- return -EINVAL;
- }
- if (vreg->corner[i].unaged_ceiling_volt <= 0) {
- cpr3_err(vreg, "invalid unaged_ceiling_volt[%d] = %d\n",
- i, vreg->corner[i].unaged_ceiling_volt);
- return -EINVAL;
- }
- if (vreg->corner[i].unaged_open_loop_volt <= 0) {
- cpr3_err(vreg, "invalid unaged_open_loop_volt[%d] = %d\n",
- i, vreg->corner[i].unaged_open_loop_volt);
- return -EINVAL;
- }
- }
- }
- if (vreg->aging_allowed && vreg->corner[vreg->aging_corner].ceiling_volt
- > vreg->thread->ctrl->aging_ref_volt) {
- cpr3_err(vreg, "aging corner %d ceiling voltage = %d > aging ref voltage = %d uV\n",
- vreg->aging_corner,
- vreg->corner[vreg->aging_corner].ceiling_volt,
- vreg->thread->ctrl->aging_ref_volt);
- return -EINVAL;
- }
- return 0;
- }
- int cpr3_regulator_suspend(struct cpr3_controller *ctrl)
- {
- int rc;
- mutex_lock(&ctrl->lock);
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
- rc = cpr3_ctrl_clear_cpr4_config(ctrl);
- if (rc) {
- cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
- rc);
- mutex_unlock(&ctrl->lock);
- return rc;
- }
- }
- cpr3_ctrl_loop_disable(ctrl);
- if (ctrl->ctrl_type != CPR_CTRL_TYPE_CPRH) {
- rc = cpr3_closed_loop_disable(ctrl);
- if (rc)
- cpr3_err(ctrl, "could not disable CPR, rc=%d\n", rc);
- ctrl->cpr_suspended = true;
- }
- mutex_unlock(&ctrl->lock);
- return 0;
- }
- int cpr3_regulator_resume(struct cpr3_controller *ctrl)
- {
- int rc;
- mutex_lock(&ctrl->lock);
- if (ctrl->ctrl_type != CPR_CTRL_TYPE_CPRH) {
- ctrl->cpr_suspended = false;
- rc = cpr3_regulator_update_ctrl_state(ctrl);
- if (rc)
- cpr3_err(ctrl, "could not enable CPR, rc=%d\n", rc);
- } else {
- cpr3_ctrl_loop_enable(ctrl);
- }
- mutex_unlock(&ctrl->lock);
- return 0;
- }
- static int cpr3_regulator_cpu_hotplug_callback(struct notifier_block *nb,
- unsigned long action, void *hcpu)
- {
- struct cpr3_controller *ctrl = container_of(nb, struct cpr3_controller,
- cpu_hotplug_notifier);
- int cpu = (long)hcpu;
- action &= ~CPU_TASKS_FROZEN;
- if (action == CPU_ONLINE
- && cpumask_test_cpu(cpu, &ctrl->irq_affinity_mask))
- irq_set_affinity(ctrl->irq, &ctrl->irq_affinity_mask);
- return NOTIFY_OK;
- }
- static int cpr3_regulator_validate_controller(struct cpr3_controller *ctrl)
- {
- struct cpr3_thread *thread;
- struct cpr3_regulator *vreg;
- int i, j, allow_boost_vreg_count = 0;
- if (!ctrl->vdd_regulator && ctrl->ctrl_type != CPR_CTRL_TYPE_CPRH) {
- cpr3_err(ctrl, "vdd regulator missing\n");
- return -EINVAL;
- } else if (ctrl->sensor_count <= 0
- || ctrl->sensor_count > CPR3_MAX_SENSOR_COUNT) {
- cpr3_err(ctrl, "invalid CPR sensor count=%d\n",
- ctrl->sensor_count);
- return -EINVAL;
- } else if (!ctrl->sensor_owner) {
- cpr3_err(ctrl, "CPR sensor ownership table missing\n");
- return -EINVAL;
- }
- if (ctrl->aging_required) {
- for (i = 0; i < ctrl->aging_sensor_count; i++) {
- if (ctrl->aging_sensor[i].sensor_id
- >= ctrl->sensor_count) {
- cpr3_err(ctrl, "aging_sensor[%d] id=%u is not in the value range 0-%d",
- i, ctrl->aging_sensor[i].sensor_id,
- ctrl->sensor_count - 1);
- return -EINVAL;
- }
- }
- }
- for (i = 0; i < ctrl->thread_count; i++) {
- thread = &ctrl->thread[i];
- for (j = 0; j < thread->vreg_count; j++) {
- vreg = &thread->vreg[j];
- if (vreg->allow_boost)
- allow_boost_vreg_count++;
- }
- }
- if (allow_boost_vreg_count > 1) {
-
- cpr3_err(ctrl, "Boost feature is enabled for more than one regulator\n");
- return -EINVAL;
- }
- return 0;
- }
- static int cpr3_panic_callback(struct notifier_block *nfb,
- unsigned long event, void *data)
- {
- struct cpr3_controller *ctrl = container_of(nfb,
- struct cpr3_controller, panic_notifier);
- struct cpr3_panic_regs_info *regs_info = ctrl->panic_regs_info;
- struct cpr3_reg_info *reg;
- int i = 0;
- for (i = 0; i < regs_info->reg_count; i++) {
- reg = &(regs_info->regs[i]);
- reg->value = readl_relaxed(reg->virt_addr);
- pr_err("%s[0x%08x] = 0x%08x\n", reg->name, reg->addr,
- reg->value);
- }
-
- mb();
- return NOTIFY_OK;
- }
- int cpr3_regulator_register(struct platform_device *pdev,
- struct cpr3_controller *ctrl)
- {
- struct device *dev = &pdev->dev;
- struct resource *res;
- int i, j, rc;
- if (!dev->of_node) {
- dev_err(dev, "%s: Device tree node is missing\n", __func__);
- return -EINVAL;
- }
- if (!ctrl || !ctrl->name) {
- dev_err(dev, "%s: CPR controller data is missing\n", __func__);
- return -EINVAL;
- }
- rc = cpr3_regulator_validate_controller(ctrl);
- if (rc) {
- cpr3_err(ctrl, "controller validation failed, rc=%d\n", rc);
- return rc;
- }
- mutex_init(&ctrl->lock);
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cpr_ctrl");
- if (!res || !res->start) {
- cpr3_err(ctrl, "CPR controller address is missing\n");
- return -ENXIO;
- }
- ctrl->cpr_ctrl_base = devm_ioremap(dev, res->start, resource_size(res));
- if (cpr3_regulator_cprh_initialized(ctrl)) {
- cpr3_err(ctrl, "CPRh controller already initialized by boot loader\n");
- return -EPERM;
- }
- if (ctrl->aging_possible_mask) {
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "aging_allowed");
- if (!res || !res->start) {
- cpr3_err(ctrl, "CPR aging allowed address is missing\n");
- return -ENXIO;
- }
- ctrl->aging_possible_reg = devm_ioremap(dev, res->start,
- resource_size(res));
- }
- if (ctrl->ctrl_type != CPR_CTRL_TYPE_CPRH) {
- ctrl->irq = platform_get_irq_byname(pdev, "cpr");
- if (ctrl->irq < 0) {
- cpr3_err(ctrl, "missing CPR interrupt\n");
- return ctrl->irq;
- }
- }
- if (ctrl->supports_hw_closed_loop) {
- rc = cpr3_regulator_init_hw_closed_loop_dependencies(pdev,
- ctrl);
- if (rc)
- return rc;
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
- ctrl->ceiling_irq = platform_get_irq_byname(pdev,
- "ceiling");
- if (ctrl->ceiling_irq < 0) {
- cpr3_err(ctrl, "missing ceiling interrupt\n");
- return ctrl->ceiling_irq;
- }
- }
- }
- if (ctrl->ctrl_type != CPR_CTRL_TYPE_CPRH) {
- rc = cpr3_regulator_init_ctrl_data(ctrl);
- if (rc) {
- cpr3_err(ctrl, "CPR controller data initialization failed, rc=%d\n",
- rc);
- return rc;
- }
- }
- for (i = 0; i < ctrl->thread_count; i++) {
- for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
- rc = cpr3_regulator_init_vreg_data(
- &ctrl->thread[i].vreg[j]);
- if (rc)
- return rc;
- cpr3_print_quots(&ctrl->thread[i].vreg[j]);
- }
- }
-
- if (ctrl->aging_required)
- cpr3_regulator_set_aging_ref_adjustment(ctrl, INT_MAX);
- rc = cpr3_regulator_init_ctrl(ctrl);
- if (rc) {
- cpr3_err(ctrl, "CPR controller initialization failed, rc=%d\n",
- rc);
- return rc;
- }
-
- for (i = 0; i < ctrl->thread_count; i++) {
- for (j = 0; j < ctrl->thread[i].vreg_count; j++) {
- rc = cpr3_regulator_vreg_register(
- &ctrl->thread[i].vreg[j]);
- if (rc) {
- cpr3_err(&ctrl->thread[i].vreg[j], "failed to register regulator, rc=%d\n",
- rc);
- goto free_regulators;
- }
- }
- }
- if (ctrl->ctrl_type != CPR_CTRL_TYPE_CPRH) {
- rc = devm_request_threaded_irq(dev, ctrl->irq, NULL,
- cpr3_irq_handler,
- IRQF_ONESHOT |
- IRQF_TRIGGER_RISING,
- "cpr3", ctrl);
- if (rc) {
- cpr3_err(ctrl, "could not request IRQ %d, rc=%d\n",
- ctrl->irq, rc);
- goto free_regulators;
- }
- }
- if (ctrl->supports_hw_closed_loop &&
- ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3) {
- rc = devm_request_threaded_irq(dev, ctrl->ceiling_irq, NULL,
- cpr3_ceiling_irq_handler,
- IRQF_ONESHOT | IRQF_TRIGGER_RISING,
- "cpr3_ceiling", ctrl);
- if (rc) {
- cpr3_err(ctrl, "could not request ceiling IRQ %d, rc=%d\n",
- ctrl->ceiling_irq, rc);
- goto free_regulators;
- }
- }
- if (ctrl->irq && !cpumask_empty(&ctrl->irq_affinity_mask)) {
- irq_set_affinity(ctrl->irq, &ctrl->irq_affinity_mask);
- ctrl->cpu_hotplug_notifier.notifier_call
- = cpr3_regulator_cpu_hotplug_callback;
- register_hotcpu_notifier(&ctrl->cpu_hotplug_notifier);
- }
- mutex_lock(&cpr3_controller_list_mutex);
- cpr3_regulator_debugfs_ctrl_add(ctrl);
- list_add(&ctrl->list, &cpr3_controller_list);
- mutex_unlock(&cpr3_controller_list_mutex);
- if (ctrl->panic_regs_info) {
-
- ctrl->panic_notifier.notifier_call = cpr3_panic_callback;
- atomic_notifier_chain_register(&panic_notifier_list,
- &ctrl->panic_notifier);
- }
- return 0;
- free_regulators:
- for (i = 0; i < ctrl->thread_count; i++)
- for (j = 0; j < ctrl->thread[i].vreg_count; j++)
- if (!IS_ERR_OR_NULL(ctrl->thread[i].vreg[j].rdev))
- regulator_unregister(
- ctrl->thread[i].vreg[j].rdev);
- return rc;
- }
- int cpr3_regulator_unregister(struct cpr3_controller *ctrl)
- {
- int i, j, rc = 0;
- mutex_lock(&cpr3_controller_list_mutex);
- list_del(&ctrl->list);
- cpr3_regulator_debugfs_ctrl_remove(ctrl);
- mutex_unlock(&cpr3_controller_list_mutex);
- if (ctrl->irq && !cpumask_empty(&ctrl->irq_affinity_mask))
- unregister_hotcpu_notifier(&ctrl->cpu_hotplug_notifier);
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR4) {
- rc = cpr3_ctrl_clear_cpr4_config(ctrl);
- if (rc)
- cpr3_err(ctrl, "failed to clear CPR4 configuration,rc=%d\n",
- rc);
- }
- cpr3_ctrl_loop_disable(ctrl);
- cpr3_closed_loop_disable(ctrl);
- if (ctrl->vdd_limit_regulator) {
- regulator_disable(ctrl->vdd_limit_regulator);
- if (ctrl->ctrl_type == CPR_CTRL_TYPE_CPR3)
- msm_spm_avs_disable_irq(0, MSM_SPM_AVS_IRQ_MAX);
- }
- for (i = 0; i < ctrl->thread_count; i++)
- for (j = 0; j < ctrl->thread[i].vreg_count; j++)
- regulator_unregister(ctrl->thread[i].vreg[j].rdev);
- if (ctrl->panic_notifier.notifier_call)
- atomic_notifier_chain_unregister(&panic_notifier_list,
- &ctrl->panic_notifier);
- return 0;
- }
|