Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918// SPDX-License-Identifier: GPL-2.0-or-later//// core.c -- Voltage/Current Regulator framework.//// Copyright 2007, 2008 Wolfson Microelectronics PLC.// Copyright 2008 SlimLogic Ltd.//// Author: Liam Girdwood <lrg@slimlogic.co.uk>
#include <linux/kernel.h>#include <linux/init.h>#include <linux/debugfs.h>#include <linux/device.h>#include <linux/slab.h>#include <linux/async.h>#include <linux/err.h>#include <linux/mutex.h>#include <linux/suspend.h>#include <linux/delay.h>#include <linux/gpio/consumer.h>#include <linux/of.h>#include <linux/reboot.h>#include <linux/regmap.h>#include <linux/regulator/of_regulator.h>#include <linux/regulator/consumer.h>#include <linux/regulator/coupler.h>#include <linux/regulator/driver.h>#include <linux/regulator/machine.h>#include <linux/module.h>#include <linux/workqueue.h>
#define CREATE_TRACE_POINTS#include <trace/events/regulator.h>
#include "dummy.h"#include "internal.h"#include "regnl.h"
static DEFINE_WW_CLASS(regulator_ww_class);static DEFINE_MUTEX(regulator_nesting_mutex);static DEFINE_MUTEX(regulator_list_mutex);static LIST_HEAD(regulator_map_list);static LIST_HEAD(regulator_ena_gpio_list);static LIST_HEAD(regulator_supply_alias_list);static LIST_HEAD(regulator_coupler_list);static bool has_full_constraints;
static const struct bus_type regulator_bus;
static struct dentry *debugfs_root;
/* * struct regulator_map * * Used to provide symbolic supply names to devices. */struct regulator_map { struct list_head list; const char *dev_name; /* The dev_name() for the consumer */ const char *supply; struct regulator_dev *regulator;};
/* * struct regulator_enable_gpio * * Management for shared enable GPIO pin */struct regulator_enable_gpio { struct list_head list; struct gpio_desc *gpiod; u32 enable_count; /* a number of enabled shared GPIO */ u32 request_count; /* a number of requested shared GPIO */};
/* * struct regulator_supply_alias * * Used to map lookups for a supply onto an alternative device. */struct regulator_supply_alias { struct list_head list; struct device *src_dev; const char *src_supply; struct device *alias_dev; const char *alias_supply;};
/* * Work item used to forward regulator events. * * @work: workqueue entry * @rdev: regulator device to notify (consumer receiving the forwarded event) * @event: event code to be forwarded */struct regulator_event_work { struct work_struct work; struct regulator_dev *rdev; unsigned long event;};
static int _regulator_enable(struct regulator *regulator);static int _regulator_is_enabled(struct regulator_dev *rdev);static int _regulator_disable(struct regulator *regulator);static int _regulator_get_error_flags(struct regulator_dev *rdev, unsigned int *flags);static int _regulator_get_current_limit(struct regulator_dev *rdev);static unsigned int _regulator_get_mode(struct regulator_dev *rdev);static int _notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data);static int _regulator_do_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV);static int regulator_balance_voltage(struct regulator_dev *rdev, suspend_state_t state);static struct regulator *create_regulator(struct regulator_dev *rdev, struct device *dev, const char *supply_name);static void destroy_regulator(struct regulator *regulator);static void _regulator_put(struct regulator *regulator);
const char *rdev_get_name(struct regulator_dev *rdev){ if (rdev->constraints && rdev->constraints->name) return rdev->constraints->name; else if (rdev->desc->name) return rdev->desc->name; else return "";}EXPORT_SYMBOL_GPL(rdev_get_name);
static bool have_full_constraints(void){ return has_full_constraints || of_have_populated_dt();}
static bool regulator_ops_is_valid(struct regulator_dev *rdev, int ops){ if (!rdev->constraints) { rdev_err(rdev, "no constraints\n"); return false; }
if (rdev->constraints->valid_ops_mask & ops) return true;
return false;}
/** * regulator_lock_nested - lock a single regulator * @rdev: regulator source * @ww_ctx: w/w mutex acquire context * * This function can be called many times by one task on * a single regulator and its mutex will be locked only * once. If a task, which is calling this function is other * than the one, which initially locked the mutex, it will * wait on mutex. * * Return: 0 on success or a negative error number on failure. */static inline int regulator_lock_nested(struct regulator_dev *rdev, struct ww_acquire_ctx *ww_ctx){ bool lock = false; int ret = 0;
mutex_lock(®ulator_nesting_mutex);
if (!ww_mutex_trylock(&rdev->mutex, ww_ctx)) { if (rdev->mutex_owner == current) rdev->ref_cnt++; else lock = true;
if (lock) { mutex_unlock(®ulator_nesting_mutex); ret = ww_mutex_lock(&rdev->mutex, ww_ctx); mutex_lock(®ulator_nesting_mutex); } } else { lock = true; }
if (lock && ret != -EDEADLK) { rdev->ref_cnt++; rdev->mutex_owner = current; }
mutex_unlock(®ulator_nesting_mutex);
return ret;}
/** * regulator_lock - lock a single regulator * @rdev: regulator source * * This function can be called many times by one task on * a single regulator and its mutex will be locked only * once. If a task, which is calling this function is other * than the one, which initially locked the mutex, it will * wait on mutex. */static void regulator_lock(struct regulator_dev *rdev){ regulator_lock_nested(rdev, NULL);}
/** * regulator_unlock - unlock a single regulator * @rdev: regulator_source * * This function unlocks the mutex when the * reference counter reaches 0. */static void regulator_unlock(struct regulator_dev *rdev){ mutex_lock(®ulator_nesting_mutex);
if (--rdev->ref_cnt == 0) { rdev->mutex_owner = NULL; ww_mutex_unlock(&rdev->mutex); }
WARN_ON_ONCE(rdev->ref_cnt < 0);
mutex_unlock(®ulator_nesting_mutex);}
/** * regulator_lock_two - lock two regulators * @rdev1: first regulator * @rdev2: second regulator * @ww_ctx: w/w mutex acquire context * * Locks both rdevs using the regulator_ww_class. */static void regulator_lock_two(struct regulator_dev *rdev1, struct regulator_dev *rdev2, struct ww_acquire_ctx *ww_ctx){ struct regulator_dev *held, *contended; int ret;
ww_acquire_init(ww_ctx, ®ulator_ww_class);
/* Try to just grab both of them */ ret = regulator_lock_nested(rdev1, ww_ctx); WARN_ON(ret); ret = regulator_lock_nested(rdev2, ww_ctx); if (ret != -EDEADLK) { WARN_ON(ret); goto exit; }
held = rdev1; contended = rdev2; while (true) { regulator_unlock(held);
ww_mutex_lock_slow(&contended->mutex, ww_ctx); contended->ref_cnt++; contended->mutex_owner = current; swap(held, contended); ret = regulator_lock_nested(contended, ww_ctx);
if (ret != -EDEADLK) { WARN_ON(ret); break; } }
exit: ww_acquire_done(ww_ctx);}
/** * regulator_unlock_two - unlock two regulators * @rdev1: first regulator * @rdev2: second regulator * @ww_ctx: w/w mutex acquire context * * The inverse of regulator_lock_two(). */
static void regulator_unlock_two(struct regulator_dev *rdev1, struct regulator_dev *rdev2, struct ww_acquire_ctx *ww_ctx){ regulator_unlock(rdev2); regulator_unlock(rdev1); ww_acquire_fini(ww_ctx);}
static bool regulator_supply_is_couple(struct regulator_dev *rdev){ struct regulator_dev *c_rdev; int i;
for (i = 1; i < rdev->coupling_desc.n_coupled; i++) { c_rdev = rdev->coupling_desc.coupled_rdevs[i];
if (rdev->supply->rdev == c_rdev) return true; }
return false;}
static void regulator_unlock_recursive(struct regulator_dev *rdev, unsigned int n_coupled){ struct regulator_dev *c_rdev, *supply_rdev; int i, supply_n_coupled;
for (i = n_coupled; i > 0; i--) { c_rdev = rdev->coupling_desc.coupled_rdevs[i - 1];
if (!c_rdev) continue;
if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) { supply_rdev = c_rdev->supply->rdev; supply_n_coupled = supply_rdev->coupling_desc.n_coupled;
regulator_unlock_recursive(supply_rdev, supply_n_coupled); }
regulator_unlock(c_rdev); }}
static int regulator_lock_recursive(struct regulator_dev *rdev, struct regulator_dev **new_contended_rdev, struct regulator_dev **old_contended_rdev, struct ww_acquire_ctx *ww_ctx){ struct regulator_dev *c_rdev; int i, err;
for (i = 0; i < rdev->coupling_desc.n_coupled; i++) { c_rdev = rdev->coupling_desc.coupled_rdevs[i];
if (!c_rdev) continue;
if (c_rdev != *old_contended_rdev) { err = regulator_lock_nested(c_rdev, ww_ctx); if (err) { if (err == -EDEADLK) { *new_contended_rdev = c_rdev; goto err_unlock; }
/* shouldn't happen */ WARN_ON_ONCE(err != -EALREADY); } } else { *old_contended_rdev = NULL; }
if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) { err = regulator_lock_recursive(c_rdev->supply->rdev, new_contended_rdev, old_contended_rdev, ww_ctx); if (err) { regulator_unlock(c_rdev); goto err_unlock; } } }
return 0;
err_unlock: regulator_unlock_recursive(rdev, i);
return err;}
/** * regulator_unlock_dependent - unlock regulator's suppliers and coupled * regulators * @rdev: regulator source * @ww_ctx: w/w mutex acquire context * * Unlock all regulators related with rdev by coupling or supplying. */static void regulator_unlock_dependent(struct regulator_dev *rdev, struct ww_acquire_ctx *ww_ctx){ regulator_unlock_recursive(rdev, rdev->coupling_desc.n_coupled); ww_acquire_fini(ww_ctx);}
/** * regulator_lock_dependent - lock regulator's suppliers and coupled regulators * @rdev: regulator source * @ww_ctx: w/w mutex acquire context * * This function as a wrapper on regulator_lock_recursive(), which locks * all regulators related with rdev by coupling or supplying. */static void regulator_lock_dependent(struct regulator_dev *rdev, struct ww_acquire_ctx *ww_ctx){ struct regulator_dev *new_contended_rdev = NULL; struct regulator_dev *old_contended_rdev = NULL; int err;
mutex_lock(®ulator_list_mutex);
ww_acquire_init(ww_ctx, ®ulator_ww_class);
do { if (new_contended_rdev) { ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx); old_contended_rdev = new_contended_rdev; old_contended_rdev->ref_cnt++; old_contended_rdev->mutex_owner = current; }
err = regulator_lock_recursive(rdev, &new_contended_rdev, &old_contended_rdev, ww_ctx);
if (old_contended_rdev) regulator_unlock(old_contended_rdev);
} while (err == -EDEADLK);
ww_acquire_done(ww_ctx);
mutex_unlock(®ulator_list_mutex);}
/* Platform voltage constraint check */int regulator_check_voltage(struct regulator_dev *rdev, int *min_uV, int *max_uV){ BUG_ON(*min_uV > *max_uV);
if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { rdev_err(rdev, "voltage operation not allowed\n"); return -EPERM; }
if (*max_uV > rdev->constraints->max_uV) *max_uV = rdev->constraints->max_uV; if (*min_uV < rdev->constraints->min_uV) *min_uV = rdev->constraints->min_uV;
if (*min_uV > *max_uV) { rdev_err(rdev, "unsupportable voltage range: %d-%duV\n", *min_uV, *max_uV); return -EINVAL; }
return 0;}EXPORT_SYMBOL_GPL(regulator_check_voltage);
/* return 0 if the state is valid */static int regulator_check_states(suspend_state_t state){ return (state > PM_SUSPEND_MAX || state == PM_SUSPEND_TO_IDLE);}
/* Make sure we select a voltage that suits the needs of all * regulator consumers */int regulator_check_consumers(struct regulator_dev *rdev, int *min_uV, int *max_uV, suspend_state_t state){ struct regulator *regulator; struct regulator_voltage *voltage;
list_for_each_entry(regulator, &rdev->consumer_list, list) { voltage = ®ulator->voltage[state]; /* * Assume consumers that didn't say anything are OK * with anything in the constraint range. */ if (!voltage->min_uV && !voltage->max_uV) continue;
if (*max_uV > voltage->max_uV) *max_uV = voltage->max_uV; if (*min_uV < voltage->min_uV) *min_uV = voltage->min_uV; }
if (*min_uV > *max_uV) { rdev_err(rdev, "Restricting voltage, %u-%uuV\n", *min_uV, *max_uV); return -EINVAL; }
return 0;}EXPORT_SYMBOL_GPL(regulator_check_consumers);
/* current constraint check */static int regulator_check_current_limit(struct regulator_dev *rdev, int *min_uA, int *max_uA){ BUG_ON(*min_uA > *max_uA);
if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_CURRENT)) { rdev_err(rdev, "current operation not allowed\n"); return -EPERM; }
if (*max_uA > rdev->constraints->max_uA && rdev->constraints->max_uA) *max_uA = rdev->constraints->max_uA; if (*min_uA < rdev->constraints->min_uA) *min_uA = rdev->constraints->min_uA;
if (*min_uA > *max_uA) { rdev_err(rdev, "unsupportable current range: %d-%duA\n", *min_uA, *max_uA); return -EINVAL; }
return 0;}
/* operating mode constraint check */static int regulator_mode_constrain(struct regulator_dev *rdev, unsigned int *mode){ switch (*mode) { case REGULATOR_MODE_FAST: case REGULATOR_MODE_NORMAL: case REGULATOR_MODE_IDLE: case REGULATOR_MODE_STANDBY: break; default: rdev_err(rdev, "invalid mode %x specified\n", *mode); return -EINVAL; }
if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_MODE)) { rdev_err(rdev, "mode operation not allowed\n"); return -EPERM; }
/* The modes are bitmasks, the most power hungry modes having * the lowest values. If the requested mode isn't supported * try higher modes. */ while (*mode) { if (rdev->constraints->valid_modes_mask & *mode) return 0; *mode /= 2; }
return -EINVAL;}
static inline struct regulator_state *regulator_get_suspend_state(struct regulator_dev *rdev, suspend_state_t state){ if (rdev->constraints == NULL) return NULL;
switch (state) { case PM_SUSPEND_STANDBY: return &rdev->constraints->state_standby; case PM_SUSPEND_MEM: return &rdev->constraints->state_mem; case PM_SUSPEND_MAX: return &rdev->constraints->state_disk; default: return NULL; }}
static const struct regulator_state *regulator_get_suspend_state_check(struct regulator_dev *rdev, suspend_state_t state){ const struct regulator_state *rstate;
rstate = regulator_get_suspend_state(rdev, state); if (rstate == NULL) return NULL;
/* If we have no suspend mode configuration don't set anything; * only warn if the driver implements set_suspend_voltage or * set_suspend_mode callback. */ if (rstate->enabled != ENABLE_IN_SUSPEND && rstate->enabled != DISABLE_IN_SUSPEND) { if (rdev->desc->ops->set_suspend_voltage || rdev->desc->ops->set_suspend_mode) rdev_warn(rdev, "No configuration\n"); return NULL; }
return rstate;}
static ssize_t microvolts_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev); int uV;
regulator_lock(rdev); uV = regulator_get_voltage_rdev(rdev); regulator_unlock(rdev);
if (uV < 0) return uV; return sprintf(buf, "%d\n", uV);}static DEVICE_ATTR_RO(microvolts);
static ssize_t microamps_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev));}static DEVICE_ATTR_RO(microamps);
static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
return sprintf(buf, "%s\n", rdev_get_name(rdev));}static DEVICE_ATTR_RO(name);
static const char *regulator_opmode_to_str(int mode){ switch (mode) { case REGULATOR_MODE_FAST: return "fast"; case REGULATOR_MODE_NORMAL: return "normal"; case REGULATOR_MODE_IDLE: return "idle"; case REGULATOR_MODE_STANDBY: return "standby"; } return "unknown";}
static ssize_t regulator_print_opmode(char *buf, int mode){ return sprintf(buf, "%s\n", regulator_opmode_to_str(mode));}
static ssize_t opmode_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
return regulator_print_opmode(buf, _regulator_get_mode(rdev));}static DEVICE_ATTR_RO(opmode);
static ssize_t regulator_print_state(char *buf, int state){ if (state > 0) return sprintf(buf, "enabled\n"); else if (state == 0) return sprintf(buf, "disabled\n"); else return sprintf(buf, "unknown\n");}
static ssize_t state_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev); ssize_t ret;
regulator_lock(rdev); ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); regulator_unlock(rdev);
return ret;}static DEVICE_ATTR_RO(state);
static ssize_t status_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev); int status; char *label;
status = rdev->desc->ops->get_status(rdev); if (status < 0) return status;
switch (status) { case REGULATOR_STATUS_OFF: label = "off"; break; case REGULATOR_STATUS_ON: label = "on"; break; case REGULATOR_STATUS_ERROR: label = "error"; break; case REGULATOR_STATUS_FAST: label = "fast"; break; case REGULATOR_STATUS_NORMAL: label = "normal"; break; case REGULATOR_STATUS_IDLE: label = "idle"; break; case REGULATOR_STATUS_STANDBY: label = "standby"; break; case REGULATOR_STATUS_BYPASS: label = "bypass"; break; case REGULATOR_STATUS_UNDEFINED: label = "undefined"; break; default: return -ERANGE; }
return sprintf(buf, "%s\n", label);}static DEVICE_ATTR_RO(status);
static ssize_t min_microamps_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints) return sprintf(buf, "constraint not defined\n");
return sprintf(buf, "%d\n", rdev->constraints->min_uA);}static DEVICE_ATTR_RO(min_microamps);
static ssize_t max_microamps_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints) return sprintf(buf, "constraint not defined\n");
return sprintf(buf, "%d\n", rdev->constraints->max_uA);}static DEVICE_ATTR_RO(max_microamps);
static ssize_t min_microvolts_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints) return sprintf(buf, "constraint not defined\n");
return sprintf(buf, "%d\n", rdev->constraints->min_uV);}static DEVICE_ATTR_RO(min_microvolts);
static ssize_t max_microvolts_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
if (!rdev->constraints) return sprintf(buf, "constraint not defined\n");
return sprintf(buf, "%d\n", rdev->constraints->max_uV);}static DEVICE_ATTR_RO(max_microvolts);
static ssize_t requested_microamps_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev); struct regulator *regulator; int uA = 0;
regulator_lock(rdev); list_for_each_entry(regulator, &rdev->consumer_list, list) { if (regulator->enable_count) uA += regulator->uA_load; } regulator_unlock(rdev); return sprintf(buf, "%d\n", uA);}static DEVICE_ATTR_RO(requested_microamps);
static ssize_t num_users_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev); return sprintf(buf, "%d\n", rdev->use_count);}static DEVICE_ATTR_RO(num_users);
static ssize_t type_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
switch (rdev->desc->type) { case REGULATOR_VOLTAGE: return sprintf(buf, "voltage\n"); case REGULATOR_CURRENT: return sprintf(buf, "current\n"); } return sprintf(buf, "unknown\n");}static DEVICE_ATTR_RO(type);
static ssize_t suspend_mem_microvolts_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV);}static DEVICE_ATTR_RO(suspend_mem_microvolts);
static ssize_t suspend_disk_microvolts_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV);}static DEVICE_ATTR_RO(suspend_disk_microvolts);
static ssize_t suspend_standby_microvolts_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV);}static DEVICE_ATTR_RO(suspend_standby_microvolts);
static ssize_t suspend_mem_mode_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
return regulator_print_opmode(buf, rdev->constraints->state_mem.mode);}static DEVICE_ATTR_RO(suspend_mem_mode);
static ssize_t suspend_disk_mode_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
return regulator_print_opmode(buf, rdev->constraints->state_disk.mode);}static DEVICE_ATTR_RO(suspend_disk_mode);
static ssize_t suspend_standby_mode_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
return regulator_print_opmode(buf, rdev->constraints->state_standby.mode);}static DEVICE_ATTR_RO(suspend_standby_mode);
static ssize_t suspend_mem_state_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
return regulator_print_state(buf, rdev->constraints->state_mem.enabled);}static DEVICE_ATTR_RO(suspend_mem_state);
static ssize_t suspend_disk_state_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
return regulator_print_state(buf, rdev->constraints->state_disk.enabled);}static DEVICE_ATTR_RO(suspend_disk_state);
static ssize_t suspend_standby_state_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
return regulator_print_state(buf, rdev->constraints->state_standby.enabled);}static DEVICE_ATTR_RO(suspend_standby_state);
static ssize_t bypass_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev); const char *report; bool bypass; int ret;
ret = rdev->desc->ops->get_bypass(rdev, &bypass);
if (ret != 0) report = "unknown"; else if (bypass) report = "enabled"; else report = "disabled";
return sprintf(buf, "%s\n", report);}static DEVICE_ATTR_RO(bypass);
static ssize_t power_budget_milliwatt_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", rdev->constraints->pw_budget_mW);}static DEVICE_ATTR_RO(power_budget_milliwatt);
static ssize_t power_requested_milliwatt_show(struct device *dev, struct device_attribute *attr, char *buf){ struct regulator_dev *rdev = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", rdev->pw_requested_mW);}static DEVICE_ATTR_RO(power_requested_milliwatt);
#define REGULATOR_ERROR_ATTR(name, bit) \ static ssize_t name##_show(struct device *dev, struct device_attribute *attr, \ char *buf) \ { \ int ret; \ unsigned int flags; \ struct regulator_dev *rdev = dev_get_drvdata(dev); \ ret = _regulator_get_error_flags(rdev, &flags); \ if (ret) \ return ret; \ return sysfs_emit(buf, "%d\n", !!(flags & (bit))); \ } \ static DEVICE_ATTR_RO(name)
REGULATOR_ERROR_ATTR(under_voltage, REGULATOR_ERROR_UNDER_VOLTAGE);REGULATOR_ERROR_ATTR(over_current, REGULATOR_ERROR_OVER_CURRENT);REGULATOR_ERROR_ATTR(regulation_out, REGULATOR_ERROR_REGULATION_OUT);REGULATOR_ERROR_ATTR(fail, REGULATOR_ERROR_FAIL);REGULATOR_ERROR_ATTR(over_temp, REGULATOR_ERROR_OVER_TEMP);REGULATOR_ERROR_ATTR(under_voltage_warn, REGULATOR_ERROR_UNDER_VOLTAGE_WARN);REGULATOR_ERROR_ATTR(over_current_warn, REGULATOR_ERROR_OVER_CURRENT_WARN);REGULATOR_ERROR_ATTR(over_voltage_warn, REGULATOR_ERROR_OVER_VOLTAGE_WARN);REGULATOR_ERROR_ATTR(over_temp_warn, REGULATOR_ERROR_OVER_TEMP_WARN);
/* Calculate the new optimum regulator operating mode based on the new total * consumer load. All locks held by caller */static int drms_uA_update(struct regulator_dev *rdev){ struct regulator *sibling; int current_uA = 0, output_uV, input_uV, err; unsigned int mode;
/* * first check to see if we can set modes at all, otherwise just * tell the consumer everything is OK. */ if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) { rdev_dbg(rdev, "DRMS operation not allowed\n"); return 0; }
if (!rdev->desc->ops->get_optimum_mode && !rdev->desc->ops->set_load) return 0;
if (!rdev->desc->ops->set_mode && !rdev->desc->ops->set_load) return -EINVAL;
/* calc total requested load */ list_for_each_entry(sibling, &rdev->consumer_list, list) { if (sibling->enable_count) current_uA += sibling->uA_load; }
current_uA += rdev->constraints->system_load;
if (rdev->desc->ops->set_load) { /* set the optimum mode for our new total regulator load */ err = rdev->desc->ops->set_load(rdev, current_uA); if (err < 0) rdev_err(rdev, "failed to set load %d: %pe\n", current_uA, ERR_PTR(err)); } else { /* * Unfortunately in some cases the constraints->valid_ops has * REGULATOR_CHANGE_DRMS but there are no valid modes listed. * That's not really legit but we won't consider it a fatal * error here. We'll treat it as if REGULATOR_CHANGE_DRMS * wasn't set. */ if (!rdev->constraints->valid_modes_mask) { rdev_dbg(rdev, "Can change modes; but no valid mode\n"); return 0; }
/* get output voltage */ output_uV = regulator_get_voltage_rdev(rdev);
/* * Don't return an error; if regulator driver cares about * output_uV then it's up to the driver to validate. */ if (output_uV <= 0) rdev_dbg(rdev, "invalid output voltage found\n");
/* get input voltage */ input_uV = 0; if (rdev->supply) input_uV = regulator_get_voltage_rdev(rdev->supply->rdev); if (input_uV <= 0) input_uV = rdev->constraints->input_uV;
/* * Don't return an error; if regulator driver cares about * input_uV then it's up to the driver to validate. */ if (input_uV <= 0) rdev_dbg(rdev, "invalid input voltage found\n");
/* now get the optimum mode for our new total regulator load */ mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, output_uV, current_uA);
/* check the new mode is allowed */ err = regulator_mode_constrain(rdev, &mode); if (err < 0) { rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV: %pe\n", current_uA, input_uV, output_uV, ERR_PTR(err)); return err; }
err = rdev->desc->ops->set_mode(rdev, mode); if (err < 0) rdev_err(rdev, "failed to set optimum mode %x: %pe\n", mode, ERR_PTR(err)); }
return err;}
static int __suspend_set_state(struct regulator_dev *rdev, const struct regulator_state *rstate){ int ret = 0;
if (rstate->enabled == ENABLE_IN_SUSPEND && rdev->desc->ops->set_suspend_enable) ret = rdev->desc->ops->set_suspend_enable(rdev); else if (rstate->enabled == DISABLE_IN_SUSPEND && rdev->desc->ops->set_suspend_disable) ret = rdev->desc->ops->set_suspend_disable(rdev); else /* OK if set_suspend_enable or set_suspend_disable is NULL */ ret = 0;
if (ret < 0) { rdev_err(rdev, "failed to enabled/disable: %pe\n", ERR_PTR(ret)); return ret; }
if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); if (ret < 0) { rdev_err(rdev, "failed to set voltage: %pe\n", ERR_PTR(ret)); return ret; } }
if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); if (ret < 0) { rdev_err(rdev, "failed to set mode: %pe\n", ERR_PTR(ret)); return ret; } }
return ret;}
static int suspend_set_initial_state(struct regulator_dev *rdev){ const struct regulator_state *rstate;
rstate = regulator_get_suspend_state_check(rdev, rdev->constraints->initial_state); if (!rstate) return 0;
return __suspend_set_state(rdev, rstate);}
#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)static void print_constraints_debug(struct regulator_dev *rdev){ struct regulation_constraints *constraints = rdev->constraints; char buf[160] = ""; size_t len = sizeof(buf) - 1; int count = 0; int ret;
if (constraints->min_uV && constraints->max_uV) { if (constraints->min_uV == constraints->max_uV) count += scnprintf(buf + count, len - count, "%d mV ", constraints->min_uV / 1000); else count += scnprintf(buf + count, len - count, "%d <--> %d mV ", constraints->min_uV / 1000, constraints->max_uV / 1000); }
if (!constraints->min_uV || constraints->min_uV != constraints->max_uV) { ret = regulator_get_voltage_rdev(rdev); if (ret > 0) count += scnprintf(buf + count, len - count, "at %d mV ", ret / 1000); }
if (constraints->uV_offset) count += scnprintf(buf + count, len - count, "%dmV offset ", constraints->uV_offset / 1000);
if (constraints->min_uA && constraints->max_uA) { if (constraints->min_uA == constraints->max_uA) count += scnprintf(buf + count, len - count, "%d mA ", constraints->min_uA / 1000); else count += scnprintf(buf + count, len - count, "%d <--> %d mA ", constraints->min_uA / 1000, constraints->max_uA / 1000); }
if (!constraints->min_uA || constraints->min_uA != constraints->max_uA) { ret = _regulator_get_current_limit(rdev); if (ret > 0) count += scnprintf(buf + count, len - count, "at %d mA ", ret / 1000); }
if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) count += scnprintf(buf + count, len - count, "fast "); if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) count += scnprintf(buf + count, len - count, "normal "); if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) count += scnprintf(buf + count, len - count, "idle "); if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) count += scnprintf(buf + count, len - count, "standby ");
if (constraints->pw_budget_mW) count += scnprintf(buf + count, len - count, "%d mW budget ", constraints->pw_budget_mW);
if (!count) count = scnprintf(buf, len, "no parameters"); else --count;
count += scnprintf(buf + count, len - count, ", %s", _regulator_is_enabled(rdev) ? "enabled" : "disabled");
rdev_dbg(rdev, "%s\n", buf);}#else /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */static inline void print_constraints_debug(struct regulator_dev *rdev) {}#endif /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */
static void print_constraints(struct regulator_dev *rdev){ struct regulation_constraints *constraints = rdev->constraints;
print_constraints_debug(rdev);
if ((constraints->min_uV != constraints->max_uV) && !regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) rdev_warn(rdev, "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n");}
static int machine_constraints_voltage(struct regulator_dev *rdev, struct regulation_constraints *constraints){ const struct regulator_ops *ops = rdev->desc->ops; int ret; bool apply_uV;
/* * Decide up front, from the constraints as handed to us, whether * apply_uV needs to run below. The clamping pass right after this * may rewrite constraints->min_uV/max_uV (e.g. the fixed-voltage * autoconfigure case), and we don't want that to change whether * apply_uV fires. */ apply_uV = rdev->constraints->apply_uV && rdev->constraints->min_uV && rdev->constraints->max_uV;
/* * Constrain machine-level voltage specs to fit the actual range * supported by this regulator before apply_uV (below) tries to * force hardware to a value from that range: otherwise apply_uV * can target a constraint value that doesn't correspond to any * real voltage selector and fail registration outright, even * though the clamping pass would have narrowed it to a value * the regulator can actually hit. */ if (ops->list_voltage && rdev->desc->n_voltages) { int count = rdev->desc->n_voltages; int i; int min_uV = INT_MAX; int max_uV = INT_MIN; int cmin = constraints->min_uV; int cmax = constraints->max_uV;
/* it's safe to autoconfigure fixed-voltage supplies * and the constraints are used by list_voltage. */ if (count == 1 && !cmin) { cmin = 1; cmax = INT_MAX; constraints->min_uV = cmin; constraints->max_uV = cmax; }
/* voltage constraints are optional */ if ((cmin == 0) && (cmax == 0)) { /* nothing more to do */
/* else require explicit machine-level constraints */ } else if (cmin <= 0 || cmax <= 0 || cmax < cmin) { rdev_err(rdev, "invalid voltage constraints\n"); return -EINVAL;
/* no need to loop voltages if range is continuous */ } else if (rdev->desc->continuous_voltage_range) { /* nothing more to do */
} else { /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ for (i = 0; i < count; i++) { int value;
value = ops->list_voltage(rdev, i); if (value <= 0) continue;
/* maybe adjust [min_uV..max_uV] */ if (value >= cmin && value < min_uV) min_uV = value; if (value <= cmax && value > max_uV) max_uV = value; }
/* final: [min_uV..max_uV] valid iff constraints valid */ if (max_uV < min_uV) { rdev_err(rdev, "unsupportable voltage constraints %u-%uuV\n", min_uV, max_uV); return -EINVAL; }
/* use regulator's subset of machine constraints */ if (constraints->min_uV < min_uV) { rdev_dbg(rdev, "override min_uV, %d -> %d\n", constraints->min_uV, min_uV); constraints->min_uV = min_uV; } if (constraints->max_uV > max_uV) { rdev_dbg(rdev, "override max_uV, %d -> %d\n", constraints->max_uV, max_uV); constraints->max_uV = max_uV; } } }
/* do we need to apply the constraint voltage */ if (apply_uV) { int target_min, target_max; int current_uV = regulator_get_voltage_rdev(rdev);
if (current_uV == -ENOTRECOVERABLE) { /* This regulator can't be read and must be initialized */ rdev_info(rdev, "Setting %d-%duV\n", rdev->constraints->min_uV, rdev->constraints->max_uV); _regulator_do_set_voltage(rdev, rdev->constraints->min_uV, rdev->constraints->max_uV); current_uV = regulator_get_voltage_rdev(rdev); }
if (current_uV < 0) { if (current_uV != -EPROBE_DEFER) rdev_err(rdev, "failed to get the current voltage: %pe\n", ERR_PTR(current_uV)); return current_uV; }
/* * If we're below the minimum voltage move up to the * minimum voltage, if we're above the maximum voltage * then move down to the maximum. */ target_min = current_uV; target_max = current_uV;
if (current_uV < rdev->constraints->min_uV) { target_min = rdev->constraints->min_uV; target_max = rdev->constraints->min_uV; }
if (current_uV > rdev->constraints->max_uV) { target_min = rdev->constraints->max_uV; target_max = rdev->constraints->max_uV; }
if (target_min != current_uV || target_max != current_uV) { rdev_info(rdev, "Bringing %duV into %d-%duV\n", current_uV, target_min, target_max); ret = _regulator_do_set_voltage( rdev, target_min, target_max); if (ret < 0) { rdev_err(rdev, "failed to apply %d-%duV constraint: %pe\n", target_min, target_max, ERR_PTR(ret)); return ret; } } }
return 0;}
static int machine_constraints_current(struct regulator_dev *rdev, struct regulation_constraints *constraints){ const struct regulator_ops *ops = rdev->desc->ops; int ret;
if (!constraints->min_uA && !constraints->max_uA) return 0;
if (constraints->min_uA > constraints->max_uA) { rdev_err(rdev, "Invalid current constraints\n"); return -EINVAL; }
if (!ops->set_current_limit || !ops->get_current_limit) { rdev_warn(rdev, "Operation of current configuration missing\n"); return 0; }
/* Set regulator current in constraints range */ ret = ops->set_current_limit(rdev, constraints->min_uA, constraints->max_uA); if (ret < 0) { rdev_err(rdev, "Failed to set current constraint, %d\n", ret); return ret; }
return 0;}
static int _regulator_do_enable(struct regulator_dev *rdev);
static int notif_set_limit(struct regulator_dev *rdev, int (*set)(struct regulator_dev *, int, int, bool), int limit, int severity){ bool enable;
if (limit == REGULATOR_NOTIF_LIMIT_DISABLE) { enable = false; limit = 0; } else { enable = true; }
if (limit == REGULATOR_NOTIF_LIMIT_ENABLE) limit = 0;
return set(rdev, limit, severity, enable);}
static int handle_notify_limits(struct regulator_dev *rdev, int (*set)(struct regulator_dev *, int, int, bool), struct notification_limit *limits){ int ret = 0;
if (!set) return -EOPNOTSUPP;
if (limits->prot) ret = notif_set_limit(rdev, set, limits->prot, REGULATOR_SEVERITY_PROT); if (ret) return ret;
if (limits->err) ret = notif_set_limit(rdev, set, limits->err, REGULATOR_SEVERITY_ERR); if (ret) return ret;
if (limits->warn) ret = notif_set_limit(rdev, set, limits->warn, REGULATOR_SEVERITY_WARN);
return ret;}/** * set_machine_constraints - sets regulator constraints * @rdev: regulator source * @is_locked: whether or not this is called with locks held already * * Allows platform initialisation code to define and constrain * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: * Constraints *must* be set by platform code in order for some * regulator operations to proceed i.e. set_voltage, set_current_limit, * set_mode. * * Return: 0 on success or a negative error number on failure. */static int set_machine_constraints(struct regulator_dev *rdev, bool is_locked){ int ret = 0; const struct regulator_ops *ops = rdev->desc->ops;
/* * If there is no mechanism for controlling the regulator then * flag it as always_on so we don't end up duplicating checks * for this so much. Note that we could control the state of * a supply to control the output on a regulator that has no * direct control. */ if (!rdev->ena_pin && !ops->enable) { if (rdev->supply_name && !rdev->supply) return -EPROBE_DEFER;
if (rdev->supply) rdev->constraints->always_on = rdev->supply->rdev->constraints->always_on; else rdev->constraints->always_on = true; }
/* * If we want to enable this regulator, make sure that we know the * supplying regulator. */ if (rdev->constraints->always_on || rdev->constraints->boot_on) { if (rdev->supply_name && !rdev->supply) return -EPROBE_DEFER; }
ret = machine_constraints_voltage(rdev, rdev->constraints); if (ret != 0) return ret;
ret = machine_constraints_current(rdev, rdev->constraints); if (ret != 0) return ret;
if (rdev->constraints->ilim_uA && ops->set_input_current_limit) { ret = ops->set_input_current_limit(rdev, rdev->constraints->ilim_uA); if (ret < 0) { rdev_err(rdev, "failed to set input limit: %pe\n", ERR_PTR(ret)); return ret; } }
/* do we need to setup our suspend state */ if (rdev->constraints->initial_state) { ret = suspend_set_initial_state(rdev); if (ret < 0) { rdev_err(rdev, "failed to set suspend state: %pe\n", ERR_PTR(ret)); return ret; } }
if (rdev->constraints->initial_mode) { if (!ops->set_mode) { rdev_err(rdev, "no set_mode operation\n"); return -EINVAL; }
ret = ops->set_mode(rdev, rdev->constraints->initial_mode); if (ret < 0) { rdev_err(rdev, "failed to set initial mode: %pe\n", ERR_PTR(ret)); return ret; } } else if (rdev->constraints->system_load) { /* * We'll only apply the initial system load if an * initial mode wasn't specified. */ drms_uA_update(rdev); }
if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) && ops->set_ramp_delay) { ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); if (ret < 0) { rdev_err(rdev, "failed to set ramp_delay: %pe\n", ERR_PTR(ret)); return ret; } }
if (rdev->constraints->pull_down && ops->set_pull_down) { ret = ops->set_pull_down(rdev); if (ret < 0) { rdev_err(rdev, "failed to set pull down: %pe\n", ERR_PTR(ret)); return ret; } }
if (rdev->constraints->soft_start && ops->set_soft_start) { ret = ops->set_soft_start(rdev); if (ret < 0) { rdev_err(rdev, "failed to set soft start: %pe\n", ERR_PTR(ret)); return ret; } }
/* * Existing logic does not warn if over_current_protection is given as * a constraint but driver does not support that. I think we should * warn about this type of issues as it is possible someone changes * PMIC on board to another type - and the other PMIC's driver does * not support setting protection. Board composer may happily believe * the DT limits are respected - especially if the new PMIC HW also * supports protection but the driver does not. I won't change the logic * without hearing more experienced opinion on this though. * * If warning is seen as a good idea then we can merge handling the * over-curret protection and detection and get rid of this special * handling. */ if (rdev->constraints->over_current_protection && ops->set_over_current_protection) { int lim = rdev->constraints->over_curr_limits.prot;
ret = ops->set_over_current_protection(rdev, lim, REGULATOR_SEVERITY_PROT, true); if (ret < 0) { rdev_err(rdev, "failed to set over current protection: %pe\n", ERR_PTR(ret)); return ret; } }
if (rdev->constraints->over_current_detection) ret = handle_notify_limits(rdev, ops->set_over_current_protection, &rdev->constraints->over_curr_limits); if (ret) { if (ret != -EOPNOTSUPP) { rdev_err(rdev, "failed to set over current limits: %pe\n", ERR_PTR(ret)); return ret; } rdev_warn(rdev, "IC does not support requested over-current limits\n"); }
if (rdev->constraints->over_voltage_detection) ret = handle_notify_limits(rdev, ops->set_over_voltage_protection, &rdev->constraints->over_voltage_limits); if (ret) { if (ret != -EOPNOTSUPP) { rdev_err(rdev, "failed to set over voltage limits %pe\n", ERR_PTR(ret)); return ret; } rdev_warn(rdev, "IC does not support requested over voltage limits\n"); }
if (rdev->constraints->under_voltage_detection) ret = handle_notify_limits(rdev, ops->set_under_voltage_protection, &rdev->constraints->under_voltage_limits); if (ret) { if (ret != -EOPNOTSUPP) { rdev_err(rdev, "failed to set under voltage limits %pe\n", ERR_PTR(ret)); return ret; } rdev_warn(rdev, "IC does not support requested under voltage limits\n"); }
if (rdev->constraints->over_temp_detection) ret = handle_notify_limits(rdev, ops->set_thermal_protection, &rdev->constraints->temp_limits); if (ret) { if (ret != -EOPNOTSUPP) { rdev_err(rdev, "failed to set temperature limits %pe\n", ERR_PTR(ret)); return ret; } rdev_warn(rdev, "IC does not support requested temperature limits\n"); }
if (rdev->constraints->active_discharge && ops->set_active_discharge) { bool ad_state = rdev->constraints->active_discharge == REGULATOR_ACTIVE_DISCHARGE_ENABLE;
ret = ops->set_active_discharge(rdev, ad_state); if (ret < 0) { rdev_err(rdev, "failed to set active discharge: %pe\n", ERR_PTR(ret)); return ret; } }
/* If the constraints say the regulator should be on at this point * and we have control then make sure it is enabled. */ if (rdev->constraints->always_on || rdev->constraints->boot_on) { bool supply_enabled = false;
/* We have ensured a potential supply has been resolved above. * * If supplying regulator has already been enabled, * it's not intended to have use_count increment * when rdev is only boot-on. */ if (rdev->supply && (rdev->constraints->always_on || !regulator_is_enabled(rdev->supply))) { ret = (is_locked ? _regulator_enable(rdev->supply) : regulator_enable(rdev->supply)); if (ret < 0) { _regulator_put(rdev->supply); rdev->supply = NULL; return ret; } supply_enabled = true; }
ret = _regulator_do_enable(rdev); if (ret < 0 && ret != -EINVAL) { rdev_err(rdev, "failed to enable: %pe\n", ERR_PTR(ret)); if (supply_enabled) regulator_disable(rdev->supply); return ret; }
if (rdev->constraints->always_on) rdev->use_count++; } else if (rdev->desc->off_on_delay) { rdev->last_off = ktime_get(); }
if (!rdev->constraints->pw_budget_mW) rdev->constraints->pw_budget_mW = INT_MAX;
print_constraints(rdev); return 0;}
/** * regulator_event_work_fn - process a deferred regulator event * @work: work_struct queued by the notifier * * Calls the regulator's notifier chain in process context while holding * the rdev lock, then releases the device reference. */static void regulator_event_work_fn(struct work_struct *work){ struct regulator_event_work *rew = container_of(work, struct regulator_event_work, work); struct regulator_dev *rdev = rew->rdev; int ret;
regulator_lock(rdev); ret = regulator_notifier_call_chain(rdev, rew->event, NULL); regulator_unlock(rdev); if (ret == NOTIFY_BAD) dev_err(rdev_get_dev(rdev), "failed to forward regulator event\n");
put_device(rdev_get_dev(rdev)); kfree(rew);}
/** * regulator_event_forward_notifier - notifier callback for supply events * @nb: notifier block embedded in the regulator * @event: regulator event code * @data: unused * * Packages the event into a work item and schedules it in process context. * Takes a reference on @rdev->dev to pin the regulator until the work * completes (see put_device() in the worker). * * Return: NOTIFY_OK on success, NOTIFY_DONE for events that are not forwarded. */static int regulator_event_forward_notifier(struct notifier_block *nb, unsigned long event, void __always_unused *data){ struct regulator_dev *rdev = container_of(nb, struct regulator_dev, supply_fwd_nb); struct regulator_event_work *rew;
switch (event) { case REGULATOR_EVENT_UNDER_VOLTAGE: break; default: /* Only forward allowed events downstream. */ return NOTIFY_DONE; }
rew = kmalloc_obj(*rew, GFP_ATOMIC); if (!rew) return NOTIFY_DONE;
get_device(rdev_get_dev(rdev)); rew->rdev = rdev; rew->event = event; INIT_WORK(&rew->work, regulator_event_work_fn);
queue_work(system_highpri_wq, &rew->work);
return NOTIFY_OK;}
/** * register_regulator_event_forwarding - enable supply event forwarding * @rdev: regulator device * * Registers a notifier on the regulator's supply so that supply events * are forwarded to the consumer regulator via the deferred work handler. * * Return: 0 on success, -EALREADY if already enabled, or a negative error code. */static int register_regulator_event_forwarding(struct regulator_dev *rdev){ int ret;
if (!rdev->supply) return 0; /* top-level regulator: nothing to forward */
if (rdev->supply_fwd_nb.notifier_call) return -EALREADY;
rdev->supply_fwd_nb.notifier_call = regulator_event_forward_notifier;
ret = regulator_register_notifier(rdev->supply, &rdev->supply_fwd_nb); if (ret) { dev_err(&rdev->dev, "failed to register supply notifier: %pe\n", ERR_PTR(ret)); rdev->supply_fwd_nb.notifier_call = NULL; return ret; }
return 0;}
static void unregister_regulator_event_forwarding(struct regulator_dev *rdev){ if (!rdev->supply_fwd_nb.notifier_call) return;
regulator_unregister_notifier(rdev->supply, &rdev->supply_fwd_nb); rdev->supply_fwd_nb.notifier_call = NULL;}
/** * set_supply - set regulator supply regulator * @rdev: regulator (locked) * @supply_rdev: supply regulator (locked)) * * Called by platform initialisation code to set the supply regulator for this * regulator. This ensures that a regulators supply will also be enabled by the * core if it's child is enabled. * * Return: 0 on success or a negative error number on failure. */static int set_supply(struct regulator_dev *rdev, struct regulator_dev *supply_rdev){ int err;
rdev_dbg(rdev, "supplied by %s\n", rdev_get_name(supply_rdev));
if (!try_module_get(supply_rdev->owner)) return -ENODEV;
rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); if (rdev->supply == NULL) { module_put(supply_rdev->owner); err = -ENOMEM; return err; } supply_rdev->open_count++;
return 0;}
/** * set_consumer_device_supply - Bind a regulator to a symbolic supply * @rdev: regulator source * @consumer_dev_name: dev_name() string for device supply applies to * @supply: symbolic name for supply * * Allows platform initialisation code to map physical regulator * sources to symbolic names for supplies for use by devices. Devices * should use these symbolic names to request regulators, avoiding the * need to provide board-specific regulator names as platform data. * * Return: 0 on success or a negative error number on failure. */static int set_consumer_device_supply(struct regulator_dev *rdev, const char *consumer_dev_name, const char *supply){ struct regulator_map *node, *new_node; int has_dev;
if (supply == NULL) return -EINVAL;
if (consumer_dev_name != NULL) has_dev = 1; else has_dev = 0;
new_node = kzalloc_obj(struct regulator_map); if (new_node == NULL) return -ENOMEM;
new_node->regulator = rdev; new_node->supply = supply;
if (has_dev) { new_node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); if (new_node->dev_name == NULL) { kfree(new_node); return -ENOMEM; } }
mutex_lock(®ulator_list_mutex); list_for_each_entry(node, ®ulator_map_list, list) { if (node->dev_name && consumer_dev_name) { if (strcmp(node->dev_name, consumer_dev_name) != 0) continue; } else if (node->dev_name || consumer_dev_name) { continue; }
if (strcmp(node->supply, supply) != 0) continue;
pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", consumer_dev_name, dev_name(&node->regulator->dev), node->regulator->desc->name, supply, dev_name(&rdev->dev), rdev_get_name(rdev)); goto fail; }
list_add(&new_node->list, ®ulator_map_list); mutex_unlock(®ulator_list_mutex);
return 0;
fail: mutex_unlock(®ulator_list_mutex); kfree(new_node->dev_name); kfree(new_node); return -EBUSY;}
static void unset_regulator_supplies(struct regulator_dev *rdev){ struct regulator_map *node, *n;
list_for_each_entry_safe(node, n, ®ulator_map_list, list) { if (rdev == node->regulator) { list_del(&node->list); kfree(node->dev_name); kfree(node); } }}
#ifdef CONFIG_DEBUG_FSstatic ssize_t constraint_flags_read_file(struct file *file, char __user *user_buf, size_t count, loff_t *ppos){ const struct regulator *regulator = file->private_data; const struct regulation_constraints *c = regulator->rdev->constraints; char *buf; ssize_t ret;
if (!c) return 0;
buf = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM;
ret = snprintf(buf, PAGE_SIZE, "always_on: %u\n" "boot_on: %u\n" "apply_uV: %u\n" "ramp_disable: %u\n" "soft_start: %u\n" "pull_down: %u\n" "over_current_protection: %u\n", c->always_on, c->boot_on, c->apply_uV, c->ramp_disable, c->soft_start, c->pull_down, c->over_current_protection);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); kfree(buf);
return ret;}
#endif
static const struct file_operations constraint_flags_fops = {#ifdef CONFIG_DEBUG_FS .open = simple_open, .read = constraint_flags_read_file, .llseek = default_llseek,#endif};
static void link_and_create_debugfs(struct regulator *regulator, struct regulator_dev *rdev, struct device *dev){ int err = 0;
if (dev) { regulator->dev = dev;
/* Add a link to the device sysfs entry */ err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj, regulator->supply_name); if (err) { rdev_dbg(rdev, "could not add device link %s: %pe\n", dev->kobj.name, ERR_PTR(err)); /* non-fatal */ } }
if (err != -EEXIST) { regulator->debugfs = debugfs_create_dir(regulator->supply_name, rdev->debugfs); if (IS_ERR(regulator->debugfs)) { rdev_dbg(rdev, "Failed to create debugfs directory\n"); regulator->debugfs = NULL; } }
if (regulator->debugfs) { debugfs_create_u32("uA_load", 0444, regulator->debugfs, ®ulator->uA_load); debugfs_create_u32("min_uV", 0444, regulator->debugfs, ®ulator->voltage[PM_SUSPEND_ON].min_uV); debugfs_create_u32("max_uV", 0444, regulator->debugfs, ®ulator->voltage[PM_SUSPEND_ON].max_uV); debugfs_create_file("constraint_flags", 0444, regulator->debugfs, regulator, &constraint_flags_fops); }}
static struct regulator *create_regulator(struct regulator_dev *rdev, struct device *dev, const char *supply_name){ struct regulator *regulator;
lockdep_assert_held_once(&rdev->mutex.base);
if (dev) { supply_name = kasprintf(GFP_KERNEL, "%s-%s", dev->kobj.name, supply_name); if (supply_name == NULL) return NULL; } else { supply_name = kstrdup_const(supply_name, GFP_KERNEL); if (supply_name == NULL) return NULL; }
regulator = kzalloc_obj(*regulator); if (regulator == NULL) { kfree_const(supply_name); return NULL; }
regulator->rdev = rdev; regulator->supply_name = supply_name;
list_add(®ulator->list, &rdev->consumer_list);
/* * Check now if the regulator is an always on regulator - if * it is then we don't need to do nearly so much work for * enable/disable calls. */ if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS) && _regulator_is_enabled(rdev)) regulator->always_on = true;
return regulator;}
static int _regulator_get_enable_time(struct regulator_dev *rdev){ if (rdev->constraints && rdev->constraints->enable_time) return rdev->constraints->enable_time; if (rdev->desc->ops->enable_time) return rdev->desc->ops->enable_time(rdev); return rdev->desc->enable_time;}
static struct regulator_supply_alias *regulator_find_supply_alias( struct device *dev, const char *supply){ struct regulator_supply_alias *map;
list_for_each_entry(map, ®ulator_supply_alias_list, list) if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0) return map;
return NULL;}
static void regulator_supply_alias(struct device **dev, const char **supply){ struct regulator_supply_alias *map;
mutex_lock(®ulator_list_mutex); map = regulator_find_supply_alias(*dev, *supply); if (map) { dev_dbg(*dev, "Mapping supply %s to %s,%s\n", *supply, map->alias_supply, dev_name(map->alias_dev)); *dev = map->alias_dev; *supply = map->alias_supply; } mutex_unlock(®ulator_list_mutex);}
static int regulator_match(struct device *dev, const void *data){ struct regulator_dev *r = dev_to_rdev(dev);
return strcmp(rdev_get_name(r), data) == 0;}
static struct regulator_dev *regulator_lookup_by_name(const char *name){ struct device *dev;
dev = class_find_device(®ulator_class, NULL, name, regulator_match);
return dev ? dev_to_rdev(dev) : NULL;}
static struct regulator_dev *regulator_dt_lookup(struct device *dev, const char *supply){ struct regulator_dev *r = NULL;
if (dev_of_node(dev)) { r = of_regulator_dev_lookup(dev, dev_of_node(dev), supply); if (PTR_ERR(r) == -ENODEV) r = NULL; }
return r;}
/** * regulator_dev_lookup - lookup a regulator device. * @dev: device for regulator "consumer". * @supply: Supply name or regulator ID. * * Return: pointer to &struct regulator_dev or ERR_PTR() encoded negative error number. * * If successful, returns a struct regulator_dev that corresponds to the name * @supply and with the embedded struct device refcount incremented by one. * The refcount must be dropped by calling put_device(). * On failure one of the following ERR_PTR() encoded values is returned: * -%ENODEV if lookup fails permanently, -%EPROBE_DEFER if lookup could succeed * in the future. */static struct regulator_dev *regulator_dev_lookup(struct device *dev, const char *supply){ struct regulator_dev *r = NULL; struct regulator_map *map; const char *devname = NULL;
regulator_supply_alias(&dev, &supply);
/* first do a dt based lookup */ r = regulator_dt_lookup(dev, supply); if (r) return r;
/* if not found, try doing it non-dt way */ if (dev) devname = dev_name(dev);
mutex_lock(®ulator_list_mutex); list_for_each_entry(map, ®ulator_map_list, list) { /* If the mapping has a device set up it must match */ if (map->dev_name && (!devname || strcmp(map->dev_name, devname))) continue;
if (strcmp(map->supply, supply) == 0 && get_device(&map->regulator->dev)) { r = map->regulator; break; } } mutex_unlock(®ulator_list_mutex);
if (r) return r;
r = regulator_lookup_by_name(supply); if (r) return r;
return ERR_PTR(-ENODEV);}
static int regulator_resolve_supply(struct regulator_dev *rdev){ struct regulator_dev *r; struct device *dev = rdev->dev.parent; struct ww_acquire_ctx ww_ctx; struct regulator *supply; bool do_final_setup; int ret = 0;
/* No supply to resolve? */ if (!rdev->supply_name) return 0;
/* Supply already resolved? (fast-path without locking contention) */ if (rdev->supply && !rdev->constraints_pending) return 0;
/* first do a dt based lookup on the node described in the virtual * device. */ r = regulator_dt_lookup(&rdev->dev, rdev->supply_name);
/* If regulator not found use usual search path in the parent * device. */ if (!r) r = regulator_dev_lookup(dev, rdev->supply_name);
if (IS_ERR(r)) { ret = PTR_ERR(r);
/* Did the lookup explicitly defer for us? */ if (ret == -EPROBE_DEFER) goto out;
if (have_full_constraints()) { r = dummy_regulator_rdev; if (!r) { ret = -EPROBE_DEFER; goto out; } get_device(&r->dev); } else { dev_err(dev, "Failed to resolve %s-supply for %s\n", rdev->supply_name, rdev->desc->name); ret = -EPROBE_DEFER; goto out; } }
if (r == rdev) { dev_err(dev, "Supply for %s (%s) resolved to itself\n", rdev->desc->name, rdev->supply_name); put_device(&rdev->dev); if (!have_full_constraints()) { ret = -EINVAL; goto out; } r = dummy_regulator_rdev; if (!r) { ret = -EPROBE_DEFER; goto out; } get_device(&r->dev); }
/* * If the supply's parent device is not the same as the * regulator's parent device, then ensure the parent device * is bound before we resolve the supply, in case the parent * device get probe deferred and unregisters the supply. */ if (r->dev.parent && r->dev.parent != rdev->dev.parent) { if (!device_is_bound(r->dev.parent)) { put_device(&r->dev); ret = -EPROBE_DEFER; goto out; } }
/* Recursively resolve the supply of the supply */ ret = regulator_resolve_supply(r); if (ret < 0) { put_device(&r->dev); goto out; }
/* * Recheck rdev->supply with rdev->mutex lock held to avoid a race * between rdev->supply null check and setting rdev->supply in * set_supply() from concurrent tasks. */ regulator_lock_two(rdev, r, &ww_ctx);
/* Supply just resolved by a concurrent task? */ if (rdev->supply) { /* Constraints might still be pending due to concurrency. */ bool done = !rdev->constraints_pending;
supply = rdev->supply;
regulator_unlock_two(rdev, r, &ww_ctx); put_device(&r->dev);
/* * Supply resolved by concurrent task, and constraints set as * well (or not required): fast path. */ if (done) goto out;
do_final_setup = false; } else { ret = set_supply(rdev, r); if (ret < 0) { regulator_unlock_two(rdev, r, &ww_ctx); put_device(&r->dev); goto out; }
supply = rdev->supply;
/* * Automatically register for event forwarding from the new * supply. This creates the downstream propagation link for * events like under-voltage. */ ret = register_regulator_event_forwarding(rdev); if (ret < 0) { rdev_warn(rdev, "Failed to register event forwarding: %pe\n", ERR_PTR(ret));
goto unset_supply; }
regulator_unlock_two(rdev, r, &ww_ctx);
do_final_setup = true; }
/* * Now that we have the supply, we can retry setting the machine * constraints, if necessary. */ regulator_lock_dependent(rdev, &ww_ctx); if (rdev->constraints_pending) { if (!rdev->supply) { /* * Supply could have been released by another task that * failed to set the constraints or event forwarding. */ regulator_unlock_dependent(rdev, &ww_ctx); ret = -EPROBE_DEFER; goto out; }
ret = set_machine_constraints(rdev, true); if (ret < 0) { regulator_unlock_dependent(rdev, &ww_ctx);
rdev_warn(rdev, "Failed to set machine constraints: %pe\n", ERR_PTR(ret));
regulator_lock_two(rdev, r, &ww_ctx);
if (supply != rdev->supply) { /* * Supply could have been released by another * task that got here before us. If it did, it * will have released 'supply' (i.e. the * previous rdev->supply) and we shouldn't do * that again via unset_supply. */ regulator_unlock_two(rdev, r, &ww_ctx); goto out; }
unregister_regulator_event_forwarding(rdev); rdev->constraints_pending = true; goto unset_supply; } rdev->constraints_pending = false; } regulator_unlock_dependent(rdev, &ww_ctx);
if (!do_final_setup) goto out;
/* rdev->supply was created in set_supply() */ link_and_create_debugfs(rdev->supply, rdev->supply->rdev, &rdev->dev);
out: return ret;
unset_supply: lockdep_assert_held_once(&rdev->mutex.base); lockdep_assert_held_once(&r->mutex.base); rdev->supply = NULL; regulator_unlock_two(rdev, supply->rdev, &ww_ctx);
regulator_put(supply);
return ret;}
/* common pre-checks for regulator requests */int _regulator_get_common_check(struct device *dev, const char *id, enum regulator_get_type get_type){ if (get_type >= MAX_GET_TYPE) { dev_err(dev, "invalid type %d in %s\n", get_type, __func__); return -EINVAL; }
if (id == NULL) { dev_err(dev, "regulator request with no identifier\n"); return -EINVAL; }
return 0;}
/** * _regulator_get_common - Common code for regulator requests * @rdev: regulator device pointer as returned by *regulator_dev_lookup() * Its reference count is expected to have been incremented. * @dev: device used for dev_printk messages * @id: Supply name or regulator ID * @get_type: enum regulator_get_type value corresponding to type of request * * Returns: pointer to struct regulator corresponding to @rdev, or ERR_PTR() * encoded error. * * This function should be chained with *regulator_dev_lookup() functions. */struct regulator *_regulator_get_common(struct regulator_dev *rdev, struct device *dev, const char *id, enum regulator_get_type get_type){ struct regulator *regulator; struct device_link *link; int ret;
if (IS_ERR(rdev)) { ret = PTR_ERR(rdev);
/* * If regulator_dev_lookup() fails with error other * than -ENODEV our job here is done, we simply return it. */ if (ret != -ENODEV) return ERR_PTR(ret);
if (!have_full_constraints()) { dev_warn(dev, "incomplete constraints, dummy supplies not allowed (id=%s)\n", id); return ERR_PTR(-ENODEV); }
switch (get_type) { case NORMAL_GET: /* * Assume that a regulator is physically present and * enabled, even if it isn't hooked up, and just * provide a dummy. */ rdev = dummy_regulator_rdev; if (!rdev) return ERR_PTR(-EPROBE_DEFER); dev_warn(dev, "supply %s not found, using dummy regulator\n", id); get_device(&rdev->dev); break;
case EXCLUSIVE_GET: dev_warn(dev, "dummy supplies not allowed for exclusive requests (id=%s)\n", id); fallthrough;
default: return ERR_PTR(-ENODEV); } }
if (rdev->exclusive) { regulator = ERR_PTR(-EPERM); put_device(&rdev->dev); return regulator; }
if (get_type == EXCLUSIVE_GET && rdev->open_count) { regulator = ERR_PTR(-EBUSY); put_device(&rdev->dev); return regulator; }
mutex_lock(®ulator_list_mutex); ret = (rdev->coupling_desc.n_resolved != rdev->coupling_desc.n_coupled); mutex_unlock(®ulator_list_mutex);
if (ret != 0) { regulator = ERR_PTR(-EPROBE_DEFER); put_device(&rdev->dev); return regulator; }
ret = regulator_resolve_supply(rdev); if (ret < 0) { regulator = ERR_PTR(ret); put_device(&rdev->dev); return regulator; }
if (!try_module_get(rdev->owner)) { regulator = ERR_PTR(-EPROBE_DEFER); put_device(&rdev->dev); return regulator; }
regulator_lock(rdev); regulator = create_regulator(rdev, dev, id); regulator_unlock(rdev); if (regulator == NULL) { regulator = ERR_PTR(-ENOMEM); module_put(rdev->owner); put_device(&rdev->dev); return regulator; }
link_and_create_debugfs(regulator, rdev, dev);
rdev->open_count++; if (get_type == EXCLUSIVE_GET) { rdev->exclusive = 1;
ret = _regulator_is_enabled(rdev); if (ret > 0) { rdev->use_count = 1; regulator->enable_count = 1;
/* Propagate the regulator state to its supply */ if (rdev->supply) { ret = regulator_enable(rdev->supply); if (ret < 0) { destroy_regulator(regulator); module_put(rdev->owner); put_device(&rdev->dev); return ERR_PTR(ret); } } } else { rdev->use_count = 0; regulator->enable_count = 0; } }
link = device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS); if (!IS_ERR_OR_NULL(link)) regulator->device_link = true;
return regulator;}
/* Internal regulator request function */struct regulator *_regulator_get(struct device *dev, const char *id, enum regulator_get_type get_type){ struct regulator_dev *rdev; int ret;
ret = _regulator_get_common_check(dev, id, get_type); if (ret) return ERR_PTR(ret);
rdev = regulator_dev_lookup(dev, id); return _regulator_get_common(rdev, dev, id, get_type);}
/** * regulator_get - lookup and obtain a reference to a regulator. * @dev: device for regulator "consumer" * @id: Supply name or regulator ID. * * Use of supply names configured via set_consumer_device_supply() is * strongly encouraged. It is recommended that the supply name used * should match the name used for the supply and/or the relevant * device pins in the datasheet. * * Return: Pointer to a &struct regulator corresponding to the regulator * producer, or an ERR_PTR() encoded negative error number. */struct regulator *regulator_get(struct device *dev, const char *id){ return _regulator_get(dev, id, NORMAL_GET);}EXPORT_SYMBOL_GPL(regulator_get);
/** * regulator_get_exclusive - obtain exclusive access to a regulator. * @dev: device for regulator "consumer" * @id: Supply name or regulator ID. * * Other consumers will be unable to obtain this regulator while this * reference is held and the use count for the regulator will be * initialised to reflect the current state of the regulator. * * This is intended for use by consumers which cannot tolerate shared * use of the regulator such as those which need to force the * regulator off for correct operation of the hardware they are * controlling. * * Use of supply names configured via set_consumer_device_supply() is * strongly encouraged. It is recommended that the supply name used * should match the name used for the supply and/or the relevant * device pins in the datasheet. * * Return: Pointer to a &struct regulator corresponding to the regulator * producer, or an ERR_PTR() encoded negative error number. */struct regulator *regulator_get_exclusive(struct device *dev, const char *id){ return _regulator_get(dev, id, EXCLUSIVE_GET);}EXPORT_SYMBOL_GPL(regulator_get_exclusive);
/** * regulator_get_optional - obtain optional access to a regulator. * @dev: device for regulator "consumer" * @id: Supply name or regulator ID. * * This is intended for use by consumers for devices which can have * some supplies unconnected in normal use, such as some MMC devices. * It can allow the regulator core to provide stub supplies for other * supplies requested using normal regulator_get() calls without * disrupting the operation of drivers that can handle absent * supplies. * * Use of supply names configured via set_consumer_device_supply() is * strongly encouraged. It is recommended that the supply name used * should match the name used for the supply and/or the relevant * device pins in the datasheet. * * Return: Pointer to a &struct regulator corresponding to the regulator * producer, or an ERR_PTR() encoded negative error number. */struct regulator *regulator_get_optional(struct device *dev, const char *id){ return _regulator_get(dev, id, OPTIONAL_GET);}EXPORT_SYMBOL_GPL(regulator_get_optional);
static void destroy_regulator(struct regulator *regulator){ struct regulator_dev *rdev = regulator->rdev;
debugfs_remove_recursive(regulator->debugfs);
if (regulator->dev) { if (regulator->device_link) device_link_remove(regulator->dev, &rdev->dev);
/* remove any sysfs entries */ sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); }
regulator_lock(rdev); list_del(®ulator->list);
rdev->open_count--; rdev->exclusive = 0; regulator_unlock(rdev);
kfree_const(regulator->supply_name); kfree(regulator);}
/* regulator_list_mutex lock held by regulator_put() */static void _regulator_put(struct regulator *regulator){ struct regulator_dev *rdev;
if (IS_ERR_OR_NULL(regulator)) return;
lockdep_assert_held_once(®ulator_list_mutex);
/* Docs say you must disable before calling regulator_put() */ WARN_ON(regulator->enable_count);
rdev = regulator->rdev;
destroy_regulator(regulator);
module_put(rdev->owner); put_device(&rdev->dev);}
/** * regulator_put - "free" the regulator source * @regulator: regulator source * * Note: drivers must ensure that all regulator_enable calls made on this * regulator source are balanced by regulator_disable calls prior to calling * this function. */void regulator_put(struct regulator *regulator){ mutex_lock(®ulator_list_mutex); _regulator_put(regulator); mutex_unlock(®ulator_list_mutex);}EXPORT_SYMBOL_GPL(regulator_put);
/** * regulator_register_supply_alias - Provide device alias for supply lookup * * @dev: device that will be given as the regulator "consumer" * @id: Supply name or regulator ID * @alias_dev: device that should be used to lookup the supply * @alias_id: Supply name or regulator ID that should be used to lookup the * supply * * All lookups for id on dev will instead be conducted for alias_id on * alias_dev. * * Return: 0 on success or a negative error number on failure. */int regulator_register_supply_alias(struct device *dev, const char *id, struct device *alias_dev, const char *alias_id){ struct regulator_supply_alias *map; struct regulator_supply_alias *new_map;
new_map = kzalloc_obj(struct regulator_supply_alias); if (!new_map) return -ENOMEM;
mutex_lock(®ulator_list_mutex); map = regulator_find_supply_alias(dev, id); if (map) { mutex_unlock(®ulator_list_mutex); kfree(new_map); return -EEXIST; }
new_map->src_dev = dev; new_map->src_supply = id; new_map->alias_dev = alias_dev; new_map->alias_supply = alias_id; list_add(&new_map->list, ®ulator_supply_alias_list); mutex_unlock(®ulator_list_mutex); pr_info("Adding alias for supply %s,%s -> %s,%s\n", id, dev_name(dev), alias_id, dev_name(alias_dev));
return 0;}EXPORT_SYMBOL_GPL(regulator_register_supply_alias);
/** * regulator_unregister_supply_alias - Remove device alias * * @dev: device that will be given as the regulator "consumer" * @id: Supply name or regulator ID * * Remove a lookup alias if one exists for id on dev. */void regulator_unregister_supply_alias(struct device *dev, const char *id){ struct regulator_supply_alias *map;
mutex_lock(®ulator_list_mutex); map = regulator_find_supply_alias(dev, id); if (map) { list_del(&map->list); kfree(map); } mutex_unlock(®ulator_list_mutex);}EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias);
/** * regulator_bulk_register_supply_alias - register multiple aliases * * @dev: device that will be given as the regulator "consumer" * @id: List of supply names or regulator IDs * @alias_dev: device that should be used to lookup the supply * @alias_id: List of supply names or regulator IDs that should be used to * lookup the supply * @num_id: Number of aliases to register * * This helper function allows drivers to register several supply * aliases in one operation. If any of the aliases cannot be * registered any aliases that were registered will be removed * before returning to the caller. * * Return: 0 on success or a negative error number on failure. */int regulator_bulk_register_supply_alias(struct device *dev, const char *const *id, struct device *alias_dev, const char *const *alias_id, int num_id){ int i; int ret;
for (i = 0; i < num_id; ++i) { ret = regulator_register_supply_alias(dev, id[i], alias_dev, alias_id[i]); if (ret < 0) goto err; }
return 0;
err: dev_err(dev, "Failed to create supply alias %s,%s -> %s,%s\n", id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
while (--i >= 0) regulator_unregister_supply_alias(dev, id[i]);
return ret;}EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias);
/** * regulator_bulk_unregister_supply_alias - unregister multiple aliases * * @dev: device that will be given as the regulator "consumer" * @id: List of supply names or regulator IDs * @num_id: Number of aliases to unregister * * This helper function allows drivers to unregister several supply * aliases in one operation. */void regulator_bulk_unregister_supply_alias(struct device *dev, const char *const *id, int num_id){ int i;
for (i = 0; i < num_id; ++i) regulator_unregister_supply_alias(dev, id[i]);}EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias);
/* Manage enable GPIO list. Same GPIO pin can be shared among regulators */static int regulator_ena_gpio_request(struct regulator_dev *rdev, const struct regulator_config *config){ struct regulator_enable_gpio *pin, *new_pin; struct gpio_desc *gpiod;
gpiod = config->ena_gpiod; new_pin = kzalloc_obj(*new_pin);
mutex_lock(®ulator_list_mutex);
if (gpiod_is_shared(gpiod)) /* * The sharing of this GPIO pin is managed internally by * GPIOLIB. We don't need to keep track of its enable count. */ goto skip_compare;
list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { if (gpiod_is_equal(pin->gpiod, gpiod)) { rdev_dbg(rdev, "GPIO is already used\n"); goto update_ena_gpio_to_rdev; } }
if (new_pin == NULL) { mutex_unlock(®ulator_list_mutex); return -ENOMEM; }
skip_compare: pin = new_pin; new_pin = NULL;
pin->gpiod = gpiod; list_add(&pin->list, ®ulator_ena_gpio_list);
update_ena_gpio_to_rdev: pin->request_count++; rdev->ena_pin = pin;
mutex_unlock(®ulator_list_mutex); kfree(new_pin);
return 0;}
static void regulator_ena_gpio_free(struct regulator_dev *rdev){ struct regulator_enable_gpio *pin, *n;
if (!rdev->ena_pin) return;
/* Free the GPIO only in case of no use */ list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { if (pin != rdev->ena_pin) continue;
if (--pin->request_count) break;
gpiod_put(pin->gpiod); list_del(&pin->list); kfree(pin); break; }
rdev->ena_pin = NULL;}
/** * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control * @rdev: regulator_dev structure * @enable: enable GPIO at initial use? * * GPIO is enabled in case of initial use. (enable_count is 0) * GPIO is disabled when it is not shared any more. (enable_count <= 1) * * Return: 0 on success or a negative error number on failure. */static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable){ struct regulator_enable_gpio *pin = rdev->ena_pin; int ret;
if (!pin) return -EINVAL;
if (enable) { /* Enable GPIO at initial use */ if (pin->enable_count == 0) { ret = gpiod_set_value_cansleep(pin->gpiod, 1); if (ret) return ret; }
pin->enable_count++; } else { if (pin->enable_count > 1) { pin->enable_count--; return 0; }
/* Disable GPIO if not used */ if (pin->enable_count <= 1) { ret = gpiod_set_value_cansleep(pin->gpiod, 0); if (ret) return ret;
pin->enable_count = 0; } }
return 0;}
/** * _regulator_check_status_enabled - check if regulator status can be * interpreted as "regulator is enabled" * @rdev: the regulator device to check * * Return: * * 1 - if status shows regulator is in enabled state * * 0 - if not enabled state * * Error Value - as received from ops->get_status() */static inline int _regulator_check_status_enabled(struct regulator_dev *rdev){ int ret = rdev->desc->ops->get_status(rdev);
if (ret < 0) { rdev_info(rdev, "get_status returned error: %d\n", ret); return ret; }
switch (ret) { case REGULATOR_STATUS_OFF: case REGULATOR_STATUS_ERROR: case REGULATOR_STATUS_UNDEFINED: return 0; default: return 1; }}
static int _regulator_do_enable(struct regulator_dev *rdev){ int ret, delay;
/* Query before enabling in case configuration dependent. */ ret = _regulator_get_enable_time(rdev); if (ret >= 0) { delay = ret; } else { rdev_warn(rdev, "enable_time() failed: %pe\n", ERR_PTR(ret)); delay = 0; }
trace_regulator_enable(rdev_get_name(rdev));
if (rdev->desc->off_on_delay) { /* if needed, keep a distance of off_on_delay from last time * this regulator was disabled. */ ktime_t end = ktime_add_us(rdev->last_off, rdev->desc->off_on_delay); s64 remaining = ktime_us_delta(end, ktime_get_boottime());
if (remaining > 0) fsleep(remaining); }
if (rdev->ena_pin) { if (!rdev->ena_gpio_state) { ret = regulator_ena_gpio_ctrl(rdev, true); if (ret < 0) return ret; rdev->ena_gpio_state = 1; } } else if (rdev->desc->ops->enable) { ret = rdev->desc->ops->enable(rdev); if (ret < 0) return ret; } else { return -EINVAL; }
/* Allow the regulator to ramp; it would be useful to extend * this for bulk operations so that the regulators can ramp * together. */ trace_regulator_enable_delay(rdev_get_name(rdev));
/* If poll_enabled_time is set, poll up to the delay calculated * above, delaying poll_enabled_time uS to check if the regulator * actually got enabled. * If the regulator isn't enabled after our delay helper has expired, * return -ETIMEDOUT. */ if (rdev->desc->poll_enabled_time) { int time_remaining = delay;
while (time_remaining > 0) { fsleep(rdev->desc->poll_enabled_time);
if (rdev->desc->ops->get_status) { ret = _regulator_check_status_enabled(rdev); if (ret < 0) return ret; else if (ret) break; } else if (rdev->desc->ops->is_enabled(rdev)) break;
time_remaining -= rdev->desc->poll_enabled_time; }
if (time_remaining <= 0) { rdev_err(rdev, "Enabled check timed out\n"); return -ETIMEDOUT; } } else { fsleep(delay); }
trace_regulator_enable_complete(rdev_get_name(rdev));
return 0;}
/** * _regulator_handle_consumer_enable - handle that a consumer enabled * @regulator: regulator source * * Some things on a regulator consumer (like the contribution towards total * load on the regulator) only have an effect when the consumer wants the * regulator enabled. Explained in example with two consumers of the same * regulator: * consumer A: set_load(100); => total load = 0 * consumer A: regulator_enable(); => total load = 100 * consumer B: set_load(1000); => total load = 100 * consumer B: regulator_enable(); => total load = 1100 * consumer A: regulator_disable(); => total_load = 1000 * * This function (together with _regulator_handle_consumer_disable) is * responsible for keeping track of the refcount for a given regulator consumer * and applying / unapplying these things. * * Return: 0 on success or negative error number on failure. */static int _regulator_handle_consumer_enable(struct regulator *regulator){ int ret; struct regulator_dev *rdev = regulator->rdev;
lockdep_assert_held_once(&rdev->mutex.base);
regulator->enable_count++; if (regulator->uA_load && regulator->enable_count == 1) { ret = drms_uA_update(rdev); if (ret) regulator->enable_count--; return ret; }
return 0;}
/** * _regulator_handle_consumer_disable - handle that a consumer disabled * @regulator: regulator source * * The opposite of _regulator_handle_consumer_enable(). * * Return: 0 on success or a negative error number on failure. */static int _regulator_handle_consumer_disable(struct regulator *regulator){ struct regulator_dev *rdev = regulator->rdev;
lockdep_assert_held_once(&rdev->mutex.base);
if (!regulator->enable_count) { rdev_err(rdev, "Underflow of regulator enable count\n"); return -EINVAL; }
regulator->enable_count--; if (regulator->uA_load && regulator->enable_count == 0) return drms_uA_update(rdev);
return 0;}
/* locks held by regulator_enable() */static int _regulator_enable(struct regulator *regulator){ struct regulator_dev *rdev = regulator->rdev; int ret;
lockdep_assert_held_once(&rdev->mutex.base);
if (rdev->use_count == 0 && rdev->supply) { ret = _regulator_enable(rdev->supply); if (ret < 0) return ret; }
/* balance only if there are regulators coupled */ if (rdev->coupling_desc.n_coupled > 1) { ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON); if (ret < 0) goto err_disable_supply; }
ret = _regulator_handle_consumer_enable(regulator); if (ret < 0) goto err_disable_supply;
if (rdev->use_count == 0) { /* * The regulator may already be enabled if it's not switchable * or was left on */ ret = _regulator_is_enabled(rdev); if (ret == -EINVAL || ret == 0) { if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) { ret = -EPERM; goto err_consumer_disable; }
ret = _regulator_do_enable(rdev); if (ret < 0) goto err_consumer_disable;
_notifier_call_chain(rdev, REGULATOR_EVENT_ENABLE, NULL); } else if (ret < 0) { rdev_err(rdev, "is_enabled() failed: %pe\n", ERR_PTR(ret)); goto err_consumer_disable; } /* Fallthrough on positive return values - already enabled */ }
if (regulator->enable_count == 1) rdev->use_count++;
return 0;
err_consumer_disable: _regulator_handle_consumer_disable(regulator);
err_disable_supply: if (rdev->use_count == 0 && rdev->supply) _regulator_disable(rdev->supply);
return ret;}
/** * regulator_enable - enable regulator output * @regulator: regulator source * * Request that the regulator be enabled with the regulator output at * the predefined voltage or current value. Calls to regulator_enable() * must be balanced with calls to regulator_disable(). * * NOTE: the output value can be set by other drivers, boot loader or may be * hardwired in the regulator. * * Return: 0 on success or a negative error number on failure. */int regulator_enable(struct regulator *regulator){ struct regulator_dev *rdev = regulator->rdev; struct ww_acquire_ctx ww_ctx; int ret;
regulator_lock_dependent(rdev, &ww_ctx); ret = _regulator_enable(regulator); regulator_unlock_dependent(rdev, &ww_ctx);
return ret;}EXPORT_SYMBOL_GPL(regulator_enable);
static int _regulator_do_disable(struct regulator_dev *rdev){ int ret;
trace_regulator_disable(rdev_get_name(rdev));
if (rdev->ena_pin) { if (rdev->ena_gpio_state) { ret = regulator_ena_gpio_ctrl(rdev, false); if (ret < 0) return ret; rdev->ena_gpio_state = 0; }
} else if (rdev->desc->ops->disable) { ret = rdev->desc->ops->disable(rdev); if (ret != 0) return ret; }
if (rdev->desc->off_on_delay) rdev->last_off = ktime_get_boottime();
trace_regulator_disable_complete(rdev_get_name(rdev));
return 0;}
/* locks held by regulator_disable() */static int _regulator_disable(struct regulator *regulator){ struct regulator_dev *rdev = regulator->rdev; int ret = 0;
lockdep_assert_held_once(&rdev->mutex.base);
if (WARN(regulator->enable_count == 0, "unbalanced disables for %s\n", rdev_get_name(rdev))) return -EIO;
if (regulator->enable_count == 1) { /* disabling last enable_count from this regulator */ /* are we the last user and permitted to disable ? */ if (rdev->use_count == 1 && (rdev->constraints && !rdev->constraints->always_on)) {
/* we are last user */ if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) { ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_DISABLE, NULL); if (ret & NOTIFY_STOP_MASK) return -EINVAL;
ret = _regulator_do_disable(rdev); if (ret < 0) { rdev_err(rdev, "failed to disable: %pe\n", ERR_PTR(ret)); _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_DISABLE, NULL); return ret; } _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, NULL); }
rdev->use_count = 0; } else if (rdev->use_count > 1) { rdev->use_count--; } }
if (ret == 0) ret = _regulator_handle_consumer_disable(regulator);
if (ret == 0 && rdev->coupling_desc.n_coupled > 1) ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);
if (ret == 0 && rdev->use_count == 0 && rdev->supply) ret = _regulator_disable(rdev->supply);
return ret;}
/** * regulator_disable - disable regulator output * @regulator: regulator source * * Disable the regulator output voltage or current. Calls to * regulator_enable() must be balanced with calls to * regulator_disable(). * * NOTE: this will only disable the regulator output if no other consumer * devices have it enabled, the regulator device supports disabling and * machine constraints permit this operation. * * Return: 0 on success or a negative error number on failure. */int regulator_disable(struct regulator *regulator){ struct regulator_dev *rdev = regulator->rdev; struct ww_acquire_ctx ww_ctx; int ret;
regulator_lock_dependent(rdev, &ww_ctx); ret = _regulator_disable(regulator); regulator_unlock_dependent(rdev, &ww_ctx);
return ret;}EXPORT_SYMBOL_GPL(regulator_disable);
/* locks held by regulator_force_disable() */static int _regulator_force_disable(struct regulator_dev *rdev){ int ret = 0;
lockdep_assert_held_once(&rdev->mutex.base);
ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | REGULATOR_EVENT_PRE_DISABLE, NULL); if (ret & NOTIFY_STOP_MASK) return -EINVAL;
ret = _regulator_do_disable(rdev); if (ret < 0) { rdev_err(rdev, "failed to force disable: %pe\n", ERR_PTR(ret)); _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | REGULATOR_EVENT_ABORT_DISABLE, NULL); return ret; }
_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | REGULATOR_EVENT_DISABLE, NULL);
return 0;}
/** * regulator_force_disable - force disable regulator output * @regulator: regulator source * * Forcibly disable the regulator output voltage or current. * NOTE: this *will* disable the regulator output even if other consumer * devices have it enabled. This should be used for situations when device * damage will likely occur if the regulator is not disabled (e.g. over temp). * * Return: 0 on success or a negative error number on failure. */int regulator_force_disable(struct regulator *regulator){ struct regulator_dev *rdev = regulator->rdev; struct ww_acquire_ctx ww_ctx; int ret;
regulator_lock_dependent(rdev, &ww_ctx);
ret = _regulator_force_disable(regulator->rdev);
if (rdev->coupling_desc.n_coupled > 1) regulator_balance_voltage(rdev, PM_SUSPEND_ON);
if (regulator->uA_load) { regulator->uA_load = 0; ret = drms_uA_update(rdev); }
if (rdev->use_count != 0 && rdev->supply) _regulator_disable(rdev->supply);
regulator_unlock_dependent(rdev, &ww_ctx);
return ret;}EXPORT_SYMBOL_GPL(regulator_force_disable);
static void regulator_disable_work(struct work_struct *work){ struct regulator_dev *rdev = container_of(work, struct regulator_dev, disable_work.work); struct ww_acquire_ctx ww_ctx; int count, i, ret; struct regulator *regulator; int total_count = 0;
regulator_lock_dependent(rdev, &ww_ctx);
/* * Workqueue functions queue the new work instance while the previous * work instance is being processed. Cancel the queued work instance * as the work instance under processing does the job of the queued * work instance. */ cancel_delayed_work(&rdev->disable_work);
list_for_each_entry(regulator, &rdev->consumer_list, list) { count = regulator->deferred_disables;
if (!count) continue;
total_count += count; regulator->deferred_disables = 0;
for (i = 0; i < count; i++) { ret = _regulator_disable(regulator); if (ret != 0) rdev_err(rdev, "Deferred disable failed: %pe\n", ERR_PTR(ret)); } } WARN_ON(!total_count);
if (rdev->coupling_desc.n_coupled > 1) regulator_balance_voltage(rdev, PM_SUSPEND_ON);
regulator_unlock_dependent(rdev, &ww_ctx);}
/** * regulator_disable_deferred - disable regulator output with delay * @regulator: regulator source * @ms: milliseconds until the regulator is disabled * * Execute regulator_disable() on the regulator after a delay. This * is intended for use with devices that require some time to quiesce. * * NOTE: this will only disable the regulator output if no other consumer * devices have it enabled, the regulator device supports disabling and * machine constraints permit this operation. * * Return: 0 on success or a negative error number on failure. */int regulator_disable_deferred(struct regulator *regulator, int ms){ struct regulator_dev *rdev = regulator->rdev;
if (!ms) return regulator_disable(regulator);
regulator_lock(rdev); regulator->deferred_disables++; mod_delayed_work(system_power_efficient_wq, &rdev->disable_work, msecs_to_jiffies(ms)); regulator_unlock(rdev);
return 0;}EXPORT_SYMBOL_GPL(regulator_disable_deferred);
static int _regulator_is_enabled(struct regulator_dev *rdev){ /* A GPIO control always takes precedence */ if (rdev->ena_pin) return rdev->ena_gpio_state;
/* If we don't know then assume that the regulator is always on */ if (!rdev->desc->ops->is_enabled) return 1;
return rdev->desc->ops->is_enabled(rdev);}
static int _regulator_list_voltage(struct regulator_dev *rdev, unsigned selector, int lock){ const struct regulator_ops *ops = rdev->desc->ops; int ret;
if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) return rdev->desc->fixed_uV;
if (ops->list_voltage) { if (selector >= rdev->desc->n_voltages) return -EINVAL; if (selector < rdev->desc->linear_min_sel) return 0; if (lock) regulator_lock(rdev); ret = ops->list_voltage(rdev, selector); if (lock) regulator_unlock(rdev); } else if (rdev->is_switch && rdev->supply) { ret = _regulator_list_voltage(rdev->supply->rdev, selector, lock); } else { return -EINVAL; }
if (ret > 0) { if (ret < rdev->constraints->min_uV) ret = 0; else if (ret > rdev->constraints->max_uV) ret = 0; }
return ret;}
/** * regulator_is_enabled - is the regulator output enabled * @regulator: regulator source * * Note that the device backing this regulator handle can have multiple * users, so it might be enabled even if regulator_enable() was never * called for this particular source. * * Return: Positive if the regulator driver backing the source/client * has requested that the device be enabled, zero if it hasn't, * else a negative error number. */int regulator_is_enabled(struct regulator *regulator){ int ret;
if (regulator->always_on) return 1;
regulator_lock(regulator->rdev); ret = _regulator_is_enabled(regulator->rdev); regulator_unlock(regulator->rdev);
return ret;}EXPORT_SYMBOL_GPL(regulator_is_enabled);
/** * regulator_count_voltages - count regulator_list_voltage() selectors * @regulator: regulator source * * Return: Number of selectors for @regulator, or negative error number. * * Selectors are numbered starting at zero, and typically correspond to * bitfields in hardware registers. */int regulator_count_voltages(struct regulator *regulator){ struct regulator_dev *rdev = regulator->rdev;
if (rdev->desc->n_voltages) return rdev->desc->n_voltages;
if (!rdev->is_switch || !rdev->supply) return -EINVAL;
return regulator_count_voltages(rdev->supply);}EXPORT_SYMBOL_GPL(regulator_count_voltages);
/** * regulator_list_voltage - enumerate supported voltages * @regulator: regulator source * @selector: identify voltage to list * Context: can sleep * * Return: Voltage for @selector that can be passed to regulator_set_voltage(), * 0 if @selector can't be used on this system, or a negative error * number on failure. */int regulator_list_voltage(struct regulator *regulator, unsigned selector){ return _regulator_list_voltage(regulator->rdev, selector, 1);}EXPORT_SYMBOL_GPL(regulator_list_voltage);
/** * regulator_get_regmap - get the regulator's register map * @regulator: regulator source * * Return: Pointer to the &struct regmap for @regulator, or ERR_PTR() * encoded -%EOPNOTSUPP if @regulator doesn't use regmap. */struct regmap *regulator_get_regmap(struct regulator *regulator){ struct regmap *map = regulator->rdev->regmap;
return map ? map : ERR_PTR(-EOPNOTSUPP);}EXPORT_SYMBOL_GPL(regulator_get_regmap);
/** * regulator_get_hardware_vsel_register - get the HW voltage selector register * @regulator: regulator source * @vsel_reg: voltage selector register, output parameter * @vsel_mask: mask for voltage selector bitfield, output parameter * * Returns the hardware register offset and bitmask used for setting the * regulator voltage. This might be useful when configuring voltage-scaling * hardware or firmware that can make I2C requests behind the kernel's back, * for example. * * Return: 0 on success, or -%EOPNOTSUPP if the regulator does not support * voltage selectors. * * On success, the output parameters @vsel_reg and @vsel_mask are filled in * and 0 is returned, otherwise a negative error number is returned. */int regulator_get_hardware_vsel_register(struct regulator *regulator, unsigned *vsel_reg, unsigned *vsel_mask){ struct regulator_dev *rdev = regulator->rdev; const struct regulator_ops *ops = rdev->desc->ops;
if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) return -EOPNOTSUPP;
*vsel_reg = rdev->desc->vsel_reg; *vsel_mask = rdev->desc->vsel_mask;
return 0;}EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register);
/** * regulator_list_hardware_vsel - get the HW-specific register value for a selector * @regulator: regulator source * @selector: identify voltage to list * * Converts the selector to a hardware-specific voltage selector that can be * directly written to the regulator registers. The address of the voltage * register can be determined by calling @regulator_get_hardware_vsel_register. * * Return: 0 on success, -%EINVAL if the selector is outside the supported * range, or -%EOPNOTSUPP if the regulator does not support voltage * selectors. */int regulator_list_hardware_vsel(struct regulator *regulator, unsigned selector){ struct regulator_dev *rdev = regulator->rdev; const struct regulator_ops *ops = rdev->desc->ops;
if (selector >= rdev->desc->n_voltages) return -EINVAL; if (selector < rdev->desc->linear_min_sel) return 0; if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) return -EOPNOTSUPP;
return selector;}EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel);
/** * regulator_hardware_enable - access the HW for enable/disable regulator * @regulator: regulator source * @enable: true for enable, false for disable * * Request that the regulator be enabled/disabled with the regulator output at * the predefined voltage or current value. * * Return: 0 on success or a negative error number on failure. */int regulator_hardware_enable(struct regulator *regulator, bool enable){ struct regulator_dev *rdev = regulator->rdev; const struct regulator_ops *ops = rdev->desc->ops; int ret = -EOPNOTSUPP;
if (!rdev->exclusive || !ops || !ops->enable || !ops->disable) return ret;
if (enable) ret = ops->enable(rdev); else ret = ops->disable(rdev);
return ret;}EXPORT_SYMBOL_GPL(regulator_hardware_enable);
/** * regulator_get_linear_step - return the voltage step size between VSEL values * @regulator: regulator source * * Return: The voltage step size between VSEL values for linear regulators, * or 0 if the regulator isn't a linear regulator. */unsigned int regulator_get_linear_step(struct regulator *regulator){ struct regulator_dev *rdev = regulator->rdev;
return rdev->desc->uV_step;}EXPORT_SYMBOL_GPL(regulator_get_linear_step);
/** * regulator_is_supported_voltage - check if a voltage range can be supported * * @regulator: Regulator to check. * @min_uV: Minimum required voltage in uV. * @max_uV: Maximum required voltage in uV. * * Return: 1 if the voltage range is supported, 0 if not, or a negative error * number if @regulator's voltage can't be changed and voltage readback * failed. */int regulator_is_supported_voltage(struct regulator *regulator, int min_uV, int max_uV){ struct regulator_dev *rdev = regulator->rdev; int i, voltages, ret;
/* If we can't change voltage check the current voltage */ if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { ret = regulator_get_voltage(regulator); if (ret >= 0) return min_uV <= ret && ret <= max_uV; else return ret; }
/* Any voltage within constrains range is fine? */ if (rdev->desc->continuous_voltage_range) return min_uV >= rdev->constraints->min_uV && max_uV <= rdev->constraints->max_uV;
ret = regulator_count_voltages(regulator); if (ret < 0) return 0; voltages = ret;
for (i = 0; i < voltages; i++) { ret = regulator_list_voltage(regulator, i);
if (ret >= min_uV && ret <= max_uV) return 1; }
return 0;}EXPORT_SYMBOL_GPL(regulator_is_supported_voltage);
static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV, int max_uV){ const struct regulator_desc *desc = rdev->desc;
if (desc->ops->map_voltage) return desc->ops->map_voltage(rdev, min_uV, max_uV);
if (desc->ops->list_voltage == regulator_list_voltage_linear) return regulator_map_voltage_linear(rdev, min_uV, max_uV);
if (desc->ops->list_voltage == regulator_list_voltage_linear_range) return regulator_map_voltage_linear_range(rdev, min_uV, max_uV);
if (desc->ops->list_voltage == regulator_list_voltage_pickable_linear_range) return regulator_map_voltage_pickable_linear_range(rdev, min_uV, max_uV);
return regulator_map_voltage_iterate(rdev, min_uV, max_uV);}
static int _regulator_call_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector){ struct pre_voltage_change_data data; int ret;
data.old_uV = regulator_get_voltage_rdev(rdev); data.min_uV = min_uV; data.max_uV = max_uV; ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, &data); if (ret & NOTIFY_STOP_MASK) return -EINVAL;
ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector); if (ret >= 0) return ret;
_notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, (void *)data.old_uV);
return ret;}
static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev, int uV, unsigned selector){ struct pre_voltage_change_data data; int ret;
data.old_uV = regulator_get_voltage_rdev(rdev); data.min_uV = uV; data.max_uV = uV; ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, &data); if (ret & NOTIFY_STOP_MASK) return -EINVAL;
ret = rdev->desc->ops->set_voltage_sel(rdev, selector); if (ret >= 0) return ret;
_notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, (void *)data.old_uV);
return ret;}
static int _regulator_set_voltage_sel_step(struct regulator_dev *rdev, int uV, int new_selector){ const struct regulator_ops *ops = rdev->desc->ops; int diff, old_sel, curr_sel, ret;
/* Stepping is only needed if the regulator is enabled. */ if (!_regulator_is_enabled(rdev)) goto final_set;
if (!ops->get_voltage_sel) return -EINVAL;
old_sel = ops->get_voltage_sel(rdev); if (old_sel < 0) return old_sel;
diff = new_selector - old_sel; if (diff == 0) return 0; /* No change needed. */
if (diff > 0) { /* Stepping up. */ for (curr_sel = old_sel + rdev->desc->vsel_step; curr_sel < new_selector; curr_sel += rdev->desc->vsel_step) { /* * Call the callback directly instead of using * _regulator_call_set_voltage_sel() as we don't * want to notify anyone yet. Same in the branch * below. */ ret = ops->set_voltage_sel(rdev, curr_sel); if (ret) goto try_revert; } } else { /* Stepping down. */ for (curr_sel = old_sel - rdev->desc->vsel_step; curr_sel > new_selector; curr_sel -= rdev->desc->vsel_step) { ret = ops->set_voltage_sel(rdev, curr_sel); if (ret) goto try_revert; } }
final_set: /* The final selector will trigger the notifiers. */ return _regulator_call_set_voltage_sel(rdev, uV, new_selector);
try_revert: /* * At least try to return to the previous voltage if setting a new * one failed. */ (void)ops->set_voltage_sel(rdev, old_sel); return ret;}
static int _regulator_set_voltage_time(struct regulator_dev *rdev, int old_uV, int new_uV){ unsigned int ramp_delay = 0;
if (rdev->constraints->ramp_delay) ramp_delay = rdev->constraints->ramp_delay; else if (rdev->desc->ramp_delay) ramp_delay = rdev->desc->ramp_delay; else if (rdev->constraints->settling_time) return rdev->constraints->settling_time; else if (rdev->constraints->settling_time_up && (new_uV > old_uV)) return rdev->constraints->settling_time_up; else if (rdev->constraints->settling_time_down && (new_uV < old_uV)) return rdev->constraints->settling_time_down;
if (ramp_delay == 0) return 0;
return DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay);}
static int _regulator_do_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV){ int ret; int delay = 0; int best_val = 0; unsigned int selector; int old_selector = -1; const struct regulator_ops *ops = rdev->desc->ops; int old_uV = regulator_get_voltage_rdev(rdev);
trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
min_uV += rdev->constraints->uV_offset; max_uV += rdev->constraints->uV_offset;
/* * If we can't obtain the old selector there is not enough * info to call set_voltage_time_sel(). */ if (_regulator_is_enabled(rdev) && ops->set_voltage_time_sel && ops->get_voltage_sel) { old_selector = ops->get_voltage_sel(rdev); if (old_selector < 0) return old_selector; }
if (ops->set_voltage) { ret = _regulator_call_set_voltage(rdev, min_uV, max_uV, &selector);
if (ret >= 0) { if (ops->list_voltage) best_val = ops->list_voltage(rdev, selector); else best_val = regulator_get_voltage_rdev(rdev); }
} else if (ops->set_voltage_sel) { ret = regulator_map_voltage(rdev, min_uV, max_uV); if (ret >= 0) { best_val = ops->list_voltage(rdev, ret); if (min_uV <= best_val && max_uV >= best_val) { selector = ret; if (old_selector == selector) ret = 0; else if (rdev->desc->vsel_step) ret = _regulator_set_voltage_sel_step( rdev, best_val, selector); else ret = _regulator_call_set_voltage_sel( rdev, best_val, selector); } else { ret = -EINVAL; } } } else { ret = -EINVAL; }
if (ret) goto out;
if (ops->set_voltage_time_sel) { /* * Call set_voltage_time_sel if successfully obtained * old_selector */ if (old_selector >= 0 && old_selector != selector) delay = ops->set_voltage_time_sel(rdev, old_selector, selector); } else { if (old_uV != best_val) { if (ops->set_voltage_time) delay = ops->set_voltage_time(rdev, old_uV, best_val); else delay = _regulator_set_voltage_time(rdev, old_uV, best_val); } }
if (delay < 0) { rdev_warn(rdev, "failed to get delay: %pe\n", ERR_PTR(delay)); delay = 0; }
/* Insert any necessary delays */ fsleep(delay);
if (best_val >= 0) { unsigned long data = best_val;
_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, (void *)data); }
out: trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val);
return ret;}
static int _regulator_do_set_suspend_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, suspend_state_t state){ struct regulator_state *rstate; int uV, sel;
rstate = regulator_get_suspend_state(rdev, state); if (rstate == NULL) return -EINVAL;
if (min_uV < rstate->min_uV) min_uV = rstate->min_uV; if (max_uV > rstate->max_uV) max_uV = rstate->max_uV;
sel = regulator_map_voltage(rdev, min_uV, max_uV); if (sel < 0) return sel;
uV = rdev->desc->ops->list_voltage(rdev, sel); if (uV >= min_uV && uV <= max_uV) rstate->uV = uV;
return 0;}
static int regulator_get_voltage_delta(struct regulator_dev *rdev, int uV){ int current_uV = regulator_get_voltage_rdev(rdev);
if (current_uV < 0) return current_uV;
return abs(current_uV - uV);}
static int regulator_set_voltage_unlocked(struct regulator *regulator, int min_uV, int max_uV, suspend_state_t state){ struct regulator_dev *rdev = regulator->rdev; struct regulator_voltage *voltage = ®ulator->voltage[state]; int ret = 0; int current_uV, delta, new_delta; int old_min_uV, old_max_uV;
/* If we're setting the same range as last time the change * should be a noop (some cpufreq implementations use the same * voltage for multiple frequencies, for example). */ if (voltage->min_uV == min_uV && voltage->max_uV == max_uV) goto out;
/* If we're trying to set a range that overlaps the current voltage, * return successfully even though the regulator does not support * changing the voltage. */ if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { current_uV = regulator_get_voltage_rdev(rdev); if (min_uV <= current_uV && current_uV <= max_uV) { voltage->min_uV = min_uV; voltage->max_uV = max_uV; goto out; } }
/* sanity check */ if (!rdev->desc->ops->set_voltage && !rdev->desc->ops->set_voltage_sel) { ret = -EINVAL; goto out; }
/* constraints check */ ret = regulator_check_voltage(rdev, &min_uV, &max_uV); if (ret < 0) goto out;
/* restore original values in case of error */ old_min_uV = voltage->min_uV; old_max_uV = voltage->max_uV; voltage->min_uV = min_uV; voltage->max_uV = max_uV;
/* for not coupled regulators this will just set the voltage */ ret = regulator_balance_voltage(rdev, state); if (ret < 0) { voltage->min_uV = old_min_uV; voltage->max_uV = old_max_uV; }
if (rdev->constraints->max_uV_step > 0) { /* For regulators with a maximum voltage step, reaching the desired * voltage might take a few retries. */ ret = regulator_get_voltage_delta(rdev, min_uV); if (ret < 0) goto out;
delta = ret;
while (delta > 0) { ret = regulator_balance_voltage(rdev, state); if (ret < 0) goto out;
ret = regulator_get_voltage_delta(rdev, min_uV); if (ret < 0) goto out;
new_delta = ret;
/* check that voltage is converging quickly enough */ if (delta - new_delta < rdev->constraints->max_uV_step) { ret = -EWOULDBLOCK; goto out; }
delta = new_delta; } }
out: return ret;}
int regulator_set_voltage_rdev(struct regulator_dev *rdev, int min_uV, int max_uV, suspend_state_t state){ int best_supply_uV = 0; int supply_change_uV = 0; int ret;
if (rdev->supply && regulator_ops_is_valid(rdev->supply->rdev, REGULATOR_CHANGE_VOLTAGE) && (rdev->desc->min_dropout_uV || !(rdev->desc->ops->get_voltage || rdev->desc->ops->get_voltage_sel))) { int current_supply_uV; int selector;
selector = regulator_map_voltage(rdev, min_uV, max_uV); if (selector < 0) { ret = selector; goto out; }
best_supply_uV = _regulator_list_voltage(rdev, selector, 0); if (best_supply_uV < 0) { ret = best_supply_uV; goto out; }
best_supply_uV += rdev->desc->min_dropout_uV;
current_supply_uV = regulator_get_voltage_rdev(rdev->supply->rdev); if (current_supply_uV < 0) { ret = current_supply_uV; goto out; }
supply_change_uV = best_supply_uV - current_supply_uV; }
if (supply_change_uV > 0) { ret = regulator_set_voltage_unlocked(rdev->supply, best_supply_uV, INT_MAX, state); if (ret) { dev_err(&rdev->dev, "Failed to increase supply voltage: %pe\n", ERR_PTR(ret)); goto out; } }
if (state == PM_SUSPEND_ON) ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); else ret = _regulator_do_set_suspend_voltage(rdev, min_uV, max_uV, state); if (ret < 0) goto out;
if (supply_change_uV < 0) { ret = regulator_set_voltage_unlocked(rdev->supply, best_supply_uV, INT_MAX, state); if (ret) dev_warn(&rdev->dev, "Failed to decrease supply voltage: %pe\n", ERR_PTR(ret)); /* No need to fail here */ ret = 0; }
out: return ret;}EXPORT_SYMBOL_GPL(regulator_set_voltage_rdev);
static int regulator_limit_voltage_step(struct regulator_dev *rdev, int *current_uV, int *min_uV){ struct regulation_constraints *constraints = rdev->constraints;
/* Limit voltage change only if necessary */ if (!constraints->max_uV_step || !_regulator_is_enabled(rdev)) return 1;
if (*current_uV < 0) { *current_uV = regulator_get_voltage_rdev(rdev);
if (*current_uV < 0) return *current_uV; }
if (abs(*current_uV - *min_uV) <= constraints->max_uV_step) return 1;
/* Clamp target voltage within the given step */ if (*current_uV < *min_uV) *min_uV = min(*current_uV + constraints->max_uV_step, *min_uV); else *min_uV = max(*current_uV - constraints->max_uV_step, *min_uV);
return 0;}
static int regulator_get_optimal_voltage(struct regulator_dev *rdev, int *current_uV, int *min_uV, int *max_uV, suspend_state_t state, int n_coupled){ struct coupling_desc *c_desc = &rdev->coupling_desc; struct regulator_dev **c_rdevs = c_desc->coupled_rdevs; struct regulation_constraints *constraints = rdev->constraints; int desired_min_uV = 0, desired_max_uV = INT_MAX; int max_current_uV = 0, min_current_uV = INT_MAX; int highest_min_uV = 0, target_uV, possible_uV; int i, ret, max_spread; bool done;
*current_uV = -1;
/* * If there are no coupled regulators, simply set the voltage * demanded by consumers. */ if (n_coupled == 1) { /* * If consumers don't provide any demands, set voltage * to min_uV */ desired_min_uV = constraints->min_uV; desired_max_uV = constraints->max_uV;
ret = regulator_check_consumers(rdev, &desired_min_uV, &desired_max_uV, state); if (ret < 0) return ret;
done = true;
goto finish; }
/* Find highest min desired voltage */ for (i = 0; i < n_coupled; i++) { int tmp_min = 0; int tmp_max = INT_MAX;
lockdep_assert_held_once(&c_rdevs[i]->mutex.base);
ret = regulator_check_consumers(c_rdevs[i], &tmp_min, &tmp_max, state); if (ret < 0) return ret;
ret = regulator_check_voltage(c_rdevs[i], &tmp_min, &tmp_max); if (ret < 0) return ret;
highest_min_uV = max(highest_min_uV, tmp_min);
if (i == 0) { desired_min_uV = tmp_min; desired_max_uV = tmp_max; } }
max_spread = constraints->max_spread[0];
/* * Let target_uV be equal to the desired one if possible. * If not, set it to minimum voltage, allowed by other coupled * regulators. */ target_uV = max(desired_min_uV, highest_min_uV - max_spread);
/* * Find min and max voltages, which currently aren't violating * max_spread. */ for (i = 1; i < n_coupled; i++) { int tmp_act;
if (!_regulator_is_enabled(c_rdevs[i])) continue;
tmp_act = regulator_get_voltage_rdev(c_rdevs[i]); if (tmp_act < 0) return tmp_act;
min_current_uV = min(tmp_act, min_current_uV); max_current_uV = max(tmp_act, max_current_uV); }
/* There aren't any other regulators enabled */ if (max_current_uV == 0) { possible_uV = target_uV; } else { /* * Correct target voltage, so as it currently isn't * violating max_spread */ possible_uV = max(target_uV, max_current_uV - max_spread); possible_uV = min(possible_uV, min_current_uV + max_spread); }
if (possible_uV > desired_max_uV) return -EINVAL;
done = (possible_uV == target_uV); desired_min_uV = possible_uV;
finish: /* Apply max_uV_step constraint if necessary */ if (state == PM_SUSPEND_ON) { ret = regulator_limit_voltage_step(rdev, current_uV, &desired_min_uV); if (ret < 0) return ret;
if (ret == 0) done = false; }
/* Set current_uV if wasn't done earlier in the code and if necessary */ if (n_coupled > 1 && *current_uV == -1) {
if (_regulator_is_enabled(rdev)) { ret = regulator_get_voltage_rdev(rdev); if (ret < 0) return ret;
*current_uV = ret; } else { *current_uV = desired_min_uV; } }
*min_uV = desired_min_uV; *max_uV = desired_max_uV;
return done;}
int regulator_do_balance_voltage(struct regulator_dev *rdev, suspend_state_t state, bool skip_coupled){ struct regulator_dev **c_rdevs; struct regulator_dev *best_rdev; struct coupling_desc *c_desc = &rdev->coupling_desc; int i, ret, n_coupled, best_min_uV, best_max_uV, best_c_rdev; unsigned int delta, best_delta; unsigned long c_rdev_done = 0; bool best_c_rdev_done;
c_rdevs = c_desc->coupled_rdevs; n_coupled = skip_coupled ? 1 : c_desc->n_coupled;
/* * Find the best possible voltage change on each loop. Leave the loop * if there isn't any possible change. */ do { best_c_rdev_done = false; best_delta = 0; best_min_uV = 0; best_max_uV = 0; best_c_rdev = 0; best_rdev = NULL;
/* * Find highest difference between optimal voltage * and current voltage. */ for (i = 0; i < n_coupled; i++) { /* * optimal_uV is the best voltage that can be set for * i-th regulator at the moment without violating * max_spread constraint in order to balance * the coupled voltages. */ int optimal_uV = 0, optimal_max_uV = 0, current_uV = 0;
if (test_bit(i, &c_rdev_done)) continue;
ret = regulator_get_optimal_voltage(c_rdevs[i], ¤t_uV, &optimal_uV, &optimal_max_uV, state, n_coupled); if (ret < 0) goto out;
delta = abs(optimal_uV - current_uV);
if (delta && best_delta <= delta) { best_c_rdev_done = ret; best_delta = delta; best_rdev = c_rdevs[i]; best_min_uV = optimal_uV; best_max_uV = optimal_max_uV; best_c_rdev = i; } }
/* Nothing to change, return successfully */ if (!best_rdev) { ret = 0; goto out; }
ret = regulator_set_voltage_rdev(best_rdev, best_min_uV, best_max_uV, state);
if (ret < 0) goto out;
if (best_c_rdev_done) set_bit(best_c_rdev, &c_rdev_done);
} while (n_coupled > 1);
out: return ret;}EXPORT_SYMBOL_GPL(regulator_do_balance_voltage);
static int regulator_balance_voltage(struct regulator_dev *rdev, suspend_state_t state){ struct coupling_desc *c_desc = &rdev->coupling_desc; struct regulator_coupler *coupler = c_desc->coupler; bool skip_coupled = false;
/* * If system is in a state other than PM_SUSPEND_ON, don't check * other coupled regulators. */ if (state != PM_SUSPEND_ON) skip_coupled = true;
if (c_desc->n_resolved < c_desc->n_coupled) { rdev_err(rdev, "Not all coupled regulators registered\n"); return -EPERM; }
/* Invoke custom balancer for customized couplers */ if (coupler && coupler->balance_voltage) return coupler->balance_voltage(coupler, rdev, state);
return regulator_do_balance_voltage(rdev, state, skip_coupled);}
/** * regulator_set_voltage - set regulator output voltage * @regulator: regulator source * @min_uV: Minimum required voltage in uV * @max_uV: Maximum acceptable voltage in uV * * Sets a voltage regulator to the desired output voltage. This can be set * during any regulator state. IOW, regulator can be disabled or enabled. * * If the regulator is enabled then the voltage will change to the new value * immediately otherwise if the regulator is disabled the regulator will * output at the new voltage when enabled. * * NOTE: If the regulator is shared between several devices then the lowest * request voltage that meets the system constraints will be used. * Regulator system constraints must be set for this regulator before * calling this function otherwise this call will fail. * * Return: 0 on success or a negative error number on failure. */int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV){ struct ww_acquire_ctx ww_ctx; int ret;
regulator_lock_dependent(regulator->rdev, &ww_ctx);
ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV, PM_SUSPEND_ON);
regulator_unlock_dependent(regulator->rdev, &ww_ctx);
return ret;}EXPORT_SYMBOL_GPL(regulator_set_voltage);
static inline int regulator_suspend_toggle(struct regulator_dev *rdev, suspend_state_t state, bool en){ struct regulator_state *rstate;
rstate = regulator_get_suspend_state(rdev, state); if (rstate == NULL) return -EINVAL;
if (!rstate->changeable) return -EPERM;
rstate->enabled = (en) ? ENABLE_IN_SUSPEND : DISABLE_IN_SUSPEND;
return 0;}
int regulator_suspend_enable(struct regulator_dev *rdev, suspend_state_t state){ return regulator_suspend_toggle(rdev, state, true);}EXPORT_SYMBOL_GPL(regulator_suspend_enable);
int regulator_suspend_disable(struct regulator_dev *rdev, suspend_state_t state){ struct regulator *regulator; struct regulator_voltage *voltage;
/* * if any consumer wants this regulator device keeping on in * suspend states, don't set it as disabled. */ list_for_each_entry(regulator, &rdev->consumer_list, list) { voltage = ®ulator->voltage[state]; if (voltage->min_uV || voltage->max_uV) return 0; }
return regulator_suspend_toggle(rdev, state, false);}EXPORT_SYMBOL_GPL(regulator_suspend_disable);
static int _regulator_set_suspend_voltage(struct regulator *regulator, int min_uV, int max_uV, suspend_state_t state){ struct regulator_dev *rdev = regulator->rdev; struct regulator_state *rstate;
rstate = regulator_get_suspend_state(rdev, state); if (rstate == NULL) return -EINVAL;
if (rstate->min_uV == rstate->max_uV) { rdev_err(rdev, "The suspend voltage can't be changed!\n"); return -EPERM; }
return regulator_set_voltage_unlocked(regulator, min_uV, max_uV, state);}
int regulator_set_suspend_voltage(struct regulator *regulator, int min_uV, int max_uV, suspend_state_t state){ struct ww_acquire_ctx ww_ctx; int ret;
/* PM_SUSPEND_ON is handled by regulator_set_voltage() */ if (regulator_check_states(state) || state == PM_SUSPEND_ON) return -EINVAL;
regulator_lock_dependent(regulator->rdev, &ww_ctx);
ret = _regulator_set_suspend_voltage(regulator, min_uV, max_uV, state);
regulator_unlock_dependent(regulator->rdev, &ww_ctx);
return ret;}EXPORT_SYMBOL_GPL(regulator_set_suspend_voltage);
/** * regulator_set_voltage_time - get raise/fall time * @regulator: regulator source * @old_uV: starting voltage in microvolts * @new_uV: target voltage in microvolts * * Provided with the starting and ending voltage, this function attempts to * calculate the time in microseconds required to rise or fall to this new * voltage. * * Return: ramp time in microseconds, or a negative error number if calculation failed. */int regulator_set_voltage_time(struct regulator *regulator, int old_uV, int new_uV){ struct regulator_dev *rdev = regulator->rdev; const struct regulator_ops *ops = rdev->desc->ops; int old_sel = -1; int new_sel = -1; int voltage; int i;
if (ops->set_voltage_time) return ops->set_voltage_time(rdev, old_uV, new_uV); else if (!ops->set_voltage_time_sel) return _regulator_set_voltage_time(rdev, old_uV, new_uV);
/* Currently requires operations to do this */ if (!ops->list_voltage || !rdev->desc->n_voltages) return -EINVAL;
for (i = 0; i < rdev->desc->n_voltages; i++) { /* We only look for exact voltage matches here */ if (i < rdev->desc->linear_min_sel) continue;
if (old_sel >= 0 && new_sel >= 0) break;
voltage = regulator_list_voltage(regulator, i); if (voltage < 0) return -EINVAL; if (voltage == 0) continue; if (voltage == old_uV) old_sel = i; if (voltage == new_uV) new_sel = i; }
if (old_sel < 0 || new_sel < 0) return -EINVAL;
return ops->set_voltage_time_sel(rdev, old_sel, new_sel);}EXPORT_SYMBOL_GPL(regulator_set_voltage_time);
/** * regulator_set_voltage_time_sel - get raise/fall time * @rdev: regulator source device * @old_selector: selector for starting voltage * @new_selector: selector for target voltage * * Provided with the starting and target voltage selectors, this function * returns time in microseconds required to rise or fall to this new voltage * * Drivers providing ramp_delay in regulation_constraints can use this as their * set_voltage_time_sel() operation. * * Return: ramp time in microseconds, or a negative error number if calculation failed. */int regulator_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int old_selector, unsigned int new_selector){ int old_volt, new_volt;
/* sanity check */ if (!rdev->desc->ops->list_voltage) return -EINVAL;
old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); new_volt = rdev->desc->ops->list_voltage(rdev, new_selector);
if (rdev->desc->ops->set_voltage_time) return rdev->desc->ops->set_voltage_time(rdev, old_volt, new_volt); else return _regulator_set_voltage_time(rdev, old_volt, new_volt);}EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel);
int regulator_sync_voltage_rdev(struct regulator_dev *rdev){ int ret;
regulator_lock(rdev);
if (!rdev->desc->ops->set_voltage && !rdev->desc->ops->set_voltage_sel) { ret = -EINVAL; goto out; }
/* balance only, if regulator is coupled */ if (rdev->coupling_desc.n_coupled > 1) ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON); else ret = -EOPNOTSUPP;
out: regulator_unlock(rdev); return ret;}
/** * regulator_sync_voltage - re-apply last regulator output voltage * @regulator: regulator source * * Re-apply the last configured voltage. This is intended to be used * where some external control source the consumer is cooperating with * has caused the configured voltage to change. * * Return: 0 on success or a negative error number on failure. */int regulator_sync_voltage(struct regulator *regulator){ struct regulator_dev *rdev = regulator->rdev; struct regulator_voltage *voltage = ®ulator->voltage[PM_SUSPEND_ON]; int ret, min_uV, max_uV;
if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) return 0;
regulator_lock(rdev);
if (!rdev->desc->ops->set_voltage && !rdev->desc->ops->set_voltage_sel) { ret = -EINVAL; goto out; }
/* This is only going to work if we've had a voltage configured. */ if (!voltage->min_uV && !voltage->max_uV) { ret = -EINVAL; goto out; }
min_uV = voltage->min_uV; max_uV = voltage->max_uV;
/* This should be a paranoia check... */ ret = regulator_check_voltage(rdev, &min_uV, &max_uV); if (ret < 0) goto out;
ret = regulator_check_consumers(rdev, &min_uV, &max_uV, 0); if (ret < 0) goto out;
/* balance only, if regulator is coupled */ if (rdev->coupling_desc.n_coupled > 1) ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON); else ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
out: regulator_unlock(rdev); return ret;}EXPORT_SYMBOL_GPL(regulator_sync_voltage);
int regulator_get_voltage_rdev(struct regulator_dev *rdev){ int sel, ret; bool bypassed;
if (rdev->desc->ops->get_bypass) { ret = rdev->desc->ops->get_bypass(rdev, &bypassed); if (ret < 0) return ret; if (bypassed) { /* if bypassed the regulator must have a supply */ if (!rdev->supply) { rdev_err(rdev, "bypassed regulator has no supply!\n"); return -EPROBE_DEFER; }
return regulator_get_voltage_rdev(rdev->supply->rdev); } }
if (rdev->desc->ops->get_voltage_sel) { sel = rdev->desc->ops->get_voltage_sel(rdev); if (sel < 0) return sel; ret = rdev->desc->ops->list_voltage(rdev, sel); } else if (rdev->desc->ops->get_voltage) { ret = rdev->desc->ops->get_voltage(rdev); } else if (rdev->desc->ops->list_voltage) { ret = rdev->desc->ops->list_voltage(rdev, 0); } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { ret = rdev->desc->fixed_uV; } else if (rdev->supply) { ret = regulator_get_voltage_rdev(rdev->supply->rdev); } else if (rdev->supply_name) { return -EPROBE_DEFER; } else { return -EINVAL; }
if (ret < 0) return ret; return ret - rdev->constraints->uV_offset;}EXPORT_SYMBOL_GPL(regulator_get_voltage_rdev);
/** * regulator_get_voltage - get regulator output voltage * @regulator: regulator source * * Return: Current regulator voltage in uV, or a negative error number on failure. * * NOTE: If the regulator is disabled it will return the voltage value. This * function should not be used to determine regulator state. */int regulator_get_voltage(struct regulator *regulator){ struct ww_acquire_ctx ww_ctx; int ret;
regulator_lock_dependent(regulator->rdev, &ww_ctx); ret = regulator_get_voltage_rdev(regulator->rdev); regulator_unlock_dependent(regulator->rdev, &ww_ctx);
return ret;}EXPORT_SYMBOL_GPL(regulator_get_voltage);
/** * regulator_set_current_limit - set regulator output current limit * @regulator: regulator source * @min_uA: Minimum supported current in uA * @max_uA: Maximum supported current in uA * * Sets current sink to the desired output current. This can be set during * any regulator state. IOW, regulator can be disabled or enabled. * * If the regulator is enabled then the current will change to the new value * immediately otherwise if the regulator is disabled the regulator will * output at the new current when enabled. * * NOTE: Regulator system constraints must be set for this regulator before * calling this function otherwise this call will fail. * * Return: 0 on success or a negative error number on failure. */int regulator_set_current_limit(struct regulator *regulator, int min_uA, int max_uA){ struct regulator_dev *rdev = regulator->rdev; int ret;
regulator_lock(rdev);
/* sanity check */ if (!rdev->desc->ops->set_current_limit) { ret = -EINVAL; goto out; }
/* constraints check */ ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); if (ret < 0) goto out;
ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA);out: regulator_unlock(rdev); return ret;}EXPORT_SYMBOL_GPL(regulator_set_current_limit);
static int _regulator_get_current_limit_unlocked(struct regulator_dev *rdev){ /* sanity check */ if (!rdev->desc->ops->get_current_limit) return -EINVAL;
return rdev->desc->ops->get_current_limit(rdev);}
static int _regulator_get_current_limit(struct regulator_dev *rdev){ int ret;
regulator_lock(rdev); ret = _regulator_get_current_limit_unlocked(rdev); regulator_unlock(rdev);
return ret;}
/** * regulator_get_current_limit - get regulator output current * @regulator: regulator source * * Return: Current supplied by the specified current sink in uA, * or a negative error number on failure. * * NOTE: If the regulator is disabled it will return the current value. This * function should not be used to determine regulator state. */int regulator_get_current_limit(struct regulator *regulator){ return _regulator_get_current_limit(regulator->rdev);}EXPORT_SYMBOL_GPL(regulator_get_current_limit);
/** * regulator_get_unclaimed_power_budget - get regulator unclaimed power budget * @regulator: regulator source * * Return: Unclaimed power budget of the regulator in mW. */int regulator_get_unclaimed_power_budget(struct regulator *regulator){ return regulator->rdev->constraints->pw_budget_mW - regulator->rdev->pw_requested_mW;}EXPORT_SYMBOL_GPL(regulator_get_unclaimed_power_budget);
/** * regulator_request_power_budget - request power budget on a regulator * @regulator: regulator source * @pw_req: Power requested * * Return: 0 on success or a negative error number on failure. */int regulator_request_power_budget(struct regulator *regulator, unsigned int pw_req){ struct regulator_dev *rdev = regulator->rdev; int ret = 0, pw_tot_req;
regulator_lock(rdev); if (rdev->supply) { ret = regulator_request_power_budget(rdev->supply, pw_req); if (ret < 0) goto out; }
pw_tot_req = rdev->pw_requested_mW + pw_req; if (pw_tot_req > rdev->constraints->pw_budget_mW) { rdev_warn(rdev, "power requested %d mW out of budget %d mW", pw_req, rdev->constraints->pw_budget_mW - rdev->pw_requested_mW); regulator_notifier_call_chain(rdev, REGULATOR_EVENT_OVER_CURRENT_WARN, NULL); ret = -ERANGE; goto out; }
rdev->pw_requested_mW = pw_tot_req;out: regulator_unlock(rdev); return ret;}EXPORT_SYMBOL_GPL(regulator_request_power_budget);
/** * regulator_free_power_budget - free power budget on a regulator * @regulator: regulator source * @pw: Power to be released. * * Return: Power budget of the regulator in mW. */void regulator_free_power_budget(struct regulator *regulator, unsigned int pw){ struct regulator_dev *rdev = regulator->rdev; int pw_tot_req;
regulator_lock(rdev); if (rdev->supply) regulator_free_power_budget(rdev->supply, pw);
pw_tot_req = rdev->pw_requested_mW - pw; if (pw_tot_req >= 0) rdev->pw_requested_mW = pw_tot_req; else rdev_warn(rdev, "too much power freed %d mW (already requested %d mW)", pw, rdev->pw_requested_mW);
regulator_unlock(rdev);}EXPORT_SYMBOL_GPL(regulator_free_power_budget);
/** * regulator_set_mode - set regulator operating mode * @regulator: regulator source * @mode: operating mode - one of the REGULATOR_MODE constants * * Set regulator operating mode to increase regulator efficiency or improve * regulation performance. * * NOTE: Regulator system constraints must be set for this regulator before * calling this function otherwise this call will fail. * * Return: 0 on success or a negative error number on failure. */int regulator_set_mode(struct regulator *regulator, unsigned int mode){ struct regulator_dev *rdev = regulator->rdev; int ret; int regulator_curr_mode;
regulator_lock(rdev);
/* sanity check */ if (!rdev->desc->ops->set_mode) { ret = -EINVAL; goto out; }
/* return if the same mode is requested */ if (rdev->desc->ops->get_mode) { regulator_curr_mode = rdev->desc->ops->get_mode(rdev); if (regulator_curr_mode == mode) { ret = 0; goto out; } }
/* constraints check */ ret = regulator_mode_constrain(rdev, &mode); if (ret < 0) goto out;
ret = rdev->desc->ops->set_mode(rdev, mode);out: regulator_unlock(rdev); return ret;}EXPORT_SYMBOL_GPL(regulator_set_mode);
static unsigned int _regulator_get_mode_unlocked(struct regulator_dev *rdev){ /* sanity check */ if (!rdev->desc->ops->get_mode) return -EINVAL;
return rdev->desc->ops->get_mode(rdev);}
static unsigned int _regulator_get_mode(struct regulator_dev *rdev){ int ret;
regulator_lock(rdev); ret = _regulator_get_mode_unlocked(rdev); regulator_unlock(rdev);
return ret;}
/** * regulator_get_mode - get regulator operating mode * @regulator: regulator source * * Get the current regulator operating mode. * * Return: Current operating mode as %REGULATOR_MODE_* values, * or a negative error number on failure. */unsigned int regulator_get_mode(struct regulator *regulator){ return _regulator_get_mode(regulator->rdev);}EXPORT_SYMBOL_GPL(regulator_get_mode);
static int rdev_get_cached_err_flags(struct regulator_dev *rdev){ int ret = 0;
if (rdev->use_cached_err) { spin_lock(&rdev->err_lock); ret = rdev->cached_err; spin_unlock(&rdev->err_lock); } return ret;}
static int _regulator_get_error_flags(struct regulator_dev *rdev, unsigned int *flags){ int cached_flags, ret = 0;
regulator_lock(rdev);
cached_flags = rdev_get_cached_err_flags(rdev);
if (rdev->desc->ops->get_error_flags) ret = rdev->desc->ops->get_error_flags(rdev, flags); else if (!rdev->use_cached_err) ret = -EINVAL;
*flags |= cached_flags;
regulator_unlock(rdev);
return ret;}
/** * regulator_get_error_flags - get regulator error information * @regulator: regulator source * @flags: pointer to store error flags * * Get the current regulator error information. * * Return: 0 on success or a negative error number on failure. */int regulator_get_error_flags(struct regulator *regulator, unsigned int *flags){ return _regulator_get_error_flags(regulator->rdev, flags);}EXPORT_SYMBOL_GPL(regulator_get_error_flags);
/** * regulator_set_load - set regulator load * @regulator: regulator source * @uA_load: load current * * Notifies the regulator core of a new device load. This is then used by * DRMS (if enabled by constraints) to set the most efficient regulator * operating mode for the new regulator loading. * * Consumer devices notify their supply regulator of the maximum power * they will require (can be taken from device datasheet in the power * consumption tables) when they change operational status and hence power * state. Examples of operational state changes that can affect power * consumption are :- * * o Device is opened / closed. * o Device I/O is about to begin or has just finished. * o Device is idling in between work. * * This information is also exported via sysfs to userspace. * * DRMS will sum the total requested load on the regulator and change * to the most efficient operating mode if platform constraints allow. * * NOTE: when a regulator consumer requests to have a regulator * disabled then any load that consumer requested no longer counts * toward the total requested load. If the regulator is re-enabled * then the previously requested load will start counting again. * * If a regulator is an always-on regulator then an individual consumer's * load will still be removed if that consumer is fully disabled. * * Return: 0 on success or a negative error number on failure. */int regulator_set_load(struct regulator *regulator, int uA_load){ struct regulator_dev *rdev = regulator->rdev; int old_uA_load; int ret = 0;
regulator_lock(rdev); old_uA_load = regulator->uA_load; regulator->uA_load = uA_load; if (regulator->enable_count && old_uA_load != uA_load) { ret = drms_uA_update(rdev); if (ret < 0) regulator->uA_load = old_uA_load; } regulator_unlock(rdev);
return ret;}EXPORT_SYMBOL_GPL(regulator_set_load);
/** * regulator_allow_bypass - allow the regulator to go into bypass mode * * @regulator: Regulator to configure * @enable: enable or disable bypass mode * * Allow the regulator to go into bypass mode if all other consumers * for the regulator also enable bypass mode and the machine * constraints allow this. Bypass mode means that the regulator is * simply passing the input directly to the output with no regulation. * * Return: 0 on success or if changing bypass is not possible, or * a negative error number on failure. */int regulator_allow_bypass(struct regulator *regulator, bool enable){ struct regulator_dev *rdev = regulator->rdev; const char *name = rdev_get_name(rdev); int ret = 0;
if (!rdev->desc->ops->set_bypass) return 0;
if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_BYPASS)) return 0;
regulator_lock(rdev);
if (enable && !regulator->bypass) { rdev->bypass_count++;
if (rdev->bypass_count == rdev->open_count) { trace_regulator_bypass_enable(name);
ret = rdev->desc->ops->set_bypass(rdev, enable); if (ret != 0) rdev->bypass_count--; else trace_regulator_bypass_enable_complete(name); }
} else if (!enable && regulator->bypass) { rdev->bypass_count--;
if (rdev->bypass_count != rdev->open_count) { trace_regulator_bypass_disable(name);
ret = rdev->desc->ops->set_bypass(rdev, enable); if (ret != 0) rdev->bypass_count++; else trace_regulator_bypass_disable_complete(name); } }
if (ret == 0) regulator->bypass = enable;
regulator_unlock(rdev);
return ret;}EXPORT_SYMBOL_GPL(regulator_allow_bypass);
/** * regulator_register_notifier - register regulator event notifier * @regulator: regulator source * @nb: notifier block * * Register notifier block to receive regulator events. * * Return: 0 on success or a negative error number on failure. */int regulator_register_notifier(struct regulator *regulator, struct notifier_block *nb){ return blocking_notifier_chain_register(®ulator->rdev->notifier, nb);}EXPORT_SYMBOL_GPL(regulator_register_notifier);
/** * regulator_unregister_notifier - unregister regulator event notifier * @regulator: regulator source * @nb: notifier block * * Unregister regulator event notifier block. * * Return: 0 on success or a negative error number on failure. */int regulator_unregister_notifier(struct regulator *regulator, struct notifier_block *nb){ return blocking_notifier_chain_unregister(®ulator->rdev->notifier, nb);}EXPORT_SYMBOL_GPL(regulator_unregister_notifier);
/* notify regulator consumers and downstream regulator consumers. * Note mutex must be held by caller. */static int _notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data){ /* call rdev chain first */ int ret = blocking_notifier_call_chain(&rdev->notifier, event, data);
if (IS_REACHABLE(CONFIG_REGULATOR_NETLINK_EVENTS)) { struct device *parent = rdev->dev.parent; const char *rname = rdev_get_name(rdev); char name[32];
/* Avoid duplicate debugfs directory names */ if (parent && rname == rdev->desc->name) { snprintf(name, sizeof(name), "%s-%s", dev_name(parent), rname); rname = name; } reg_generate_netlink_event(rname, event); }
return ret;}
int _regulator_bulk_get(struct device *dev, int num_consumers, struct regulator_bulk_data *consumers, enum regulator_get_type get_type){ int i; int ret;
for (i = 0; i < num_consumers; i++) consumers[i].consumer = NULL;
for (i = 0; i < num_consumers; i++) { consumers[i].consumer = _regulator_get(dev, consumers[i].supply, get_type); if (IS_ERR(consumers[i].consumer)) { ret = dev_err_probe(dev, PTR_ERR(consumers[i].consumer), "Failed to get supply '%s'\n", consumers[i].supply); consumers[i].consumer = NULL; goto err; }
if (consumers[i].init_load_uA > 0) { ret = regulator_set_load(consumers[i].consumer, consumers[i].init_load_uA); if (ret) { i++; goto err; } } }
return 0;
err: while (--i >= 0) regulator_put(consumers[i].consumer);
return ret;}
/** * regulator_bulk_get - get multiple regulator consumers * * @dev: Device to supply * @num_consumers: Number of consumers to register * @consumers: Configuration of consumers; clients are stored here. * * This helper function allows drivers to get several regulator * consumers in one operation. If any of the regulators cannot be * acquired then any regulators that were allocated will be freed * before returning to the caller. * * Return: 0 on success or a negative error number on failure. */int regulator_bulk_get(struct device *dev, int num_consumers, struct regulator_bulk_data *consumers){ return _regulator_bulk_get(dev, num_consumers, consumers, NORMAL_GET);}EXPORT_SYMBOL_GPL(regulator_bulk_get);
static void regulator_bulk_enable_async(void *data, async_cookie_t cookie){ struct regulator_bulk_data *bulk = data;
bulk->ret = regulator_enable(bulk->consumer);}
/** * regulator_bulk_enable - enable multiple regulator consumers * * @num_consumers: Number of consumers * @consumers: Consumer data; clients are stored here. * * This convenience API allows consumers to enable multiple regulator * clients in a single API call. If any consumers cannot be enabled * then any others that were enabled will be disabled again prior to * return. * * Return: 0 on success or a negative error number on failure. */int regulator_bulk_enable(int num_consumers, struct regulator_bulk_data *consumers){ ASYNC_DOMAIN_EXCLUSIVE(async_domain); int i; int ret = 0;
for (i = 0; i < num_consumers; i++) { async_schedule_domain(regulator_bulk_enable_async, &consumers[i], &async_domain); }
async_synchronize_full_domain(&async_domain);
/* If any consumer failed we need to unwind any that succeeded */ for (i = 0; i < num_consumers; i++) { if (consumers[i].ret != 0) { ret = consumers[i].ret; goto err; } }
return 0;
err: for (i = 0; i < num_consumers; i++) { if (consumers[i].ret < 0) pr_err("Failed to enable %s: %pe\n", consumers[i].supply, ERR_PTR(consumers[i].ret)); else regulator_disable(consumers[i].consumer); }
return ret;}EXPORT_SYMBOL_GPL(regulator_bulk_enable);
/** * regulator_bulk_disable - disable multiple regulator consumers * * @num_consumers: Number of consumers * @consumers: Consumer data; clients are stored here. * * This convenience API allows consumers to disable multiple regulator * clients in a single API call. If any consumers cannot be disabled * then any others that were disabled will be enabled again prior to * return. * * Return: 0 on success or a negative error number on failure. */int regulator_bulk_disable(int num_consumers, struct regulator_bulk_data *consumers){ int i; int ret, r;
for (i = num_consumers - 1; i >= 0; --i) { ret = regulator_disable(consumers[i].consumer); if (ret != 0) goto err; }
return 0;
err: pr_err("Failed to disable %s: %pe\n", consumers[i].supply, ERR_PTR(ret)); for (++i; i < num_consumers; ++i) { r = regulator_enable(consumers[i].consumer); if (r != 0) pr_err("Failed to re-enable %s: %pe\n", consumers[i].supply, ERR_PTR(r)); }
return ret;}EXPORT_SYMBOL_GPL(regulator_bulk_disable);
/** * regulator_bulk_force_disable - force disable multiple regulator consumers * * @num_consumers: Number of consumers * @consumers: Consumer data; clients are stored here. * * This convenience API allows consumers to forcibly disable multiple regulator * clients in a single API call. * NOTE: This should be used for situations when device damage will * likely occur if the regulators are not disabled (e.g. over temp). * Although regulator_force_disable function call for some consumers can * return error numbers, the function is called for all consumers. * * Return: 0 on success or a negative error number on failure. */int regulator_bulk_force_disable(int num_consumers, struct regulator_bulk_data *consumers){ int i; int ret = 0;
for (i = 0; i < num_consumers; i++) { consumers[i].ret = regulator_force_disable(consumers[i].consumer);
/* Store first error for reporting */ if (consumers[i].ret && !ret) ret = consumers[i].ret; }
return ret;}EXPORT_SYMBOL_GPL(regulator_bulk_force_disable);
/** * regulator_bulk_free - free multiple regulator consumers * * @num_consumers: Number of consumers * @consumers: Consumer data; clients are stored here. * * This convenience API allows consumers to free multiple regulator * clients in a single API call. */void regulator_bulk_free(int num_consumers, struct regulator_bulk_data *consumers){ int i;
for (i = 0; i < num_consumers; i++) { regulator_put(consumers[i].consumer); consumers[i].consumer = NULL; }}EXPORT_SYMBOL_GPL(regulator_bulk_free);
/** * regulator_handle_critical - Handle events for system-critical regulators. * @rdev: The regulator device. * @event: The event being handled. * * This function handles critical events such as under-voltage, over-current, * and unknown errors for regulators deemed system-critical. On detecting such * events, it triggers a hardware protection shutdown with a defined timeout. */static void regulator_handle_critical(struct regulator_dev *rdev, unsigned long event){ const char *reason = NULL;
if (!rdev->constraints->system_critical) return;
switch (event) { case REGULATOR_EVENT_UNDER_VOLTAGE: reason = "System critical regulator: voltage drop detected"; break; case REGULATOR_EVENT_OVER_CURRENT: reason = "System critical regulator: over-current detected"; break; case REGULATOR_EVENT_FAIL: reason = "System critical regulator: unknown error"; }
if (!reason) return;
hw_protection_trigger(reason, rdev->constraints->uv_less_critical_window_ms);}
/** * regulator_notifier_call_chain - call regulator event notifier * @rdev: regulator source * @event: notifier block * @data: callback-specific data. * * Called by regulator drivers to notify clients a regulator event has * occurred. * * Return: %NOTIFY_DONE. */int regulator_notifier_call_chain(struct regulator_dev *rdev, unsigned long event, void *data){ regulator_handle_critical(rdev, event);
_notifier_call_chain(rdev, event, data); return NOTIFY_DONE;
}EXPORT_SYMBOL_GPL(regulator_notifier_call_chain);
/** * regulator_mode_to_status - convert a regulator mode into a status * * @mode: Mode to convert * * Convert a regulator mode into a status. * * Return: %REGULATOR_STATUS_* value corresponding to given mode. */int regulator_mode_to_status(unsigned int mode){ switch (mode) { case REGULATOR_MODE_FAST: return REGULATOR_STATUS_FAST; case REGULATOR_MODE_NORMAL: return REGULATOR_STATUS_NORMAL; case REGULATOR_MODE_IDLE: return REGULATOR_STATUS_IDLE; case REGULATOR_MODE_STANDBY: return REGULATOR_STATUS_STANDBY; default: return REGULATOR_STATUS_UNDEFINED; }}EXPORT_SYMBOL_GPL(regulator_mode_to_status);
static struct attribute *regulator_dev_attrs[] = { &dev_attr_name.attr, &dev_attr_num_users.attr, &dev_attr_type.attr, &dev_attr_microvolts.attr, &dev_attr_microamps.attr, &dev_attr_opmode.attr, &dev_attr_state.attr, &dev_attr_status.attr, &dev_attr_bypass.attr, &dev_attr_requested_microamps.attr, &dev_attr_min_microvolts.attr, &dev_attr_max_microvolts.attr, &dev_attr_min_microamps.attr, &dev_attr_max_microamps.attr, &dev_attr_under_voltage.attr, &dev_attr_over_current.attr, &dev_attr_regulation_out.attr, &dev_attr_fail.attr, &dev_attr_over_temp.attr, &dev_attr_under_voltage_warn.attr, &dev_attr_over_current_warn.attr, &dev_attr_over_voltage_warn.attr, &dev_attr_over_temp_warn.attr, &dev_attr_suspend_standby_state.attr, &dev_attr_suspend_mem_state.attr, &dev_attr_suspend_disk_state.attr, &dev_attr_suspend_standby_microvolts.attr, &dev_attr_suspend_mem_microvolts.attr, &dev_attr_suspend_disk_microvolts.attr, &dev_attr_suspend_standby_mode.attr, &dev_attr_suspend_mem_mode.attr, &dev_attr_suspend_disk_mode.attr, &dev_attr_power_budget_milliwatt.attr, &dev_attr_power_requested_milliwatt.attr, NULL};
/* * To avoid cluttering sysfs (and memory) with useless state, only * create attributes that can be meaningfully displayed. */static umode_t regulator_attr_is_visible(struct kobject *kobj, struct attribute *attr, int idx){ struct device *dev = kobj_to_dev(kobj); struct regulator_dev *rdev = dev_to_rdev(dev); const struct regulator_ops *ops = rdev->desc->ops; umode_t mode = attr->mode;
/* these three are always present */ if (attr == &dev_attr_name.attr || attr == &dev_attr_num_users.attr || attr == &dev_attr_type.attr) return mode;
/* some attributes need specific methods to be displayed */ if (attr == &dev_attr_microvolts.attr) { if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1)) return mode; return 0; }
if (attr == &dev_attr_microamps.attr) return ops->get_current_limit ? mode : 0;
if (attr == &dev_attr_opmode.attr) return ops->get_mode ? mode : 0;
if (attr == &dev_attr_state.attr) return (rdev->ena_pin || ops->is_enabled) ? mode : 0;
if (attr == &dev_attr_status.attr) return ops->get_status ? mode : 0;
if (attr == &dev_attr_bypass.attr) return ops->get_bypass ? mode : 0;
if (attr == &dev_attr_under_voltage.attr || attr == &dev_attr_over_current.attr || attr == &dev_attr_regulation_out.attr || attr == &dev_attr_fail.attr || attr == &dev_attr_over_temp.attr || attr == &dev_attr_under_voltage_warn.attr || attr == &dev_attr_over_current_warn.attr || attr == &dev_attr_over_voltage_warn.attr || attr == &dev_attr_over_temp_warn.attr) return ops->get_error_flags ? mode : 0;
/* constraints need specific supporting methods */ if (attr == &dev_attr_min_microvolts.attr || attr == &dev_attr_max_microvolts.attr) return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0;
if (attr == &dev_attr_min_microamps.attr || attr == &dev_attr_max_microamps.attr) return ops->set_current_limit ? mode : 0;
if (attr == &dev_attr_suspend_standby_state.attr || attr == &dev_attr_suspend_mem_state.attr || attr == &dev_attr_suspend_disk_state.attr) return mode;
if (attr == &dev_attr_suspend_standby_microvolts.attr || attr == &dev_attr_suspend_mem_microvolts.attr || attr == &dev_attr_suspend_disk_microvolts.attr) return ops->set_suspend_voltage ? mode : 0;
if (attr == &dev_attr_suspend_standby_mode.attr || attr == &dev_attr_suspend_mem_mode.attr || attr == &dev_attr_suspend_disk_mode.attr) return ops->set_suspend_mode ? mode : 0;
if (attr == &dev_attr_power_budget_milliwatt.attr || attr == &dev_attr_power_requested_milliwatt.attr) return rdev->constraints->pw_budget_mW != INT_MAX ? mode : 0;
return mode;}
static const struct attribute_group regulator_dev_group = { .attrs = regulator_dev_attrs, .is_visible = regulator_attr_is_visible,};
static const struct attribute_group *regulator_dev_groups[] = { ®ulator_dev_group, NULL};
static void regulator_dev_release(struct device *dev){ struct regulator_dev *rdev = dev_get_drvdata(dev);
debugfs_remove_recursive(rdev->debugfs); kfree(rdev->constraints); of_node_put(rdev->dev.of_node); kfree(rdev);}
static void rdev_init_debugfs(struct regulator_dev *rdev){ struct device *parent = rdev->dev.parent; const char *rname = rdev_get_name(rdev); char name[NAME_MAX];
/* Avoid duplicate debugfs directory names */ if (parent && rname == rdev->desc->name) { snprintf(name, sizeof(name), "%s-%s", dev_name(parent), rname); rname = name; }
rdev->debugfs = debugfs_create_dir(rname, debugfs_root); if (IS_ERR(rdev->debugfs)) rdev_dbg(rdev, "Failed to create debugfs directory\n");
debugfs_create_u32("use_count", 0444, rdev->debugfs, &rdev->use_count); debugfs_create_u32("open_count", 0444, rdev->debugfs, &rdev->open_count); debugfs_create_u32("bypass_count", 0444, rdev->debugfs, &rdev->bypass_count);}
int regulator_coupler_register(struct regulator_coupler *coupler){ mutex_lock(®ulator_list_mutex); list_add_tail(&coupler->list, ®ulator_coupler_list); mutex_unlock(®ulator_list_mutex);
return 0;}EXPORT_SYMBOL_GPL(regulator_coupler_register);
static struct regulator_coupler *regulator_find_coupler(struct regulator_dev *rdev){ struct regulator_coupler *coupler; int err;
/* * Note that regulators are appended to the list and the generic * coupler is registered first, hence it will be attached at last * if nobody cared. */ list_for_each_entry_reverse(coupler, ®ulator_coupler_list, list) { err = coupler->attach_regulator(coupler, rdev); if (!err) { if (!coupler->balance_voltage && rdev->coupling_desc.n_coupled > 2) goto err_unsupported;
return coupler; }
if (err < 0) return ERR_PTR(err);
if (err == 1) continue;
break; }
return ERR_PTR(-EINVAL);
err_unsupported: if (coupler->detach_regulator) coupler->detach_regulator(coupler, rdev);
rdev_err(rdev, "Voltage balancing for multiple regulator couples is unimplemented\n");
return ERR_PTR(-EPERM);}
static void regulator_resolve_coupling(struct regulator_dev *rdev){ struct regulator_coupler *coupler = rdev->coupling_desc.coupler; struct coupling_desc *c_desc = &rdev->coupling_desc; int n_coupled = c_desc->n_coupled; struct regulator_dev *c_rdev; int i;
for (i = 1; i < n_coupled; i++) { /* already resolved */ if (c_desc->coupled_rdevs[i]) continue;
c_rdev = of_parse_coupled_regulator(rdev, i - 1);
if (!c_rdev) continue;
if (c_rdev->coupling_desc.coupler != coupler) { rdev_err(rdev, "coupler mismatch with %s\n", rdev_get_name(c_rdev)); put_device(&c_rdev->dev); return; }
c_desc->coupled_rdevs[i] = c_rdev; c_desc->n_resolved++;
regulator_resolve_coupling(c_rdev); }}
static void regulator_remove_coupling(struct regulator_dev *rdev){ struct regulator_coupler *coupler = rdev->coupling_desc.coupler; struct coupling_desc *__c_desc, *c_desc = &rdev->coupling_desc; struct regulator_dev *__c_rdev, *c_rdev; unsigned int __n_coupled, n_coupled; int i, k; int err;
n_coupled = c_desc->n_coupled;
for (i = 1; i < n_coupled; i++) { c_rdev = c_desc->coupled_rdevs[i];
if (!c_rdev) continue;
regulator_lock(c_rdev);
__c_desc = &c_rdev->coupling_desc; __n_coupled = __c_desc->n_coupled;
for (k = 1; k < __n_coupled; k++) { __c_rdev = __c_desc->coupled_rdevs[k];
if (__c_rdev == rdev) { __c_desc->coupled_rdevs[k] = NULL; __c_desc->n_resolved--; break; } }
regulator_unlock(c_rdev);
c_desc->coupled_rdevs[i] = NULL; c_desc->n_resolved--;
put_device(&c_rdev->dev); }
if (coupler && coupler->detach_regulator) { err = coupler->detach_regulator(coupler, rdev); if (err) rdev_err(rdev, "failed to detach from coupler: %pe\n", ERR_PTR(err)); }
rdev->coupling_desc.n_coupled = 0; kfree(rdev->coupling_desc.coupled_rdevs); rdev->coupling_desc.coupled_rdevs = NULL;}
static int regulator_init_coupling(struct regulator_dev *rdev){ struct regulator_dev **coupled; int err, n_phandles;
if (!IS_ENABLED(CONFIG_OF)) n_phandles = 0; else n_phandles = of_get_n_coupled(rdev);
coupled = kzalloc_objs(*coupled, n_phandles + 1); if (!coupled) return -ENOMEM;
rdev->coupling_desc.coupled_rdevs = coupled;
/* * Every regulator should always have coupling descriptor filled with * at least pointer to itself. */ rdev->coupling_desc.coupled_rdevs[0] = rdev; rdev->coupling_desc.n_coupled = n_phandles + 1; rdev->coupling_desc.n_resolved++;
/* regulator isn't coupled */ if (n_phandles == 0) return 0;
if (!of_check_coupling_data(rdev)) return -EPERM;
mutex_lock(®ulator_list_mutex); rdev->coupling_desc.coupler = regulator_find_coupler(rdev); mutex_unlock(®ulator_list_mutex);
if (IS_ERR(rdev->coupling_desc.coupler)) { err = PTR_ERR(rdev->coupling_desc.coupler); rdev_err(rdev, "failed to get coupler: %pe\n", ERR_PTR(err)); return err; }
return 0;}
static int generic_coupler_attach(struct regulator_coupler *coupler, struct regulator_dev *rdev){ if (rdev->coupling_desc.n_coupled > 2) { rdev_err(rdev, "Voltage balancing for multiple regulator couples is unimplemented\n"); return -EPERM; }
if (!rdev->constraints->always_on) { rdev_err(rdev, "Coupling of a non always-on regulator is unimplemented\n"); return -ENOTSUPP; }
return 0;}
static struct regulator_coupler generic_regulator_coupler = { .attach_regulator = generic_coupler_attach,};
/** * regulator_register - register regulator * @dev: the device that drive the regulator * @regulator_desc: regulator to register * @cfg: runtime configuration for regulator * * Called by regulator drivers to register a regulator. * * Return: Pointer to a valid &struct regulator_dev on success or * an ERR_PTR() encoded negative error number on failure. */struct regulator_dev *regulator_register(struct device *dev, const struct regulator_desc *regulator_desc, const struct regulator_config *cfg){ const struct regulator_init_data *init_data; struct regulator_config *config = NULL; static atomic_t regulator_no = ATOMIC_INIT(-1); struct regulator_dev *rdev; bool tried_supply_resolve = false; bool dangling_cfg_gpiod = false; bool dangling_of_gpiod = false; int ret, i;
if (cfg == NULL) return ERR_PTR(-EINVAL); if (cfg->ena_gpiod) dangling_cfg_gpiod = true; if (regulator_desc == NULL) { ret = -EINVAL; goto rinse; }
WARN_ON(!dev || !cfg->dev);
if (regulator_desc->name == NULL || regulator_desc->ops == NULL) { ret = -EINVAL; goto rinse; }
if (regulator_desc->type != REGULATOR_VOLTAGE && regulator_desc->type != REGULATOR_CURRENT) { ret = -EINVAL; goto rinse; }
/* Only one of each should be implemented */ WARN_ON(regulator_desc->ops->get_voltage && regulator_desc->ops->get_voltage_sel); WARN_ON(regulator_desc->ops->set_voltage && regulator_desc->ops->set_voltage_sel);
/* If we're using selectors we must implement list_voltage. */ if (regulator_desc->ops->get_voltage_sel && !regulator_desc->ops->list_voltage) { ret = -EINVAL; goto rinse; } if (regulator_desc->ops->set_voltage_sel && !regulator_desc->ops->list_voltage) { ret = -EINVAL; goto rinse; }
rdev = kzalloc_obj(struct regulator_dev); if (rdev == NULL) { ret = -ENOMEM; goto rinse; } device_initialize(&rdev->dev); dev_set_drvdata(&rdev->dev, rdev); rdev->dev.class = ®ulator_class; spin_lock_init(&rdev->err_lock);
/* * Duplicate the config so the driver could override it after * parsing init data. */ config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL); if (config == NULL) { ret = -ENOMEM; goto clean; }
/* * DT may override the config->init_data provided if the platform * needs to do so. If so, config->init_data is completely ignored. */ init_data = regulator_of_get_init_data(dev, regulator_desc, config, &rdev->dev.of_node);
/* * Sometimes not all resources are probed already so we need to take * that into account. This happens most the time if the ena_gpiod comes * from a gpio extender or something else. */ if (PTR_ERR(init_data) == -EPROBE_DEFER) { ret = -EPROBE_DEFER; goto clean; }
/* * We need to keep track of any GPIO descriptor coming from the * device tree until we have handled it over to the core. If the * config that was passed in to this function DOES NOT contain * a descriptor, and the config after this call DOES contain * a descriptor, we definitely got one from parsing the device * tree. */ if (!cfg->ena_gpiod && config->ena_gpiod) dangling_of_gpiod = true; if (!init_data) { init_data = config->init_data; rdev->dev.of_node = of_node_get(config->of_node); }
ww_mutex_init(&rdev->mutex, ®ulator_ww_class); rdev->reg_data = config->driver_data; rdev->owner = regulator_desc->owner; rdev->desc = regulator_desc; if (config->regmap) rdev->regmap = config->regmap; else if (dev_get_regmap(dev, NULL)) rdev->regmap = dev_get_regmap(dev, NULL); else if (dev->parent) rdev->regmap = dev_get_regmap(dev->parent, NULL); INIT_LIST_HEAD(&rdev->consumer_list); INIT_LIST_HEAD(&rdev->list); BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work);
if (init_data && init_data->supply_regulator) rdev->supply_name = init_data->supply_regulator; else if (regulator_desc->supply_name) rdev->supply_name = regulator_desc->supply_name;
/* register with sysfs */ rdev->dev.parent = config->dev; dev_set_name(&rdev->dev, "regulator.%lu", (unsigned long) atomic_inc_return(®ulator_no));
/* set regulator constraints */ if (init_data) rdev->constraints = kmemdup(&init_data->constraints, sizeof(*rdev->constraints), GFP_KERNEL); else rdev->constraints = kzalloc_obj(*rdev->constraints); if (!rdev->constraints) { ret = -ENOMEM; goto wash; }
if (regulator_desc->init_cb) { ret = regulator_desc->init_cb(rdev, config); if (ret < 0) goto wash; }
if (config->ena_gpiod) { ret = regulator_ena_gpio_request(rdev, config); if (ret != 0) { rdev_err(rdev, "Failed to request enable GPIO: %pe\n", ERR_PTR(ret)); goto wash; } /* The regulator core took over the GPIO descriptor */ dangling_cfg_gpiod = false; dangling_of_gpiod = false; }
ret = set_machine_constraints(rdev, false); if (ret == -EPROBE_DEFER) { /* Regulator might be in bypass mode or an always-on or boot-on * regulator and so needs its supply to set the constraints or * for enable. */ /* FIXME: this currently triggers a chicken-and-egg problem * when creating -SUPPLY symlink in sysfs to a regulator * that is just being created */ rdev_dbg(rdev, "will resolve supply early: %s\n", rdev->supply_name); ret = regulator_resolve_supply(rdev); if (!ret) ret = set_machine_constraints(rdev, false); else rdev_dbg(rdev, "unable to resolve supply early: %pe\n", ERR_PTR(ret)); tried_supply_resolve = true; } if (ret < 0) { if (ret != -EPROBE_DEFER) goto wash; rdev->constraints_pending = true; }
ret = regulator_init_coupling(rdev); if (ret < 0) goto wash;
/* add consumers devices */ if (init_data) { for (i = 0; i < init_data->num_consumer_supplies; i++) { ret = set_consumer_device_supply(rdev, init_data->consumer_supplies[i].dev_name, init_data->consumer_supplies[i].supply); if (ret < 0) { dev_err(dev, "Failed to set supply %s\n", init_data->consumer_supplies[i].supply); goto unset_supplies; } } }
if (!rdev->desc->ops->get_voltage && !rdev->desc->ops->list_voltage && !rdev->desc->fixed_uV) rdev->is_switch = true;
ret = device_add(&rdev->dev); if (ret != 0) goto unset_supplies;
if (!tried_supply_resolve) { /* * As an optimisation, try to resolve our supply (if any) now to * avoid adding the bus device. Errors are not fatal at this * stage, we'll simply try again later. */ ret = regulator_resolve_supply(rdev); if (ret) rdev_dbg(rdev, "unable to resolve supply (ignoring): %pe\n", ERR_PTR(ret)); }
/* * If we have a supply but couldn't resolve it yet, register a device * with our bus, so that the bus probe gets called whenever any new * driver binds, allowing us to retry matching supplies and which then * triggers (re)probe of consumers if successful. */ if (rdev->supply_name && !rdev->supply) { device_initialize(&rdev->bdev); rdev->bdev.bus = ®ulator_bus; rdev->bdev.parent = &rdev->dev; device_set_pm_not_required(&rdev->dev); dev_set_name(&rdev->bdev, "%s.bdev", dev_name(&rdev->dev));
ret = device_add(&rdev->bdev); if (ret) goto del_cdev_and_bdev; }
rdev_init_debugfs(rdev);
/* try to resolve regulators coupling since a new one was registered */ mutex_lock(®ulator_list_mutex); regulator_resolve_coupling(rdev); mutex_unlock(®ulator_list_mutex);
kfree(config); return rdev;
del_cdev_and_bdev: if (rdev->bdev.bus == ®ulator_bus) put_device(&rdev->bdev); device_del(&rdev->dev);unset_supplies: mutex_lock(®ulator_list_mutex); unset_regulator_supplies(rdev); regulator_remove_coupling(rdev); mutex_unlock(®ulator_list_mutex);wash: regulator_put(rdev->supply); kfree(rdev->coupling_desc.coupled_rdevs); mutex_lock(®ulator_list_mutex); regulator_ena_gpio_free(rdev); mutex_unlock(®ulator_list_mutex);clean: if (dangling_of_gpiod) gpiod_put(config->ena_gpiod); kfree(config); put_device(&rdev->dev);rinse: if (dangling_cfg_gpiod) gpiod_put(cfg->ena_gpiod); return ERR_PTR(ret);}EXPORT_SYMBOL_GPL(regulator_register);
/** * regulator_unregister - unregister regulator * @rdev: regulator to unregister * * Called by regulator drivers to unregister a regulator. */void regulator_unregister(struct regulator_dev *rdev){ if (rdev == NULL) return;
if (rdev->supply) { regulator_unregister_notifier(rdev->supply, &rdev->supply_fwd_nb);
while (rdev->use_count--) regulator_disable(rdev->supply); regulator_put(rdev->supply); }
flush_work(&rdev->disable_work.work);
mutex_lock(®ulator_list_mutex);
WARN_ON(rdev->open_count); regulator_remove_coupling(rdev); unset_regulator_supplies(rdev); list_del(&rdev->list); regulator_ena_gpio_free(rdev); if (rdev->bdev.bus == ®ulator_bus) /* only if the device was added in the first place */ device_unregister(&rdev->bdev); device_unregister(&rdev->dev);
mutex_unlock(®ulator_list_mutex);}EXPORT_SYMBOL_GPL(regulator_unregister);
#ifdef CONFIG_SUSPEND/** * regulator_suspend - prepare regulators for system wide suspend * @dev: ``&struct device`` pointer that is passed to _regulator_suspend() * * Configure each regulator with it's suspend operating parameters for state. * * Return: 0 on success or a negative error number on failure. */static int regulator_suspend(struct device *dev){ struct regulator_dev *rdev = dev_to_rdev(dev); suspend_state_t state = pm_suspend_target_state; int ret; const struct regulator_state *rstate;
rstate = regulator_get_suspend_state_check(rdev, state); if (!rstate) return 0;
regulator_lock(rdev); ret = __suspend_set_state(rdev, rstate); regulator_unlock(rdev);
return ret;}
static int regulator_resume(struct device *dev){ suspend_state_t state = pm_suspend_target_state; struct regulator_dev *rdev = dev_to_rdev(dev); struct regulator_state *rstate; int ret = 0;
rstate = regulator_get_suspend_state(rdev, state); if (rstate == NULL) return 0;
/* Avoid grabbing the lock if we don't need to */ if (!rdev->desc->ops->resume) return 0;
regulator_lock(rdev);
if (rstate->enabled == ENABLE_IN_SUSPEND || rstate->enabled == DISABLE_IN_SUSPEND) ret = rdev->desc->ops->resume(rdev);
regulator_unlock(rdev);
return ret;}#else /* !CONFIG_SUSPEND */
#define regulator_suspend NULL#define regulator_resume NULL
#endif /* !CONFIG_SUSPEND */
#ifdef CONFIG_PMstatic const struct dev_pm_ops __maybe_unused regulator_pm_ops = { .suspend = regulator_suspend, .resume = regulator_resume,};#endif
const struct class regulator_class = { .name = "regulator", .dev_release = regulator_dev_release, .dev_groups = regulator_dev_groups,#ifdef CONFIG_PM .pm = ®ulator_pm_ops,#endif};
#define bdev_to_rdev(__bdev) container_of_const(__bdev, struct regulator_dev, bdev)
static int regulator_bus_match(struct device *bdev, const struct device_driver *drv){ /* Match always succeeds, we only have one driver */ return 1;}
static int regulator_bus_probe(struct device *bdev){ struct regulator_dev *rdev = bdev_to_rdev(bdev); int ret;
ret = regulator_resolve_supply(rdev); if (ret) rdev_dbg(rdev, "unable to resolve supply or constraints '%s': %pe\n", rdev->supply_name, ERR_PTR(ret)); else rdev_dbg(rdev, "resolved supply '%s'\n", rdev->supply_name);
return ret;}
static const struct bus_type regulator_bus = { .name = "regulator", .match = regulator_bus_match, .probe = regulator_bus_probe,};
static struct device_driver regulator_bus_driver = { .name = "regulator-bus-drv", .bus = ®ulator_bus, .suppress_bind_attrs = true, .probe_type = PROBE_PREFER_ASYNCHRONOUS,};
/** * regulator_has_full_constraints - the system has fully specified constraints * * Calling this function will cause the regulator API to disable all * regulators which have a zero use count and don't have an always_on * constraint in a late_initcall. * * The intention is that this will become the default behaviour in a * future kernel release so users are encouraged to use this facility * now. */void regulator_has_full_constraints(void){ has_full_constraints = 1;}EXPORT_SYMBOL_GPL(regulator_has_full_constraints);
/** * rdev_get_drvdata - get rdev regulator driver data * @rdev: regulator * * Get rdev regulator driver private data. This call can be used in the * regulator driver context. * * Return: Pointer to regulator driver private data. */void *rdev_get_drvdata(struct regulator_dev *rdev){ return rdev->reg_data;}EXPORT_SYMBOL_GPL(rdev_get_drvdata);
/** * regulator_get_drvdata - get regulator driver data * @regulator: regulator * * Get regulator driver private data. This call can be used in the consumer * driver context when non API regulator specific functions need to be called. * * Return: Pointer to regulator driver private data. */void *regulator_get_drvdata(struct regulator *regulator){ return regulator->rdev->reg_data;}EXPORT_SYMBOL_GPL(regulator_get_drvdata);
/** * regulator_set_drvdata - set regulator driver data * @regulator: regulator * @data: data */void regulator_set_drvdata(struct regulator *regulator, void *data){ regulator->rdev->reg_data = data;}EXPORT_SYMBOL_GPL(regulator_set_drvdata);
/** * rdev_get_id - get regulator ID * @rdev: regulator * * Return: Regulator ID for @rdev. */int rdev_get_id(struct regulator_dev *rdev){ return rdev->desc->id;}EXPORT_SYMBOL_GPL(rdev_get_id);
struct device *rdev_get_dev(struct regulator_dev *rdev){ return &rdev->dev;}EXPORT_SYMBOL_GPL(rdev_get_dev);
struct regmap *rdev_get_regmap(struct regulator_dev *rdev){ return rdev->regmap;}EXPORT_SYMBOL_GPL(rdev_get_regmap);
void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data){ return reg_init_data->driver_data;}EXPORT_SYMBOL_GPL(regulator_get_init_drvdata);
#ifdef CONFIG_DEBUG_FSstatic int supply_map_show(struct seq_file *sf, void *data){ struct regulator_map *map;
list_for_each_entry(map, ®ulator_map_list, list) { seq_printf(sf, "%s -> %s.%s\n", rdev_get_name(map->regulator), map->dev_name, map->supply); }
return 0;}DEFINE_SHOW_ATTRIBUTE(supply_map);
struct summary_data { struct seq_file *s; struct regulator_dev *parent; int level;};
static void regulator_summary_show_subtree(struct seq_file *s, struct regulator_dev *rdev, int level);
static int regulator_summary_show_children(struct device *dev, void *data){ struct regulator_dev *rdev = dev_to_rdev(dev); struct summary_data *summary_data = data;
if (rdev->supply && rdev->supply->rdev == summary_data->parent) regulator_summary_show_subtree(summary_data->s, rdev, summary_data->level + 1);
return 0;}
static void regulator_summary_show_subtree(struct seq_file *s, struct regulator_dev *rdev, int level){ struct regulation_constraints *c; struct regulator *consumer; struct summary_data summary_data; unsigned int opmode;
if (!rdev) return;
opmode = _regulator_get_mode_unlocked(rdev); seq_printf(s, "%*s%-*s %3d %4d %6d %7s ", level * 3 + 1, "", 30 - level * 3, rdev_get_name(rdev), rdev->use_count, rdev->open_count, rdev->bypass_count, regulator_opmode_to_str(opmode));
seq_printf(s, "%5dmV ", regulator_get_voltage_rdev(rdev) / 1000); seq_printf(s, "%5dmA ", _regulator_get_current_limit_unlocked(rdev) / 1000);
c = rdev->constraints; if (c) { switch (rdev->desc->type) { case REGULATOR_VOLTAGE: seq_printf(s, "%5dmV %5dmV ", c->min_uV / 1000, c->max_uV / 1000); break; case REGULATOR_CURRENT: seq_printf(s, "%5dmA %5dmA ", c->min_uA / 1000, c->max_uA / 1000); break; } }
seq_puts(s, "\n");
list_for_each_entry(consumer, &rdev->consumer_list, list) { if (consumer->dev && consumer->dev->class == ®ulator_class) continue;
seq_printf(s, "%*s%-*s ", (level + 1) * 3 + 1, "", 30 - (level + 1) * 3, consumer->supply_name ? consumer->supply_name : consumer->dev ? dev_name(consumer->dev) : "deviceless");
switch (rdev->desc->type) { case REGULATOR_VOLTAGE: seq_printf(s, "%3d %33dmA%c%5dmV %5dmV", consumer->enable_count, consumer->uA_load / 1000, consumer->uA_load && !consumer->enable_count ? '*' : ' ', consumer->voltage[PM_SUSPEND_ON].min_uV / 1000, consumer->voltage[PM_SUSPEND_ON].max_uV / 1000); break; case REGULATOR_CURRENT: break; }
seq_puts(s, "\n"); }
summary_data.s = s; summary_data.level = level; summary_data.parent = rdev;
class_for_each_device(®ulator_class, NULL, &summary_data, regulator_summary_show_children);}
struct summary_lock_data { struct ww_acquire_ctx *ww_ctx; struct regulator_dev **new_contended_rdev; struct regulator_dev **old_contended_rdev;};
static int regulator_summary_lock_one(struct device *dev, void *data){ struct regulator_dev *rdev = dev_to_rdev(dev); struct summary_lock_data *lock_data = data; int ret = 0;
if (rdev != *lock_data->old_contended_rdev) { ret = regulator_lock_nested(rdev, lock_data->ww_ctx);
if (ret == -EDEADLK) *lock_data->new_contended_rdev = rdev; else WARN_ON_ONCE(ret); } else { *lock_data->old_contended_rdev = NULL; }
return ret;}
static int regulator_summary_unlock_one(struct device *dev, void *data){ struct regulator_dev *rdev = dev_to_rdev(dev); struct summary_lock_data *lock_data = data;
if (lock_data) { if (rdev == *lock_data->new_contended_rdev) return -EDEADLK; }
regulator_unlock(rdev);
return 0;}
static int regulator_summary_lock_all(struct ww_acquire_ctx *ww_ctx, struct regulator_dev **new_contended_rdev, struct regulator_dev **old_contended_rdev){ struct summary_lock_data lock_data; int ret;
lock_data.ww_ctx = ww_ctx; lock_data.new_contended_rdev = new_contended_rdev; lock_data.old_contended_rdev = old_contended_rdev;
ret = class_for_each_device(®ulator_class, NULL, &lock_data, regulator_summary_lock_one); if (ret) class_for_each_device(®ulator_class, NULL, &lock_data, regulator_summary_unlock_one);
return ret;}
static void regulator_summary_lock(struct ww_acquire_ctx *ww_ctx){ struct regulator_dev *new_contended_rdev = NULL; struct regulator_dev *old_contended_rdev = NULL; int err;
mutex_lock(®ulator_list_mutex);
ww_acquire_init(ww_ctx, ®ulator_ww_class);
do { if (new_contended_rdev) { ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx); old_contended_rdev = new_contended_rdev; old_contended_rdev->ref_cnt++; old_contended_rdev->mutex_owner = current; }
err = regulator_summary_lock_all(ww_ctx, &new_contended_rdev, &old_contended_rdev);
if (old_contended_rdev) regulator_unlock(old_contended_rdev);
} while (err == -EDEADLK);
ww_acquire_done(ww_ctx);}
static void regulator_summary_unlock(struct ww_acquire_ctx *ww_ctx){ class_for_each_device(®ulator_class, NULL, NULL, regulator_summary_unlock_one); ww_acquire_fini(ww_ctx);
mutex_unlock(®ulator_list_mutex);}
static int regulator_summary_show_roots(struct device *dev, void *data){ struct regulator_dev *rdev = dev_to_rdev(dev); struct seq_file *s = data;
if (!rdev->supply) regulator_summary_show_subtree(s, rdev, 0);
return 0;}
static int regulator_summary_show(struct seq_file *s, void *data){ struct ww_acquire_ctx ww_ctx;
seq_puts(s, " regulator use open bypass opmode voltage current min max\n"); seq_puts(s, "---------------------------------------------------------------------------------------\n");
regulator_summary_lock(&ww_ctx);
class_for_each_device(®ulator_class, NULL, s, regulator_summary_show_roots);
regulator_summary_unlock(&ww_ctx);
return 0;}DEFINE_SHOW_ATTRIBUTE(regulator_summary);#endif /* CONFIG_DEBUG_FS */
static int __init regulator_init(void){ int ret;
ret = bus_register(®ulator_bus); if (ret) return ret;
ret = class_register(®ulator_class); if (ret) goto err_class;
ret = driver_register(®ulator_bus_driver); if (ret) goto err_driver;
debugfs_root = debugfs_create_dir("regulator", NULL); if (IS_ERR(debugfs_root)) pr_debug("regulator: Failed to create debugfs directory\n");
#ifdef CONFIG_DEBUG_FS debugfs_create_file("supply_map", 0444, debugfs_root, NULL, &supply_map_fops);
debugfs_create_file("regulator_summary", 0444, debugfs_root, NULL, ®ulator_summary_fops);#endif regulator_dummy_init();
regulator_coupler_register(&generic_regulator_coupler);
return 0;
err_driver: class_unregister(®ulator_class);err_class: bus_unregister(®ulator_bus); return ret;}
/* init early to allow our consumers to complete system booting */core_initcall(regulator_init);
static int regulator_late_cleanup(struct device *dev, void *data){ struct regulator_dev *rdev = dev_to_rdev(dev); struct regulation_constraints *c = rdev->constraints; int ret;
if (c && c->always_on) return 0;
if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) return 0;
regulator_lock(rdev);
if (rdev->use_count) goto unlock;
/* If reading the status failed, assume that it's off. */ if (_regulator_is_enabled(rdev) <= 0) goto unlock;
if (have_full_constraints()) { /* We log since this may kill the system if it goes * wrong. */ rdev_info(rdev, "disabling\n"); ret = _regulator_do_disable(rdev); if (ret != 0) rdev_err(rdev, "couldn't disable: %pe\n", ERR_PTR(ret)); } else { /* The intention is that in future we will * assume that full constraints are provided * so warn even if we aren't going to do * anything here. */ rdev_warn(rdev, "incomplete constraints, leaving on\n"); }
unlock: regulator_unlock(rdev);
return 0;}
static bool regulator_ignore_unused;static int __init regulator_ignore_unused_setup(char *__unused){ regulator_ignore_unused = true; return 1;}__setup("regulator_ignore_unused", regulator_ignore_unused_setup);
static void regulator_init_complete_work_function(struct work_struct *work){ /* * For debugging purposes, it may be useful to prevent unused * regulators from being disabled. */ if (regulator_ignore_unused) { pr_warn("regulator: Not disabling unused regulators\n"); return; }
/* If we have a full configuration then disable any regulators * we have permission to change the status for and which are * not in use or always_on. This is effectively the default * for DT and ACPI as they have full constraints. */ class_for_each_device(®ulator_class, NULL, NULL, regulator_late_cleanup);}
static DECLARE_DELAYED_WORK(regulator_init_complete_work, regulator_init_complete_work_function);
static int __init regulator_init_complete(void){ /* * Since DT doesn't provide an idiomatic mechanism for * enabling full constraints and since it's much more natural * with DT to provide them just assume that a DT enabled * system has full constraints. */ if (of_have_populated_dt()) has_full_constraints = true;
/* * We punt completion for an arbitrary amount of time since * systems like distros will load many drivers from userspace * so consumers might not always be ready yet, this is * particularly an issue with laptops where this might bounce * the display off then on. Ideally we'd get a notification * from userspace when this happens but we don't so just wait * a bit and hope we waited long enough. It'd be better if * we'd only do this on systems that need it, and a kernel * command line option might be useful. */ queue_delayed_work(system_freezable_wq, ®ulator_init_complete_work, msecs_to_jiffies(30000));
return 0;}late_initcall_sync(regulator_init_complete);