0004-Add-dwc_otg-driver.patch 1.6 MB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216192171921819219192201922119222192231922419225192261922719228192291923019231192321923319234192351923619237192381923919240192411924219243192441924519246192471924819249192501925119252192531925419255192561925719258192591926019261192621926319264192651926619267192681926919270192711927219273192741927519276192771927819279192801928119282192831928419285192861928719288192891929019291192921929319294192951929619297192981929919300193011930219303193041930519306193071930819309193101931119312193131931419315193161931719318193191932019321193221932319324193251932619327193281932919330193311933219333193341933519336193371933819339193401934119342193431934419345193461934719348193491935019351193521935319354193551935619357193581935919360193611936219363193641936519366193671936819369193701937119372193731937419375193761937719378193791938019381193821938319384193851938619387193881938919390193911939219393193941939519396193971939819399194001940119402194031940419405194061940719408194091941019411194121941319414194151941619417194181941919420194211942219423194241942519426194271942819429194301943119432194331943419435194361943719438194391944019441194421944319444194451944619447194481944919450194511945219453194541945519456194571945819459194601946119462194631946419465194661946719468194691947019471194721947319474194751947619477194781947919480194811948219483194841948519486194871948819489194901949119492194931949419495194961949719498194991950019501195021950319504195051950619507195081950919510195111951219513195141951519516195171951819519195201952119522195231952419525195261952719528195291953019531195321953319534195351953619537195381953919540195411954219543195441954519546195471954819549195501955119552195531955419555195561955719558195591956019561195621956319564195651956619567195681956919570195711957219573195741957519576195771957819579195801958119582195831958419585195861958719588195891959019591195921959319594195951959619597195981959919600196011960219603196041960519606196071960819609196101961119612196131961419615196161961719618196191962019621196221962319624196251962619627196281962919630196311963219633196341963519636196371963819639196401964119642196431964419645196461964719648196491965019651196521965319654196551965619657196581965919660196611966219663196641966519666196671966819669196701967119672196731967419675196761967719678196791968019681196821968319684196851968619687196881968919690196911969219693196941969519696196971969819699197001970119702197031970419705197061970719708197091971019711197121971319714197151971619717197181971919720197211972219723197241972519726197271972819729197301973119732197331973419735197361973719738197391974019741197421974319744197451974619747197481974919750197511975219753197541975519756197571975819759197601976119762197631976419765197661976719768197691977019771197721977319774197751977619777197781977919780197811978219783197841978519786197871978819789197901979119792197931979419795197961979719798197991980019801198021980319804198051980619807198081980919810198111981219813198141981519816198171981819819198201982119822198231982419825198261982719828198291983019831198321983319834198351983619837198381983919840198411984219843198441984519846198471984819849198501985119852198531985419855198561985719858198591986019861198621986319864198651986619867198681986919870198711987219873198741987519876198771987819879198801988119882198831988419885198861988719888198891989019891198921989319894198951989619897198981989919900199011990219903199041990519906199071990819909199101991119912199131991419915199161991719918199191992019921199221992319924199251992619927199281992919930199311993219933199341993519936199371993819939199401994119942199431994419945199461994719948199491995019951199521995319954199551995619957199581995919960199611996219963199641996519966199671996819969199701997119972199731997419975199761997719978199791998019981199821998319984199851998619987199881998919990199911999219993199941999519996199971999819999200002000120002200032000420005200062000720008200092001020011200122001320014200152001620017200182001920020200212002220023200242002520026200272002820029200302003120032200332003420035200362003720038200392004020041200422004320044200452004620047200482004920050200512005220053200542005520056200572005820059200602006120062200632006420065200662006720068200692007020071200722007320074200752007620077200782007920080200812008220083200842008520086200872008820089200902009120092200932009420095200962009720098200992010020101201022010320104201052010620107201082010920110201112011220113201142011520116201172011820119201202012120122201232012420125201262012720128201292013020131201322013320134201352013620137201382013920140201412014220143201442014520146201472014820149201502015120152201532015420155201562015720158201592016020161201622016320164201652016620167201682016920170201712017220173201742017520176201772017820179201802018120182201832018420185201862018720188201892019020191201922019320194201952019620197201982019920200202012020220203202042020520206202072020820209202102021120212202132021420215202162021720218202192022020221202222022320224202252022620227202282022920230202312023220233202342023520236202372023820239202402024120242202432024420245202462024720248202492025020251202522025320254202552025620257202582025920260202612026220263202642026520266202672026820269202702027120272202732027420275202762027720278202792028020281202822028320284202852028620287202882028920290202912029220293202942029520296202972029820299203002030120302203032030420305203062030720308203092031020311203122031320314203152031620317203182031920320203212032220323203242032520326203272032820329203302033120332203332033420335203362033720338203392034020341203422034320344203452034620347203482034920350203512035220353203542035520356203572035820359203602036120362203632036420365203662036720368203692037020371203722037320374203752037620377203782037920380203812038220383203842038520386203872038820389203902039120392203932039420395203962039720398203992040020401204022040320404204052040620407204082040920410204112041220413204142041520416204172041820419204202042120422204232042420425204262042720428204292043020431204322043320434204352043620437204382043920440204412044220443204442044520446204472044820449204502045120452204532045420455204562045720458204592046020461204622046320464204652046620467204682046920470204712047220473204742047520476204772047820479204802048120482204832048420485204862048720488204892049020491204922049320494204952049620497204982049920500205012050220503205042050520506205072050820509205102051120512205132051420515205162051720518205192052020521205222052320524205252052620527205282052920530205312053220533205342053520536205372053820539205402054120542205432054420545205462054720548205492055020551205522055320554205552055620557205582055920560205612056220563205642056520566205672056820569205702057120572205732057420575205762057720578205792058020581205822058320584205852058620587205882058920590205912059220593205942059520596205972059820599206002060120602206032060420605206062060720608206092061020611206122061320614206152061620617206182061920620206212062220623206242062520626206272062820629206302063120632206332063420635206362063720638206392064020641206422064320644206452064620647206482064920650206512065220653206542065520656206572065820659206602066120662206632066420665206662066720668206692067020671206722067320674206752067620677206782067920680206812068220683206842068520686206872068820689206902069120692206932069420695206962069720698206992070020701207022070320704207052070620707207082070920710207112071220713207142071520716207172071820719207202072120722207232072420725207262072720728207292073020731207322073320734207352073620737207382073920740207412074220743207442074520746207472074820749207502075120752207532075420755207562075720758207592076020761207622076320764207652076620767207682076920770207712077220773207742077520776207772077820779207802078120782207832078420785207862078720788207892079020791207922079320794207952079620797207982079920800208012080220803208042080520806208072080820809208102081120812208132081420815208162081720818208192082020821208222082320824208252082620827208282082920830208312083220833208342083520836208372083820839208402084120842208432084420845208462084720848208492085020851208522085320854208552085620857208582085920860208612086220863208642086520866208672086820869208702087120872208732087420875208762087720878208792088020881208822088320884208852088620887208882088920890208912089220893208942089520896208972089820899209002090120902209032090420905209062090720908209092091020911209122091320914209152091620917209182091920920209212092220923209242092520926209272092820929209302093120932209332093420935209362093720938209392094020941209422094320944209452094620947209482094920950209512095220953209542095520956209572095820959209602096120962209632096420965209662096720968209692097020971209722097320974209752097620977209782097920980209812098220983209842098520986209872098820989209902099120992209932099420995209962099720998209992100021001210022100321004210052100621007210082100921010210112101221013210142101521016210172101821019210202102121022210232102421025210262102721028210292103021031210322103321034210352103621037210382103921040210412104221043210442104521046210472104821049210502105121052210532105421055210562105721058210592106021061210622106321064210652106621067210682106921070210712107221073210742107521076210772107821079210802108121082210832108421085210862108721088210892109021091210922109321094210952109621097210982109921100211012110221103211042110521106211072110821109211102111121112211132111421115211162111721118211192112021121211222112321124211252112621127211282112921130211312113221133211342113521136211372113821139211402114121142211432114421145211462114721148211492115021151211522115321154211552115621157211582115921160211612116221163211642116521166211672116821169211702117121172211732117421175211762117721178211792118021181211822118321184211852118621187211882118921190211912119221193211942119521196211972119821199212002120121202212032120421205212062120721208212092121021211212122121321214212152121621217212182121921220212212122221223212242122521226212272122821229212302123121232212332123421235212362123721238212392124021241212422124321244212452124621247212482124921250212512125221253212542125521256212572125821259212602126121262212632126421265212662126721268212692127021271212722127321274212752127621277212782127921280212812128221283212842128521286212872128821289212902129121292212932129421295212962129721298212992130021301213022130321304213052130621307213082130921310213112131221313213142131521316213172131821319213202132121322213232132421325213262132721328213292133021331213322133321334213352133621337213382133921340213412134221343213442134521346213472134821349213502135121352213532135421355213562135721358213592136021361213622136321364213652136621367213682136921370213712137221373213742137521376213772137821379213802138121382213832138421385213862138721388213892139021391213922139321394213952139621397213982139921400214012140221403214042140521406214072140821409214102141121412214132141421415214162141721418214192142021421214222142321424214252142621427214282142921430214312143221433214342143521436214372143821439214402144121442214432144421445214462144721448214492145021451214522145321454214552145621457214582145921460214612146221463214642146521466214672146821469214702147121472214732147421475214762147721478214792148021481214822148321484214852148621487214882148921490214912149221493214942149521496214972149821499215002150121502215032150421505215062150721508215092151021511215122151321514215152151621517215182151921520215212152221523215242152521526215272152821529215302153121532215332153421535215362153721538215392154021541215422154321544215452154621547215482154921550215512155221553215542155521556215572155821559215602156121562215632156421565215662156721568215692157021571215722157321574215752157621577215782157921580215812158221583215842158521586215872158821589215902159121592215932159421595215962159721598215992160021601216022160321604216052160621607216082160921610216112161221613216142161521616216172161821619216202162121622216232162421625216262162721628216292163021631216322163321634216352163621637216382163921640216412164221643216442164521646216472164821649216502165121652216532165421655216562165721658216592166021661216622166321664216652166621667216682166921670216712167221673216742167521676216772167821679216802168121682216832168421685216862168721688216892169021691216922169321694216952169621697216982169921700217012170221703217042170521706217072170821709217102171121712217132171421715217162171721718217192172021721217222172321724217252172621727217282172921730217312173221733217342173521736217372173821739217402174121742217432174421745217462174721748217492175021751217522175321754217552175621757217582175921760217612176221763217642176521766217672176821769217702177121772217732177421775217762177721778217792178021781217822178321784217852178621787217882178921790217912179221793217942179521796217972179821799218002180121802218032180421805218062180721808218092181021811218122181321814218152181621817218182181921820218212182221823218242182521826218272182821829218302183121832218332183421835218362183721838218392184021841218422184321844218452184621847218482184921850218512185221853218542185521856218572185821859218602186121862218632186421865218662186721868218692187021871218722187321874218752187621877218782187921880218812188221883218842188521886218872188821889218902189121892218932189421895218962189721898218992190021901219022190321904219052190621907219082190921910219112191221913219142191521916219172191821919219202192121922219232192421925219262192721928219292193021931219322193321934219352193621937219382193921940219412194221943219442194521946219472194821949219502195121952219532195421955219562195721958219592196021961219622196321964219652196621967219682196921970219712197221973219742197521976219772197821979219802198121982219832198421985219862198721988219892199021991219922199321994219952199621997219982199922000220012200222003220042200522006220072200822009220102201122012220132201422015220162201722018220192202022021220222202322024220252202622027220282202922030220312203222033220342203522036220372203822039220402204122042220432204422045220462204722048220492205022051220522205322054220552205622057220582205922060220612206222063220642206522066220672206822069220702207122072220732207422075220762207722078220792208022081220822208322084220852208622087220882208922090220912209222093220942209522096220972209822099221002210122102221032210422105221062210722108221092211022111221122211322114221152211622117221182211922120221212212222123221242212522126221272212822129221302213122132221332213422135221362213722138221392214022141221422214322144221452214622147221482214922150221512215222153221542215522156221572215822159221602216122162221632216422165221662216722168221692217022171221722217322174221752217622177221782217922180221812218222183221842218522186221872218822189221902219122192221932219422195221962219722198221992220022201222022220322204222052220622207222082220922210222112221222213222142221522216222172221822219222202222122222222232222422225222262222722228222292223022231222322223322234222352223622237222382223922240222412224222243222442224522246222472224822249222502225122252222532225422255222562225722258222592226022261222622226322264222652226622267222682226922270222712227222273222742227522276222772227822279222802228122282222832228422285222862228722288222892229022291222922229322294222952229622297222982229922300223012230222303223042230522306223072230822309223102231122312223132231422315223162231722318223192232022321223222232322324223252232622327223282232922330223312233222333223342233522336223372233822339223402234122342223432234422345223462234722348223492235022351223522235322354223552235622357223582235922360223612236222363223642236522366223672236822369223702237122372223732237422375223762237722378223792238022381223822238322384223852238622387223882238922390223912239222393223942239522396223972239822399224002240122402224032240422405224062240722408224092241022411224122241322414224152241622417224182241922420224212242222423224242242522426224272242822429224302243122432224332243422435224362243722438224392244022441224422244322444224452244622447224482244922450224512245222453224542245522456224572245822459224602246122462224632246422465224662246722468224692247022471224722247322474224752247622477224782247922480224812248222483224842248522486224872248822489224902249122492224932249422495224962249722498224992250022501225022250322504225052250622507225082250922510225112251222513225142251522516225172251822519225202252122522225232252422525225262252722528225292253022531225322253322534225352253622537225382253922540225412254222543225442254522546225472254822549225502255122552225532255422555225562255722558225592256022561225622256322564225652256622567225682256922570225712257222573225742257522576225772257822579225802258122582225832258422585225862258722588225892259022591225922259322594225952259622597225982259922600226012260222603226042260522606226072260822609226102261122612226132261422615226162261722618226192262022621226222262322624226252262622627226282262922630226312263222633226342263522636226372263822639226402264122642226432264422645226462264722648226492265022651226522265322654226552265622657226582265922660226612266222663226642266522666226672266822669226702267122672226732267422675226762267722678226792268022681226822268322684226852268622687226882268922690226912269222693226942269522696226972269822699227002270122702227032270422705227062270722708227092271022711227122271322714227152271622717227182271922720227212272222723227242272522726227272272822729227302273122732227332273422735227362273722738227392274022741227422274322744227452274622747227482274922750227512275222753227542275522756227572275822759227602276122762227632276422765227662276722768227692277022771227722277322774227752277622777227782277922780227812278222783227842278522786227872278822789227902279122792227932279422795227962279722798227992280022801228022280322804228052280622807228082280922810228112281222813228142281522816228172281822819228202282122822228232282422825228262282722828228292283022831228322283322834228352283622837228382283922840228412284222843228442284522846228472284822849228502285122852228532285422855228562285722858228592286022861228622286322864228652286622867228682286922870228712287222873228742287522876228772287822879228802288122882228832288422885228862288722888228892289022891228922289322894228952289622897228982289922900229012290222903229042290522906229072290822909229102291122912229132291422915229162291722918229192292022921229222292322924229252292622927229282292922930229312293222933229342293522936229372293822939229402294122942229432294422945229462294722948229492295022951229522295322954229552295622957229582295922960229612296222963229642296522966229672296822969229702297122972229732297422975229762297722978229792298022981229822298322984229852298622987229882298922990229912299222993229942299522996229972299822999230002300123002230032300423005230062300723008230092301023011230122301323014230152301623017230182301923020230212302223023230242302523026230272302823029230302303123032230332303423035230362303723038230392304023041230422304323044230452304623047230482304923050230512305223053230542305523056230572305823059230602306123062230632306423065230662306723068230692307023071230722307323074230752307623077230782307923080230812308223083230842308523086230872308823089230902309123092230932309423095230962309723098230992310023101231022310323104231052310623107231082310923110231112311223113231142311523116231172311823119231202312123122231232312423125231262312723128231292313023131231322313323134231352313623137231382313923140231412314223143231442314523146231472314823149231502315123152231532315423155231562315723158231592316023161231622316323164231652316623167231682316923170231712317223173231742317523176231772317823179231802318123182231832318423185231862318723188231892319023191231922319323194231952319623197231982319923200232012320223203232042320523206232072320823209232102321123212232132321423215232162321723218232192322023221232222322323224232252322623227232282322923230232312323223233232342323523236232372323823239232402324123242232432324423245232462324723248232492325023251232522325323254232552325623257232582325923260232612326223263232642326523266232672326823269232702327123272232732327423275232762327723278232792328023281232822328323284232852328623287232882328923290232912329223293232942329523296232972329823299233002330123302233032330423305233062330723308233092331023311233122331323314233152331623317233182331923320233212332223323233242332523326233272332823329233302333123332233332333423335233362333723338233392334023341233422334323344233452334623347233482334923350233512335223353233542335523356233572335823359233602336123362233632336423365233662336723368233692337023371233722337323374233752337623377233782337923380233812338223383233842338523386233872338823389233902339123392233932339423395233962339723398233992340023401234022340323404234052340623407234082340923410234112341223413234142341523416234172341823419234202342123422234232342423425234262342723428234292343023431234322343323434234352343623437234382343923440234412344223443234442344523446234472344823449234502345123452234532345423455234562345723458234592346023461234622346323464234652346623467234682346923470234712347223473234742347523476234772347823479234802348123482234832348423485234862348723488234892349023491234922349323494234952349623497234982349923500235012350223503235042350523506235072350823509235102351123512235132351423515235162351723518235192352023521235222352323524235252352623527235282352923530235312353223533235342353523536235372353823539235402354123542235432354423545235462354723548235492355023551235522355323554235552355623557235582355923560235612356223563235642356523566235672356823569235702357123572235732357423575235762357723578235792358023581235822358323584235852358623587235882358923590235912359223593235942359523596235972359823599236002360123602236032360423605236062360723608236092361023611236122361323614236152361623617236182361923620236212362223623236242362523626236272362823629236302363123632236332363423635236362363723638236392364023641236422364323644236452364623647236482364923650236512365223653236542365523656236572365823659236602366123662236632366423665236662366723668236692367023671236722367323674236752367623677236782367923680236812368223683236842368523686236872368823689236902369123692236932369423695236962369723698236992370023701237022370323704237052370623707237082370923710237112371223713237142371523716237172371823719237202372123722237232372423725237262372723728237292373023731237322373323734237352373623737237382373923740237412374223743237442374523746237472374823749237502375123752237532375423755237562375723758237592376023761237622376323764237652376623767237682376923770237712377223773237742377523776237772377823779237802378123782237832378423785237862378723788237892379023791237922379323794237952379623797237982379923800238012380223803238042380523806238072380823809238102381123812238132381423815238162381723818238192382023821238222382323824238252382623827238282382923830238312383223833238342383523836238372383823839238402384123842238432384423845238462384723848238492385023851238522385323854238552385623857238582385923860238612386223863238642386523866238672386823869238702387123872238732387423875238762387723878238792388023881238822388323884238852388623887238882388923890238912389223893238942389523896238972389823899239002390123902239032390423905239062390723908239092391023911239122391323914239152391623917239182391923920239212392223923239242392523926239272392823929239302393123932239332393423935239362393723938239392394023941239422394323944239452394623947239482394923950239512395223953239542395523956239572395823959239602396123962239632396423965239662396723968239692397023971239722397323974239752397623977239782397923980239812398223983239842398523986239872398823989239902399123992239932399423995239962399723998239992400024001240022400324004240052400624007240082400924010240112401224013240142401524016240172401824019240202402124022240232402424025240262402724028240292403024031240322403324034240352403624037240382403924040240412404224043240442404524046240472404824049240502405124052240532405424055240562405724058240592406024061240622406324064240652406624067240682406924070240712407224073240742407524076240772407824079240802408124082240832408424085240862408724088240892409024091240922409324094240952409624097240982409924100241012410224103241042410524106241072410824109241102411124112241132411424115241162411724118241192412024121241222412324124241252412624127241282412924130241312413224133241342413524136241372413824139241402414124142241432414424145241462414724148241492415024151241522415324154241552415624157241582415924160241612416224163241642416524166241672416824169241702417124172241732417424175241762417724178241792418024181241822418324184241852418624187241882418924190241912419224193241942419524196241972419824199242002420124202242032420424205242062420724208242092421024211242122421324214242152421624217242182421924220242212422224223242242422524226242272422824229242302423124232242332423424235242362423724238242392424024241242422424324244242452424624247242482424924250242512425224253242542425524256242572425824259242602426124262242632426424265242662426724268242692427024271242722427324274242752427624277242782427924280242812428224283242842428524286242872428824289242902429124292242932429424295242962429724298242992430024301243022430324304243052430624307243082430924310243112431224313243142431524316243172431824319243202432124322243232432424325243262432724328243292433024331243322433324334243352433624337243382433924340243412434224343243442434524346243472434824349243502435124352243532435424355243562435724358243592436024361243622436324364243652436624367243682436924370243712437224373243742437524376243772437824379243802438124382243832438424385243862438724388243892439024391243922439324394243952439624397243982439924400244012440224403244042440524406244072440824409244102441124412244132441424415244162441724418244192442024421244222442324424244252442624427244282442924430244312443224433244342443524436244372443824439244402444124442244432444424445244462444724448244492445024451244522445324454244552445624457244582445924460244612446224463244642446524466244672446824469244702447124472244732447424475244762447724478244792448024481244822448324484244852448624487244882448924490244912449224493244942449524496244972449824499245002450124502245032450424505245062450724508245092451024511245122451324514245152451624517245182451924520245212452224523245242452524526245272452824529245302453124532245332453424535245362453724538245392454024541245422454324544245452454624547245482454924550245512455224553245542455524556245572455824559245602456124562245632456424565245662456724568245692457024571245722457324574245752457624577245782457924580245812458224583245842458524586245872458824589245902459124592245932459424595245962459724598245992460024601246022460324604246052460624607246082460924610246112461224613246142461524616246172461824619246202462124622246232462424625246262462724628246292463024631246322463324634246352463624637246382463924640246412464224643246442464524646246472464824649246502465124652246532465424655246562465724658246592466024661246622466324664246652466624667246682466924670246712467224673246742467524676246772467824679246802468124682246832468424685246862468724688246892469024691246922469324694246952469624697246982469924700247012470224703247042470524706247072470824709247102471124712247132471424715247162471724718247192472024721247222472324724247252472624727247282472924730247312473224733247342473524736247372473824739247402474124742247432474424745247462474724748247492475024751247522475324754247552475624757247582475924760247612476224763247642476524766247672476824769247702477124772247732477424775247762477724778247792478024781247822478324784247852478624787247882478924790247912479224793247942479524796247972479824799248002480124802248032480424805248062480724808248092481024811248122481324814248152481624817248182481924820248212482224823248242482524826248272482824829248302483124832248332483424835248362483724838248392484024841248422484324844248452484624847248482484924850248512485224853248542485524856248572485824859248602486124862248632486424865248662486724868248692487024871248722487324874248752487624877248782487924880248812488224883248842488524886248872488824889248902489124892248932489424895248962489724898248992490024901249022490324904249052490624907249082490924910249112491224913249142491524916249172491824919249202492124922249232492424925249262492724928249292493024931249322493324934249352493624937249382493924940249412494224943249442494524946249472494824949249502495124952249532495424955249562495724958249592496024961249622496324964249652496624967249682496924970249712497224973249742497524976249772497824979249802498124982249832498424985249862498724988249892499024991249922499324994249952499624997249982499925000250012500225003250042500525006250072500825009250102501125012250132501425015250162501725018250192502025021250222502325024250252502625027250282502925030250312503225033250342503525036250372503825039250402504125042250432504425045250462504725048250492505025051250522505325054250552505625057250582505925060250612506225063250642506525066250672506825069250702507125072250732507425075250762507725078250792508025081250822508325084250852508625087250882508925090250912509225093250942509525096250972509825099251002510125102251032510425105251062510725108251092511025111251122511325114251152511625117251182511925120251212512225123251242512525126251272512825129251302513125132251332513425135251362513725138251392514025141251422514325144251452514625147251482514925150251512515225153251542515525156251572515825159251602516125162251632516425165251662516725168251692517025171251722517325174251752517625177251782517925180251812518225183251842518525186251872518825189251902519125192251932519425195251962519725198251992520025201252022520325204252052520625207252082520925210252112521225213252142521525216252172521825219252202522125222252232522425225252262522725228252292523025231252322523325234252352523625237252382523925240252412524225243252442524525246252472524825249252502525125252252532525425255252562525725258252592526025261252622526325264252652526625267252682526925270252712527225273252742527525276252772527825279252802528125282252832528425285252862528725288252892529025291252922529325294252952529625297252982529925300253012530225303253042530525306253072530825309253102531125312253132531425315253162531725318253192532025321253222532325324253252532625327253282532925330253312533225333253342533525336253372533825339253402534125342253432534425345253462534725348253492535025351253522535325354253552535625357253582535925360253612536225363253642536525366253672536825369253702537125372253732537425375253762537725378253792538025381253822538325384253852538625387253882538925390253912539225393253942539525396253972539825399254002540125402254032540425405254062540725408254092541025411254122541325414254152541625417254182541925420254212542225423254242542525426254272542825429254302543125432254332543425435254362543725438254392544025441254422544325444254452544625447254482544925450254512545225453254542545525456254572545825459254602546125462254632546425465254662546725468254692547025471254722547325474254752547625477254782547925480254812548225483254842548525486254872548825489254902549125492254932549425495254962549725498254992550025501255022550325504255052550625507255082550925510255112551225513255142551525516255172551825519255202552125522255232552425525255262552725528255292553025531255322553325534255352553625537255382553925540255412554225543255442554525546255472554825549255502555125552255532555425555255562555725558255592556025561255622556325564255652556625567255682556925570255712557225573255742557525576255772557825579255802558125582255832558425585255862558725588255892559025591255922559325594255952559625597255982559925600256012560225603256042560525606256072560825609256102561125612256132561425615256162561725618256192562025621256222562325624256252562625627256282562925630256312563225633256342563525636256372563825639256402564125642256432564425645256462564725648256492565025651256522565325654256552565625657256582565925660256612566225663256642566525666256672566825669256702567125672256732567425675256762567725678256792568025681256822568325684256852568625687256882568925690256912569225693256942569525696256972569825699257002570125702257032570425705257062570725708257092571025711257122571325714257152571625717257182571925720257212572225723257242572525726257272572825729257302573125732257332573425735257362573725738257392574025741257422574325744257452574625747257482574925750257512575225753257542575525756257572575825759257602576125762257632576425765257662576725768257692577025771257722577325774257752577625777257782577925780257812578225783257842578525786257872578825789257902579125792257932579425795257962579725798257992580025801258022580325804258052580625807258082580925810258112581225813258142581525816258172581825819258202582125822258232582425825258262582725828258292583025831258322583325834258352583625837258382583925840258412584225843258442584525846258472584825849258502585125852258532585425855258562585725858258592586025861258622586325864258652586625867258682586925870258712587225873258742587525876258772587825879258802588125882258832588425885258862588725888258892589025891258922589325894258952589625897258982589925900259012590225903259042590525906259072590825909259102591125912259132591425915259162591725918259192592025921259222592325924259252592625927259282592925930259312593225933259342593525936259372593825939259402594125942259432594425945259462594725948259492595025951259522595325954259552595625957259582595925960259612596225963259642596525966259672596825969259702597125972259732597425975259762597725978259792598025981259822598325984259852598625987259882598925990259912599225993259942599525996259972599825999260002600126002260032600426005260062600726008260092601026011260122601326014260152601626017260182601926020260212602226023260242602526026260272602826029260302603126032260332603426035260362603726038260392604026041260422604326044260452604626047260482604926050260512605226053260542605526056260572605826059260602606126062260632606426065260662606726068260692607026071260722607326074260752607626077260782607926080260812608226083260842608526086260872608826089260902609126092260932609426095260962609726098260992610026101261022610326104261052610626107261082610926110261112611226113261142611526116261172611826119261202612126122261232612426125261262612726128261292613026131261322613326134261352613626137261382613926140261412614226143261442614526146261472614826149261502615126152261532615426155261562615726158261592616026161261622616326164261652616626167261682616926170261712617226173261742617526176261772617826179261802618126182261832618426185261862618726188261892619026191261922619326194261952619626197261982619926200262012620226203262042620526206262072620826209262102621126212262132621426215262162621726218262192622026221262222622326224262252622626227262282622926230262312623226233262342623526236262372623826239262402624126242262432624426245262462624726248262492625026251262522625326254262552625626257262582625926260262612626226263262642626526266262672626826269262702627126272262732627426275262762627726278262792628026281262822628326284262852628626287262882628926290262912629226293262942629526296262972629826299263002630126302263032630426305263062630726308263092631026311263122631326314263152631626317263182631926320263212632226323263242632526326263272632826329263302633126332263332633426335263362633726338263392634026341263422634326344263452634626347263482634926350263512635226353263542635526356263572635826359263602636126362263632636426365263662636726368263692637026371263722637326374263752637626377263782637926380263812638226383263842638526386263872638826389263902639126392263932639426395263962639726398263992640026401264022640326404264052640626407264082640926410264112641226413264142641526416264172641826419264202642126422264232642426425264262642726428264292643026431264322643326434264352643626437264382643926440264412644226443264442644526446264472644826449264502645126452264532645426455264562645726458264592646026461264622646326464264652646626467264682646926470264712647226473264742647526476264772647826479264802648126482264832648426485264862648726488264892649026491264922649326494264952649626497264982649926500265012650226503265042650526506265072650826509265102651126512265132651426515265162651726518265192652026521265222652326524265252652626527265282652926530265312653226533265342653526536265372653826539265402654126542265432654426545265462654726548265492655026551265522655326554265552655626557265582655926560265612656226563265642656526566265672656826569265702657126572265732657426575265762657726578265792658026581265822658326584265852658626587265882658926590265912659226593265942659526596265972659826599266002660126602266032660426605266062660726608266092661026611266122661326614266152661626617266182661926620266212662226623266242662526626266272662826629266302663126632266332663426635266362663726638266392664026641266422664326644266452664626647266482664926650266512665226653266542665526656266572665826659266602666126662266632666426665266662666726668266692667026671266722667326674266752667626677266782667926680266812668226683266842668526686266872668826689266902669126692266932669426695266962669726698266992670026701267022670326704267052670626707267082670926710267112671226713267142671526716267172671826719267202672126722267232672426725267262672726728267292673026731267322673326734267352673626737267382673926740267412674226743267442674526746267472674826749267502675126752267532675426755267562675726758267592676026761267622676326764267652676626767267682676926770267712677226773267742677526776267772677826779267802678126782267832678426785267862678726788267892679026791267922679326794267952679626797267982679926800268012680226803268042680526806268072680826809268102681126812268132681426815268162681726818268192682026821268222682326824268252682626827268282682926830268312683226833268342683526836268372683826839268402684126842268432684426845268462684726848268492685026851268522685326854268552685626857268582685926860268612686226863268642686526866268672686826869268702687126872268732687426875268762687726878268792688026881268822688326884268852688626887268882688926890268912689226893268942689526896268972689826899269002690126902269032690426905269062690726908269092691026911269122691326914269152691626917269182691926920269212692226923269242692526926269272692826929269302693126932269332693426935269362693726938269392694026941269422694326944269452694626947269482694926950269512695226953269542695526956269572695826959269602696126962269632696426965269662696726968269692697026971269722697326974269752697626977269782697926980269812698226983269842698526986269872698826989269902699126992269932699426995269962699726998269992700027001270022700327004270052700627007270082700927010270112701227013270142701527016270172701827019270202702127022270232702427025270262702727028270292703027031270322703327034270352703627037270382703927040270412704227043270442704527046270472704827049270502705127052270532705427055270562705727058270592706027061270622706327064270652706627067270682706927070270712707227073270742707527076270772707827079270802708127082270832708427085270862708727088270892709027091270922709327094270952709627097270982709927100271012710227103271042710527106271072710827109271102711127112271132711427115271162711727118271192712027121271222712327124271252712627127271282712927130271312713227133271342713527136271372713827139271402714127142271432714427145271462714727148271492715027151271522715327154271552715627157271582715927160271612716227163271642716527166271672716827169271702717127172271732717427175271762717727178271792718027181271822718327184271852718627187271882718927190271912719227193271942719527196271972719827199272002720127202272032720427205272062720727208272092721027211272122721327214272152721627217272182721927220272212722227223272242722527226272272722827229272302723127232272332723427235272362723727238272392724027241272422724327244272452724627247272482724927250272512725227253272542725527256272572725827259272602726127262272632726427265272662726727268272692727027271272722727327274272752727627277272782727927280272812728227283272842728527286272872728827289272902729127292272932729427295272962729727298272992730027301273022730327304273052730627307273082730927310273112731227313273142731527316273172731827319273202732127322273232732427325273262732727328273292733027331273322733327334273352733627337273382733927340273412734227343273442734527346273472734827349273502735127352273532735427355273562735727358273592736027361273622736327364273652736627367273682736927370273712737227373273742737527376273772737827379273802738127382273832738427385273862738727388273892739027391273922739327394273952739627397273982739927400274012740227403274042740527406274072740827409274102741127412274132741427415274162741727418274192742027421274222742327424274252742627427274282742927430274312743227433274342743527436274372743827439274402744127442274432744427445274462744727448274492745027451274522745327454274552745627457274582745927460274612746227463274642746527466274672746827469274702747127472274732747427475274762747727478274792748027481274822748327484274852748627487274882748927490274912749227493274942749527496274972749827499275002750127502275032750427505275062750727508275092751027511275122751327514275152751627517275182751927520275212752227523275242752527526275272752827529275302753127532275332753427535275362753727538275392754027541275422754327544275452754627547275482754927550275512755227553275542755527556275572755827559275602756127562275632756427565275662756727568275692757027571275722757327574275752757627577275782757927580275812758227583275842758527586275872758827589275902759127592275932759427595275962759727598275992760027601276022760327604276052760627607276082760927610276112761227613276142761527616276172761827619276202762127622276232762427625276262762727628276292763027631276322763327634276352763627637276382763927640276412764227643276442764527646276472764827649276502765127652276532765427655276562765727658276592766027661276622766327664276652766627667276682766927670276712767227673276742767527676276772767827679276802768127682276832768427685276862768727688276892769027691276922769327694276952769627697276982769927700277012770227703277042770527706277072770827709277102771127712277132771427715277162771727718277192772027721277222772327724277252772627727277282772927730277312773227733277342773527736277372773827739277402774127742277432774427745277462774727748277492775027751277522775327754277552775627757277582775927760277612776227763277642776527766277672776827769277702777127772277732777427775277762777727778277792778027781277822778327784277852778627787277882778927790277912779227793277942779527796277972779827799278002780127802278032780427805278062780727808278092781027811278122781327814278152781627817278182781927820278212782227823278242782527826278272782827829278302783127832278332783427835278362783727838278392784027841278422784327844278452784627847278482784927850278512785227853278542785527856278572785827859278602786127862278632786427865278662786727868278692787027871278722787327874278752787627877278782787927880278812788227883278842788527886278872788827889278902789127892278932789427895278962789727898278992790027901279022790327904279052790627907279082790927910279112791227913279142791527916279172791827919279202792127922279232792427925279262792727928279292793027931279322793327934279352793627937279382793927940279412794227943279442794527946279472794827949279502795127952279532795427955279562795727958279592796027961279622796327964279652796627967279682796927970279712797227973279742797527976279772797827979279802798127982279832798427985279862798727988279892799027991279922799327994279952799627997279982799928000280012800228003280042800528006280072800828009280102801128012280132801428015280162801728018280192802028021280222802328024280252802628027280282802928030280312803228033280342803528036280372803828039280402804128042280432804428045280462804728048280492805028051280522805328054280552805628057280582805928060280612806228063280642806528066280672806828069280702807128072280732807428075280762807728078280792808028081280822808328084280852808628087280882808928090280912809228093280942809528096280972809828099281002810128102281032810428105281062810728108281092811028111281122811328114281152811628117281182811928120281212812228123281242812528126281272812828129281302813128132281332813428135281362813728138281392814028141281422814328144281452814628147281482814928150281512815228153281542815528156281572815828159281602816128162281632816428165281662816728168281692817028171281722817328174281752817628177281782817928180281812818228183281842818528186281872818828189281902819128192281932819428195281962819728198281992820028201282022820328204282052820628207282082820928210282112821228213282142821528216282172821828219282202822128222282232822428225282262822728228282292823028231282322823328234282352823628237282382823928240282412824228243282442824528246282472824828249282502825128252282532825428255282562825728258282592826028261282622826328264282652826628267282682826928270282712827228273282742827528276282772827828279282802828128282282832828428285282862828728288282892829028291282922829328294282952829628297282982829928300283012830228303283042830528306283072830828309283102831128312283132831428315283162831728318283192832028321283222832328324283252832628327283282832928330283312833228333283342833528336283372833828339283402834128342283432834428345283462834728348283492835028351283522835328354283552835628357283582835928360283612836228363283642836528366283672836828369283702837128372283732837428375283762837728378283792838028381283822838328384283852838628387283882838928390283912839228393283942839528396283972839828399284002840128402284032840428405284062840728408284092841028411284122841328414284152841628417284182841928420284212842228423284242842528426284272842828429284302843128432284332843428435284362843728438284392844028441284422844328444284452844628447284482844928450284512845228453284542845528456284572845828459284602846128462284632846428465284662846728468284692847028471284722847328474284752847628477284782847928480284812848228483284842848528486284872848828489284902849128492284932849428495284962849728498284992850028501285022850328504285052850628507285082850928510285112851228513285142851528516285172851828519285202852128522285232852428525285262852728528285292853028531285322853328534285352853628537285382853928540285412854228543285442854528546285472854828549285502855128552285532855428555285562855728558285592856028561285622856328564285652856628567285682856928570285712857228573285742857528576285772857828579285802858128582285832858428585285862858728588285892859028591285922859328594285952859628597285982859928600286012860228603286042860528606286072860828609286102861128612286132861428615286162861728618286192862028621286222862328624286252862628627286282862928630286312863228633286342863528636286372863828639286402864128642286432864428645286462864728648286492865028651286522865328654286552865628657286582865928660286612866228663286642866528666286672866828669286702867128672286732867428675286762867728678286792868028681286822868328684286852868628687286882868928690286912869228693286942869528696286972869828699287002870128702287032870428705287062870728708287092871028711287122871328714287152871628717287182871928720287212872228723287242872528726287272872828729287302873128732287332873428735287362873728738287392874028741287422874328744287452874628747287482874928750287512875228753287542875528756287572875828759287602876128762287632876428765287662876728768287692877028771287722877328774287752877628777287782877928780287812878228783287842878528786287872878828789287902879128792287932879428795287962879728798287992880028801288022880328804288052880628807288082880928810288112881228813288142881528816288172881828819288202882128822288232882428825288262882728828288292883028831288322883328834288352883628837288382883928840288412884228843288442884528846288472884828849288502885128852288532885428855288562885728858288592886028861288622886328864288652886628867288682886928870288712887228873288742887528876288772887828879288802888128882288832888428885288862888728888288892889028891288922889328894288952889628897288982889928900289012890228903289042890528906289072890828909289102891128912289132891428915289162891728918289192892028921289222892328924289252892628927289282892928930289312893228933289342893528936289372893828939289402894128942289432894428945289462894728948289492895028951289522895328954289552895628957289582895928960289612896228963289642896528966289672896828969289702897128972289732897428975289762897728978289792898028981289822898328984289852898628987289882898928990289912899228993289942899528996289972899828999290002900129002290032900429005290062900729008290092901029011290122901329014290152901629017290182901929020290212902229023290242902529026290272902829029290302903129032290332903429035290362903729038290392904029041290422904329044290452904629047290482904929050290512905229053290542905529056290572905829059290602906129062290632906429065290662906729068290692907029071290722907329074290752907629077290782907929080290812908229083290842908529086290872908829089290902909129092290932909429095290962909729098290992910029101291022910329104291052910629107291082910929110291112911229113291142911529116291172911829119291202912129122291232912429125291262912729128291292913029131291322913329134291352913629137291382913929140291412914229143291442914529146291472914829149291502915129152291532915429155291562915729158291592916029161291622916329164291652916629167291682916929170291712917229173291742917529176291772917829179291802918129182291832918429185291862918729188291892919029191291922919329194291952919629197291982919929200292012920229203292042920529206292072920829209292102921129212292132921429215292162921729218292192922029221292222922329224292252922629227292282922929230292312923229233292342923529236292372923829239292402924129242292432924429245292462924729248292492925029251292522925329254292552925629257292582925929260292612926229263292642926529266292672926829269292702927129272292732927429275292762927729278292792928029281292822928329284292852928629287292882928929290292912929229293292942929529296292972929829299293002930129302293032930429305293062930729308293092931029311293122931329314293152931629317293182931929320293212932229323293242932529326293272932829329293302933129332293332933429335293362933729338293392934029341293422934329344293452934629347293482934929350293512935229353293542935529356293572935829359293602936129362293632936429365293662936729368293692937029371293722937329374293752937629377293782937929380293812938229383293842938529386293872938829389293902939129392293932939429395293962939729398293992940029401294022940329404294052940629407294082940929410294112941229413294142941529416294172941829419294202942129422294232942429425294262942729428294292943029431294322943329434294352943629437294382943929440294412944229443294442944529446294472944829449294502945129452294532945429455294562945729458294592946029461294622946329464294652946629467294682946929470294712947229473294742947529476294772947829479294802948129482294832948429485294862948729488294892949029491294922949329494294952949629497294982949929500295012950229503295042950529506295072950829509295102951129512295132951429515295162951729518295192952029521295222952329524295252952629527295282952929530295312953229533295342953529536295372953829539295402954129542295432954429545295462954729548295492955029551295522955329554295552955629557295582955929560295612956229563295642956529566295672956829569295702957129572295732957429575295762957729578295792958029581295822958329584295852958629587295882958929590295912959229593295942959529596295972959829599296002960129602296032960429605296062960729608296092961029611296122961329614296152961629617296182961929620296212962229623296242962529626296272962829629296302963129632296332963429635296362963729638296392964029641296422964329644296452964629647296482964929650296512965229653296542965529656296572965829659296602966129662296632966429665296662966729668296692967029671296722967329674296752967629677296782967929680296812968229683296842968529686296872968829689296902969129692296932969429695296962969729698296992970029701297022970329704297052970629707297082970929710297112971229713297142971529716297172971829719297202972129722297232972429725297262972729728297292973029731297322973329734297352973629737297382973929740297412974229743297442974529746297472974829749297502975129752297532975429755297562975729758297592976029761297622976329764297652976629767297682976929770297712977229773297742977529776297772977829779297802978129782297832978429785297862978729788297892979029791297922979329794297952979629797297982979929800298012980229803298042980529806298072980829809298102981129812298132981429815298162981729818298192982029821298222982329824298252982629827298282982929830298312983229833298342983529836298372983829839298402984129842298432984429845298462984729848298492985029851298522985329854298552985629857298582985929860298612986229863298642986529866298672986829869298702987129872298732987429875298762987729878298792988029881298822988329884298852988629887298882988929890298912989229893298942989529896298972989829899299002990129902299032990429905299062990729908299092991029911299122991329914299152991629917299182991929920299212992229923299242992529926299272992829929299302993129932299332993429935299362993729938299392994029941299422994329944299452994629947299482994929950299512995229953299542995529956299572995829959299602996129962299632996429965299662996729968299692997029971299722997329974299752997629977299782997929980299812998229983299842998529986299872998829989299902999129992299932999429995299962999729998299993000030001300023000330004300053000630007300083000930010300113001230013300143001530016300173001830019300203002130022300233002430025300263002730028300293003030031300323003330034300353003630037300383003930040300413004230043300443004530046300473004830049300503005130052300533005430055300563005730058300593006030061300623006330064300653006630067300683006930070300713007230073300743007530076300773007830079300803008130082300833008430085300863008730088300893009030091300923009330094300953009630097300983009930100301013010230103301043010530106301073010830109301103011130112301133011430115301163011730118301193012030121301223012330124301253012630127301283012930130301313013230133301343013530136301373013830139301403014130142301433014430145301463014730148301493015030151301523015330154301553015630157301583015930160301613016230163301643016530166301673016830169301703017130172301733017430175301763017730178301793018030181301823018330184301853018630187301883018930190301913019230193301943019530196301973019830199302003020130202302033020430205302063020730208302093021030211302123021330214302153021630217302183021930220302213022230223302243022530226302273022830229302303023130232302333023430235302363023730238302393024030241302423024330244302453024630247302483024930250302513025230253302543025530256302573025830259302603026130262302633026430265302663026730268302693027030271302723027330274302753027630277302783027930280302813028230283302843028530286302873028830289302903029130292302933029430295302963029730298302993030030301303023030330304303053030630307303083030930310303113031230313303143031530316303173031830319303203032130322303233032430325303263032730328303293033030331303323033330334303353033630337303383033930340303413034230343303443034530346303473034830349303503035130352303533035430355303563035730358303593036030361303623036330364303653036630367303683036930370303713037230373303743037530376303773037830379303803038130382303833038430385303863038730388303893039030391303923039330394303953039630397303983039930400304013040230403304043040530406304073040830409304103041130412304133041430415304163041730418304193042030421304223042330424304253042630427304283042930430304313043230433304343043530436304373043830439304403044130442304433044430445304463044730448304493045030451304523045330454304553045630457304583045930460304613046230463304643046530466304673046830469304703047130472304733047430475304763047730478304793048030481304823048330484304853048630487304883048930490304913049230493304943049530496304973049830499305003050130502305033050430505305063050730508305093051030511305123051330514305153051630517305183051930520305213052230523305243052530526305273052830529305303053130532305333053430535305363053730538305393054030541305423054330544305453054630547305483054930550305513055230553305543055530556305573055830559305603056130562305633056430565305663056730568305693057030571305723057330574305753057630577305783057930580305813058230583305843058530586305873058830589305903059130592305933059430595305963059730598305993060030601306023060330604306053060630607306083060930610306113061230613306143061530616306173061830619306203062130622306233062430625306263062730628306293063030631306323063330634306353063630637306383063930640306413064230643306443064530646306473064830649306503065130652306533065430655306563065730658306593066030661306623066330664306653066630667306683066930670306713067230673306743067530676306773067830679306803068130682306833068430685306863068730688306893069030691306923069330694306953069630697306983069930700307013070230703307043070530706307073070830709307103071130712307133071430715307163071730718307193072030721307223072330724307253072630727307283072930730307313073230733307343073530736307373073830739307403074130742307433074430745307463074730748307493075030751307523075330754307553075630757307583075930760307613076230763307643076530766307673076830769307703077130772307733077430775307763077730778307793078030781307823078330784307853078630787307883078930790307913079230793307943079530796307973079830799308003080130802308033080430805308063080730808308093081030811308123081330814308153081630817308183081930820308213082230823308243082530826308273082830829308303083130832308333083430835308363083730838308393084030841308423084330844308453084630847308483084930850308513085230853308543085530856308573085830859308603086130862308633086430865308663086730868308693087030871308723087330874308753087630877308783087930880308813088230883308843088530886308873088830889308903089130892308933089430895308963089730898308993090030901309023090330904309053090630907309083090930910309113091230913309143091530916309173091830919309203092130922309233092430925309263092730928309293093030931309323093330934309353093630937309383093930940309413094230943309443094530946309473094830949309503095130952309533095430955309563095730958309593096030961309623096330964309653096630967309683096930970309713097230973309743097530976309773097830979309803098130982309833098430985309863098730988309893099030991309923099330994309953099630997309983099931000310013100231003310043100531006310073100831009310103101131012310133101431015310163101731018310193102031021310223102331024310253102631027310283102931030310313103231033310343103531036310373103831039310403104131042310433104431045310463104731048310493105031051310523105331054310553105631057310583105931060310613106231063310643106531066310673106831069310703107131072310733107431075310763107731078310793108031081310823108331084310853108631087310883108931090310913109231093310943109531096310973109831099311003110131102311033110431105311063110731108311093111031111311123111331114311153111631117311183111931120311213112231123311243112531126311273112831129311303113131132311333113431135311363113731138311393114031141311423114331144311453114631147311483114931150311513115231153311543115531156311573115831159311603116131162311633116431165311663116731168311693117031171311723117331174311753117631177311783117931180311813118231183311843118531186311873118831189311903119131192311933119431195311963119731198311993120031201312023120331204312053120631207312083120931210312113121231213312143121531216312173121831219312203122131222312233122431225312263122731228312293123031231312323123331234312353123631237312383123931240312413124231243312443124531246312473124831249312503125131252312533125431255312563125731258312593126031261312623126331264312653126631267312683126931270312713127231273312743127531276312773127831279312803128131282312833128431285312863128731288312893129031291312923129331294312953129631297312983129931300313013130231303313043130531306313073130831309313103131131312313133131431315313163131731318313193132031321313223132331324313253132631327313283132931330313313133231333313343133531336313373133831339313403134131342313433134431345313463134731348313493135031351313523135331354313553135631357313583135931360313613136231363313643136531366313673136831369313703137131372313733137431375313763137731378313793138031381313823138331384313853138631387313883138931390313913139231393313943139531396313973139831399314003140131402314033140431405314063140731408314093141031411314123141331414314153141631417314183141931420314213142231423314243142531426314273142831429314303143131432314333143431435314363143731438314393144031441314423144331444314453144631447314483144931450314513145231453314543145531456314573145831459314603146131462314633146431465314663146731468314693147031471314723147331474314753147631477314783147931480314813148231483314843148531486314873148831489314903149131492314933149431495314963149731498314993150031501315023150331504315053150631507315083150931510315113151231513315143151531516315173151831519315203152131522315233152431525315263152731528315293153031531315323153331534315353153631537315383153931540315413154231543315443154531546315473154831549315503155131552315533155431555315563155731558315593156031561315623156331564315653156631567315683156931570315713157231573315743157531576315773157831579315803158131582315833158431585315863158731588315893159031591315923159331594315953159631597315983159931600316013160231603316043160531606316073160831609316103161131612316133161431615316163161731618316193162031621316223162331624316253162631627316283162931630316313163231633316343163531636316373163831639316403164131642316433164431645316463164731648316493165031651316523165331654316553165631657316583165931660316613166231663316643166531666316673166831669316703167131672316733167431675316763167731678316793168031681316823168331684316853168631687316883168931690316913169231693316943169531696316973169831699317003170131702317033170431705317063170731708317093171031711317123171331714317153171631717317183171931720317213172231723317243172531726317273172831729317303173131732317333173431735317363173731738317393174031741317423174331744317453174631747317483174931750317513175231753317543175531756317573175831759317603176131762317633176431765317663176731768317693177031771317723177331774317753177631777317783177931780317813178231783317843178531786317873178831789317903179131792317933179431795317963179731798317993180031801318023180331804318053180631807318083180931810318113181231813318143181531816318173181831819318203182131822318233182431825318263182731828318293183031831318323183331834318353183631837318383183931840318413184231843318443184531846318473184831849318503185131852318533185431855318563185731858318593186031861318623186331864318653186631867318683186931870318713187231873318743187531876318773187831879318803188131882318833188431885318863188731888318893189031891318923189331894318953189631897318983189931900319013190231903319043190531906319073190831909319103191131912319133191431915319163191731918319193192031921319223192331924319253192631927319283192931930319313193231933319343193531936319373193831939319403194131942319433194431945319463194731948319493195031951319523195331954319553195631957319583195931960319613196231963319643196531966319673196831969319703197131972319733197431975319763197731978319793198031981319823198331984319853198631987319883198931990319913199231993319943199531996319973199831999320003200132002320033200432005320063200732008320093201032011320123201332014320153201632017320183201932020320213202232023320243202532026320273202832029320303203132032320333203432035320363203732038320393204032041320423204332044320453204632047320483204932050320513205232053320543205532056320573205832059320603206132062320633206432065320663206732068320693207032071320723207332074320753207632077320783207932080320813208232083320843208532086320873208832089320903209132092320933209432095320963209732098320993210032101321023210332104321053210632107321083210932110321113211232113321143211532116321173211832119321203212132122321233212432125321263212732128321293213032131321323213332134321353213632137321383213932140321413214232143321443214532146321473214832149321503215132152321533215432155321563215732158321593216032161321623216332164321653216632167321683216932170321713217232173321743217532176321773217832179321803218132182321833218432185321863218732188321893219032191321923219332194321953219632197321983219932200322013220232203322043220532206322073220832209322103221132212322133221432215322163221732218322193222032221322223222332224322253222632227322283222932230322313223232233322343223532236322373223832239322403224132242322433224432245322463224732248322493225032251322523225332254322553225632257322583225932260322613226232263322643226532266322673226832269322703227132272322733227432275322763227732278322793228032281322823228332284322853228632287322883228932290322913229232293322943229532296322973229832299323003230132302323033230432305323063230732308323093231032311323123231332314323153231632317323183231932320323213232232323323243232532326323273232832329323303233132332323333233432335323363233732338323393234032341323423234332344323453234632347323483234932350323513235232353323543235532356323573235832359323603236132362323633236432365323663236732368323693237032371323723237332374323753237632377323783237932380323813238232383323843238532386323873238832389323903239132392323933239432395323963239732398323993240032401324023240332404324053240632407324083240932410324113241232413324143241532416324173241832419324203242132422324233242432425324263242732428324293243032431324323243332434324353243632437324383243932440324413244232443324443244532446324473244832449324503245132452324533245432455324563245732458324593246032461324623246332464324653246632467324683246932470324713247232473324743247532476324773247832479324803248132482324833248432485324863248732488324893249032491324923249332494324953249632497324983249932500325013250232503325043250532506325073250832509325103251132512325133251432515325163251732518325193252032521325223252332524325253252632527325283252932530325313253232533325343253532536325373253832539325403254132542325433254432545325463254732548325493255032551325523255332554325553255632557325583255932560325613256232563325643256532566325673256832569325703257132572325733257432575325763257732578325793258032581325823258332584325853258632587325883258932590325913259232593325943259532596325973259832599326003260132602326033260432605326063260732608326093261032611326123261332614326153261632617326183261932620326213262232623326243262532626326273262832629326303263132632326333263432635326363263732638326393264032641326423264332644326453264632647326483264932650326513265232653326543265532656326573265832659326603266132662326633266432665326663266732668326693267032671326723267332674326753267632677326783267932680326813268232683326843268532686326873268832689326903269132692326933269432695326963269732698326993270032701327023270332704327053270632707327083270932710327113271232713327143271532716327173271832719327203272132722327233272432725327263272732728327293273032731327323273332734327353273632737327383273932740327413274232743327443274532746327473274832749327503275132752327533275432755327563275732758327593276032761327623276332764327653276632767327683276932770327713277232773327743277532776327773277832779327803278132782327833278432785327863278732788327893279032791327923279332794327953279632797327983279932800328013280232803328043280532806328073280832809328103281132812328133281432815328163281732818328193282032821328223282332824328253282632827328283282932830328313283232833328343283532836328373283832839328403284132842328433284432845328463284732848328493285032851328523285332854328553285632857328583285932860328613286232863328643286532866328673286832869328703287132872328733287432875328763287732878328793288032881328823288332884328853288632887328883288932890328913289232893328943289532896328973289832899329003290132902329033290432905329063290732908329093291032911329123291332914329153291632917329183291932920329213292232923329243292532926329273292832929329303293132932329333293432935329363293732938329393294032941329423294332944329453294632947329483294932950329513295232953329543295532956329573295832959329603296132962329633296432965329663296732968329693297032971329723297332974329753297632977329783297932980329813298232983329843298532986329873298832989329903299132992329933299432995329963299732998329993300033001330023300333004330053300633007330083300933010330113301233013330143301533016330173301833019330203302133022330233302433025330263302733028330293303033031330323303333034330353303633037330383303933040330413304233043330443304533046330473304833049330503305133052330533305433055330563305733058330593306033061330623306333064330653306633067330683306933070330713307233073330743307533076330773307833079330803308133082330833308433085330863308733088330893309033091330923309333094330953309633097330983309933100331013310233103331043310533106331073310833109331103311133112331133311433115331163311733118331193312033121331223312333124331253312633127331283312933130331313313233133331343313533136331373313833139331403314133142331433314433145331463314733148331493315033151331523315333154331553315633157331583315933160331613316233163331643316533166331673316833169331703317133172331733317433175331763317733178331793318033181331823318333184331853318633187331883318933190331913319233193331943319533196331973319833199332003320133202332033320433205332063320733208332093321033211332123321333214332153321633217332183321933220332213322233223332243322533226332273322833229332303323133232332333323433235332363323733238332393324033241332423324333244332453324633247332483324933250332513325233253332543325533256332573325833259332603326133262332633326433265332663326733268332693327033271332723327333274332753327633277332783327933280332813328233283332843328533286332873328833289332903329133292332933329433295332963329733298332993330033301333023330333304333053330633307333083330933310333113331233313333143331533316333173331833319333203332133322333233332433325333263332733328333293333033331333323333333334333353333633337333383333933340333413334233343333443334533346333473334833349333503335133352333533335433355333563335733358333593336033361333623336333364333653336633367333683336933370333713337233373333743337533376333773337833379333803338133382333833338433385333863338733388333893339033391333923339333394333953339633397333983339933400334013340233403334043340533406334073340833409334103341133412334133341433415334163341733418334193342033421334223342333424334253342633427334283342933430334313343233433334343343533436334373343833439334403344133442334433344433445334463344733448334493345033451334523345333454334553345633457334583345933460334613346233463334643346533466334673346833469334703347133472334733347433475334763347733478334793348033481334823348333484334853348633487334883348933490334913349233493334943349533496334973349833499335003350133502335033350433505335063350733508335093351033511335123351333514335153351633517335183351933520335213352233523335243352533526335273352833529335303353133532335333353433535335363353733538335393354033541335423354333544335453354633547335483354933550335513355233553335543355533556335573355833559335603356133562335633356433565335663356733568335693357033571335723357333574335753357633577335783357933580335813358233583335843358533586335873358833589335903359133592335933359433595335963359733598335993360033601336023360333604336053360633607336083360933610336113361233613336143361533616336173361833619336203362133622336233362433625336263362733628336293363033631336323363333634336353363633637336383363933640336413364233643336443364533646336473364833649336503365133652336533365433655336563365733658336593366033661336623366333664336653366633667336683366933670336713367233673336743367533676336773367833679336803368133682336833368433685336863368733688336893369033691336923369333694336953369633697336983369933700337013370233703337043370533706337073370833709337103371133712337133371433715337163371733718337193372033721337223372333724337253372633727337283372933730337313373233733337343373533736337373373833739337403374133742337433374433745337463374733748337493375033751337523375333754337553375633757337583375933760337613376233763337643376533766337673376833769337703377133772337733377433775337763377733778337793378033781337823378333784337853378633787337883378933790337913379233793337943379533796337973379833799338003380133802338033380433805338063380733808338093381033811338123381333814338153381633817338183381933820338213382233823338243382533826338273382833829338303383133832338333383433835338363383733838338393384033841338423384333844338453384633847338483384933850338513385233853338543385533856338573385833859338603386133862338633386433865338663386733868338693387033871338723387333874338753387633877338783387933880338813388233883338843388533886338873388833889338903389133892338933389433895338963389733898338993390033901339023390333904339053390633907339083390933910339113391233913339143391533916339173391833919339203392133922339233392433925339263392733928339293393033931339323393333934339353393633937339383393933940339413394233943339443394533946339473394833949339503395133952339533395433955339563395733958339593396033961339623396333964339653396633967339683396933970339713397233973339743397533976339773397833979339803398133982339833398433985339863398733988339893399033991339923399333994339953399633997339983399934000340013400234003340043400534006340073400834009340103401134012340133401434015340163401734018340193402034021340223402334024340253402634027340283402934030340313403234033340343403534036340373403834039340403404134042340433404434045340463404734048340493405034051340523405334054340553405634057340583405934060340613406234063340643406534066340673406834069340703407134072340733407434075340763407734078340793408034081340823408334084340853408634087340883408934090340913409234093340943409534096340973409834099341003410134102341033410434105341063410734108341093411034111341123411334114341153411634117341183411934120341213412234123341243412534126341273412834129341303413134132341333413434135341363413734138341393414034141341423414334144341453414634147341483414934150341513415234153341543415534156341573415834159341603416134162341633416434165341663416734168341693417034171341723417334174341753417634177341783417934180341813418234183341843418534186341873418834189341903419134192341933419434195341963419734198341993420034201342023420334204342053420634207342083420934210342113421234213342143421534216342173421834219342203422134222342233422434225342263422734228342293423034231342323423334234342353423634237342383423934240342413424234243342443424534246342473424834249342503425134252342533425434255342563425734258342593426034261342623426334264342653426634267342683426934270342713427234273342743427534276342773427834279342803428134282342833428434285342863428734288342893429034291342923429334294342953429634297342983429934300343013430234303343043430534306343073430834309343103431134312343133431434315343163431734318343193432034321343223432334324343253432634327343283432934330343313433234333343343433534336343373433834339343403434134342343433434434345343463434734348343493435034351343523435334354343553435634357343583435934360343613436234363343643436534366343673436834369343703437134372343733437434375343763437734378343793438034381343823438334384343853438634387343883438934390343913439234393343943439534396343973439834399344003440134402344033440434405344063440734408344093441034411344123441334414344153441634417344183441934420344213442234423344243442534426344273442834429344303443134432344333443434435344363443734438344393444034441344423444334444344453444634447344483444934450344513445234453344543445534456344573445834459344603446134462344633446434465344663446734468344693447034471344723447334474344753447634477344783447934480344813448234483344843448534486344873448834489344903449134492344933449434495344963449734498344993450034501345023450334504345053450634507345083450934510345113451234513345143451534516345173451834519345203452134522345233452434525345263452734528345293453034531345323453334534345353453634537345383453934540345413454234543345443454534546345473454834549345503455134552345533455434555345563455734558345593456034561345623456334564345653456634567345683456934570345713457234573345743457534576345773457834579345803458134582345833458434585345863458734588345893459034591345923459334594345953459634597345983459934600346013460234603346043460534606346073460834609346103461134612346133461434615346163461734618346193462034621346223462334624346253462634627346283462934630346313463234633346343463534636346373463834639346403464134642346433464434645346463464734648346493465034651346523465334654346553465634657346583465934660346613466234663346643466534666346673466834669346703467134672346733467434675346763467734678346793468034681346823468334684346853468634687346883468934690346913469234693346943469534696346973469834699347003470134702347033470434705347063470734708347093471034711347123471334714347153471634717347183471934720347213472234723347243472534726347273472834729347303473134732347333473434735347363473734738347393474034741347423474334744347453474634747347483474934750347513475234753347543475534756347573475834759347603476134762347633476434765347663476734768347693477034771347723477334774347753477634777347783477934780347813478234783347843478534786347873478834789347903479134792347933479434795347963479734798347993480034801348023480334804348053480634807348083480934810348113481234813348143481534816348173481834819348203482134822348233482434825348263482734828348293483034831348323483334834348353483634837348383483934840348413484234843348443484534846348473484834849348503485134852348533485434855348563485734858348593486034861348623486334864348653486634867348683486934870348713487234873348743487534876348773487834879348803488134882348833488434885348863488734888348893489034891348923489334894348953489634897348983489934900349013490234903349043490534906349073490834909349103491134912349133491434915349163491734918349193492034921349223492334924349253492634927349283492934930349313493234933349343493534936349373493834939349403494134942349433494434945349463494734948349493495034951349523495334954349553495634957349583495934960349613496234963349643496534966349673496834969349703497134972349733497434975349763497734978349793498034981349823498334984349853498634987349883498934990349913499234993349943499534996349973499834999350003500135002350033500435005350063500735008350093501035011350123501335014350153501635017350183501935020350213502235023350243502535026350273502835029350303503135032350333503435035350363503735038350393504035041350423504335044350453504635047350483504935050350513505235053350543505535056350573505835059350603506135062350633506435065350663506735068350693507035071350723507335074350753507635077350783507935080350813508235083350843508535086350873508835089350903509135092350933509435095350963509735098350993510035101351023510335104351053510635107351083510935110351113511235113351143511535116351173511835119351203512135122351233512435125351263512735128351293513035131351323513335134351353513635137351383513935140351413514235143351443514535146351473514835149351503515135152351533515435155351563515735158351593516035161351623516335164351653516635167351683516935170351713517235173351743517535176351773517835179351803518135182351833518435185351863518735188351893519035191351923519335194351953519635197351983519935200352013520235203352043520535206352073520835209352103521135212352133521435215352163521735218352193522035221352223522335224352253522635227352283522935230352313523235233352343523535236352373523835239352403524135242352433524435245352463524735248352493525035251352523525335254352553525635257352583525935260352613526235263352643526535266352673526835269352703527135272352733527435275352763527735278352793528035281352823528335284352853528635287352883528935290352913529235293352943529535296352973529835299353003530135302353033530435305353063530735308353093531035311353123531335314353153531635317353183531935320353213532235323353243532535326353273532835329353303533135332353333533435335353363533735338353393534035341353423534335344353453534635347353483534935350353513535235353353543535535356353573535835359353603536135362353633536435365353663536735368353693537035371353723537335374353753537635377353783537935380353813538235383353843538535386353873538835389353903539135392353933539435395353963539735398353993540035401354023540335404354053540635407354083540935410354113541235413354143541535416354173541835419354203542135422354233542435425354263542735428354293543035431354323543335434354353543635437354383543935440354413544235443354443544535446354473544835449354503545135452354533545435455354563545735458354593546035461354623546335464354653546635467354683546935470354713547235473354743547535476354773547835479354803548135482354833548435485354863548735488354893549035491354923549335494354953549635497354983549935500355013550235503355043550535506355073550835509355103551135512355133551435515355163551735518355193552035521355223552335524355253552635527355283552935530355313553235533355343553535536355373553835539355403554135542355433554435545355463554735548355493555035551355523555335554355553555635557355583555935560355613556235563355643556535566355673556835569355703557135572355733557435575355763557735578355793558035581355823558335584355853558635587355883558935590355913559235593355943559535596355973559835599356003560135602356033560435605356063560735608356093561035611356123561335614356153561635617356183561935620356213562235623356243562535626356273562835629356303563135632356333563435635356363563735638356393564035641356423564335644356453564635647356483564935650356513565235653356543565535656356573565835659356603566135662356633566435665356663566735668356693567035671356723567335674356753567635677356783567935680356813568235683356843568535686356873568835689356903569135692356933569435695356963569735698356993570035701357023570335704357053570635707357083570935710357113571235713357143571535716357173571835719357203572135722357233572435725357263572735728357293573035731357323573335734357353573635737357383573935740357413574235743357443574535746357473574835749357503575135752357533575435755357563575735758357593576035761357623576335764357653576635767357683576935770357713577235773357743577535776357773577835779357803578135782357833578435785357863578735788357893579035791357923579335794357953579635797357983579935800358013580235803358043580535806358073580835809358103581135812358133581435815358163581735818358193582035821358223582335824358253582635827358283582935830358313583235833358343583535836358373583835839358403584135842358433584435845358463584735848358493585035851358523585335854358553585635857358583585935860358613586235863358643586535866358673586835869358703587135872358733587435875358763587735878358793588035881358823588335884358853588635887358883588935890358913589235893358943589535896358973589835899359003590135902359033590435905359063590735908359093591035911359123591335914359153591635917359183591935920359213592235923359243592535926359273592835929359303593135932359333593435935359363593735938359393594035941359423594335944359453594635947359483594935950359513595235953359543595535956359573595835959359603596135962359633596435965359663596735968359693597035971359723597335974359753597635977359783597935980359813598235983359843598535986359873598835989359903599135992359933599435995359963599735998359993600036001360023600336004360053600636007360083600936010360113601236013360143601536016360173601836019360203602136022360233602436025360263602736028360293603036031360323603336034360353603636037360383603936040360413604236043360443604536046360473604836049360503605136052360533605436055360563605736058360593606036061360623606336064360653606636067360683606936070360713607236073360743607536076360773607836079360803608136082360833608436085360863608736088360893609036091360923609336094360953609636097360983609936100361013610236103361043610536106361073610836109361103611136112361133611436115361163611736118361193612036121361223612336124361253612636127361283612936130361313613236133361343613536136361373613836139361403614136142361433614436145361463614736148361493615036151361523615336154361553615636157361583615936160361613616236163361643616536166361673616836169361703617136172361733617436175361763617736178361793618036181361823618336184361853618636187361883618936190361913619236193361943619536196361973619836199362003620136202362033620436205362063620736208362093621036211362123621336214362153621636217362183621936220362213622236223362243622536226362273622836229362303623136232362333623436235362363623736238362393624036241362423624336244362453624636247362483624936250362513625236253362543625536256362573625836259362603626136262362633626436265362663626736268362693627036271362723627336274362753627636277362783627936280362813628236283362843628536286362873628836289362903629136292362933629436295362963629736298362993630036301363023630336304363053630636307363083630936310363113631236313363143631536316363173631836319363203632136322363233632436325363263632736328363293633036331363323633336334363353633636337363383633936340363413634236343363443634536346363473634836349363503635136352363533635436355363563635736358363593636036361363623636336364363653636636367363683636936370363713637236373363743637536376363773637836379363803638136382363833638436385363863638736388363893639036391363923639336394363953639636397363983639936400364013640236403364043640536406364073640836409364103641136412364133641436415364163641736418364193642036421364223642336424364253642636427364283642936430364313643236433364343643536436364373643836439364403644136442364433644436445364463644736448364493645036451364523645336454364553645636457364583645936460364613646236463364643646536466364673646836469364703647136472364733647436475364763647736478364793648036481364823648336484364853648636487364883648936490364913649236493364943649536496364973649836499365003650136502365033650436505365063650736508365093651036511365123651336514365153651636517365183651936520365213652236523365243652536526365273652836529365303653136532365333653436535365363653736538365393654036541365423654336544365453654636547365483654936550365513655236553365543655536556365573655836559365603656136562365633656436565365663656736568365693657036571365723657336574365753657636577365783657936580365813658236583365843658536586365873658836589365903659136592365933659436595365963659736598365993660036601366023660336604366053660636607366083660936610366113661236613366143661536616366173661836619366203662136622366233662436625366263662736628366293663036631366323663336634366353663636637366383663936640366413664236643366443664536646366473664836649366503665136652366533665436655366563665736658366593666036661366623666336664366653666636667366683666936670366713667236673366743667536676366773667836679366803668136682366833668436685366863668736688366893669036691366923669336694366953669636697366983669936700367013670236703367043670536706367073670836709367103671136712367133671436715367163671736718367193672036721367223672336724367253672636727367283672936730367313673236733367343673536736367373673836739367403674136742367433674436745367463674736748367493675036751367523675336754367553675636757367583675936760367613676236763367643676536766367673676836769367703677136772367733677436775367763677736778367793678036781367823678336784367853678636787367883678936790367913679236793367943679536796367973679836799368003680136802368033680436805368063680736808368093681036811368123681336814368153681636817368183681936820368213682236823368243682536826368273682836829368303683136832368333683436835368363683736838368393684036841368423684336844368453684636847368483684936850368513685236853368543685536856368573685836859368603686136862368633686436865368663686736868368693687036871368723687336874368753687636877368783687936880368813688236883368843688536886368873688836889368903689136892368933689436895368963689736898368993690036901369023690336904369053690636907369083690936910369113691236913369143691536916369173691836919369203692136922369233692436925369263692736928369293693036931369323693336934369353693636937369383693936940369413694236943369443694536946369473694836949369503695136952369533695436955369563695736958369593696036961369623696336964369653696636967369683696936970369713697236973369743697536976369773697836979369803698136982369833698436985369863698736988369893699036991369923699336994369953699636997369983699937000370013700237003370043700537006370073700837009370103701137012370133701437015370163701737018370193702037021370223702337024370253702637027370283702937030370313703237033370343703537036370373703837039370403704137042370433704437045370463704737048370493705037051370523705337054370553705637057370583705937060370613706237063370643706537066370673706837069370703707137072370733707437075370763707737078370793708037081370823708337084370853708637087370883708937090370913709237093370943709537096370973709837099371003710137102371033710437105371063710737108371093711037111371123711337114371153711637117371183711937120371213712237123371243712537126371273712837129371303713137132371333713437135371363713737138371393714037141371423714337144371453714637147371483714937150371513715237153371543715537156371573715837159371603716137162371633716437165371663716737168371693717037171371723717337174371753717637177371783717937180371813718237183371843718537186371873718837189371903719137192371933719437195371963719737198371993720037201372023720337204372053720637207372083720937210372113721237213372143721537216372173721837219372203722137222372233722437225372263722737228372293723037231372323723337234372353723637237372383723937240372413724237243372443724537246372473724837249372503725137252372533725437255372563725737258372593726037261372623726337264372653726637267372683726937270372713727237273372743727537276372773727837279372803728137282372833728437285372863728737288372893729037291372923729337294372953729637297372983729937300373013730237303373043730537306373073730837309373103731137312373133731437315373163731737318373193732037321373223732337324373253732637327373283732937330373313733237333373343733537336373373733837339373403734137342373433734437345373463734737348373493735037351373523735337354373553735637357373583735937360373613736237363373643736537366373673736837369373703737137372373733737437375373763737737378373793738037381373823738337384373853738637387373883738937390373913739237393373943739537396373973739837399374003740137402374033740437405374063740737408374093741037411374123741337414374153741637417374183741937420374213742237423374243742537426374273742837429374303743137432374333743437435374363743737438374393744037441374423744337444374453744637447374483744937450374513745237453374543745537456374573745837459374603746137462374633746437465374663746737468374693747037471374723747337474374753747637477374783747937480374813748237483374843748537486374873748837489374903749137492374933749437495374963749737498374993750037501375023750337504375053750637507375083750937510375113751237513375143751537516375173751837519375203752137522375233752437525375263752737528375293753037531375323753337534375353753637537375383753937540375413754237543375443754537546375473754837549375503755137552375533755437555375563755737558375593756037561375623756337564375653756637567375683756937570375713757237573375743757537576375773757837579375803758137582375833758437585375863758737588375893759037591375923759337594375953759637597375983759937600376013760237603376043760537606376073760837609376103761137612376133761437615376163761737618376193762037621376223762337624376253762637627376283762937630376313763237633376343763537636376373763837639376403764137642376433764437645376463764737648376493765037651376523765337654376553765637657376583765937660376613766237663376643766537666376673766837669376703767137672376733767437675376763767737678376793768037681376823768337684376853768637687376883768937690376913769237693376943769537696376973769837699377003770137702377033770437705377063770737708377093771037711377123771337714377153771637717377183771937720377213772237723377243772537726377273772837729377303773137732377333773437735377363773737738377393774037741377423774337744377453774637747377483774937750377513775237753377543775537756377573775837759377603776137762377633776437765377663776737768377693777037771377723777337774377753777637777377783777937780377813778237783377843778537786377873778837789377903779137792377933779437795377963779737798377993780037801378023780337804378053780637807378083780937810378113781237813378143781537816378173781837819378203782137822378233782437825378263782737828378293783037831378323783337834378353783637837378383783937840378413784237843378443784537846378473784837849378503785137852378533785437855378563785737858378593786037861378623786337864378653786637867378683786937870378713787237873378743787537876378773787837879378803788137882378833788437885378863788737888378893789037891378923789337894378953789637897378983789937900379013790237903379043790537906379073790837909379103791137912379133791437915379163791737918379193792037921379223792337924379253792637927379283792937930379313793237933379343793537936379373793837939379403794137942379433794437945379463794737948379493795037951379523795337954379553795637957379583795937960379613796237963379643796537966379673796837969379703797137972379733797437975379763797737978379793798037981379823798337984379853798637987379883798937990379913799237993379943799537996379973799837999380003800138002380033800438005380063800738008380093801038011380123801338014380153801638017380183801938020380213802238023380243802538026380273802838029380303803138032380333803438035380363803738038380393804038041380423804338044380453804638047380483804938050380513805238053380543805538056380573805838059380603806138062380633806438065380663806738068380693807038071380723807338074380753807638077380783807938080380813808238083380843808538086380873808838089380903809138092380933809438095380963809738098380993810038101381023810338104381053810638107381083810938110381113811238113381143811538116381173811838119381203812138122381233812438125381263812738128381293813038131381323813338134381353813638137381383813938140381413814238143381443814538146381473814838149381503815138152381533815438155381563815738158381593816038161381623816338164381653816638167381683816938170381713817238173381743817538176381773817838179381803818138182381833818438185381863818738188381893819038191381923819338194381953819638197381983819938200382013820238203382043820538206382073820838209382103821138212382133821438215382163821738218382193822038221382223822338224382253822638227382283822938230382313823238233382343823538236382373823838239382403824138242382433824438245382463824738248382493825038251382523825338254382553825638257382583825938260382613826238263382643826538266382673826838269382703827138272382733827438275382763827738278382793828038281382823828338284382853828638287382883828938290382913829238293382943829538296382973829838299383003830138302383033830438305383063830738308383093831038311383123831338314383153831638317383183831938320383213832238323383243832538326383273832838329383303833138332383333833438335383363833738338383393834038341383423834338344383453834638347383483834938350383513835238353383543835538356383573835838359383603836138362383633836438365383663836738368383693837038371383723837338374383753837638377383783837938380383813838238383383843838538386383873838838389383903839138392383933839438395383963839738398383993840038401384023840338404384053840638407384083840938410384113841238413384143841538416384173841838419384203842138422384233842438425384263842738428384293843038431384323843338434384353843638437384383843938440384413844238443384443844538446384473844838449384503845138452384533845438455384563845738458384593846038461384623846338464384653846638467384683846938470384713847238473384743847538476384773847838479384803848138482384833848438485384863848738488384893849038491384923849338494384953849638497384983849938500385013850238503385043850538506385073850838509385103851138512385133851438515385163851738518385193852038521385223852338524385253852638527385283852938530385313853238533385343853538536385373853838539385403854138542385433854438545385463854738548385493855038551385523855338554385553855638557385583855938560385613856238563385643856538566385673856838569385703857138572385733857438575385763857738578385793858038581385823858338584385853858638587385883858938590385913859238593385943859538596385973859838599386003860138602386033860438605386063860738608386093861038611386123861338614386153861638617386183861938620386213862238623386243862538626386273862838629386303863138632386333863438635386363863738638386393864038641386423864338644386453864638647386483864938650386513865238653386543865538656386573865838659386603866138662386633866438665386663866738668386693867038671386723867338674386753867638677386783867938680386813868238683386843868538686386873868838689386903869138692386933869438695386963869738698386993870038701387023870338704387053870638707387083870938710387113871238713387143871538716387173871838719387203872138722387233872438725387263872738728387293873038731387323873338734387353873638737387383873938740387413874238743387443874538746387473874838749387503875138752387533875438755387563875738758387593876038761387623876338764387653876638767387683876938770387713877238773387743877538776387773877838779387803878138782387833878438785387863878738788387893879038791387923879338794387953879638797387983879938800388013880238803388043880538806388073880838809388103881138812388133881438815388163881738818388193882038821388223882338824388253882638827388283882938830388313883238833388343883538836388373883838839388403884138842388433884438845388463884738848388493885038851388523885338854388553885638857388583885938860388613886238863388643886538866388673886838869388703887138872388733887438875388763887738878388793888038881388823888338884388853888638887388883888938890388913889238893388943889538896388973889838899389003890138902389033890438905389063890738908389093891038911389123891338914389153891638917389183891938920389213892238923389243892538926389273892838929389303893138932389333893438935389363893738938389393894038941389423894338944389453894638947389483894938950389513895238953389543895538956389573895838959389603896138962389633896438965389663896738968389693897038971389723897338974389753897638977389783897938980389813898238983389843898538986389873898838989389903899138992389933899438995389963899738998389993900039001390023900339004390053900639007390083900939010390113901239013390143901539016390173901839019390203902139022390233902439025390263902739028390293903039031390323903339034390353903639037390383903939040390413904239043390443904539046390473904839049390503905139052390533905439055390563905739058390593906039061390623906339064390653906639067390683906939070390713907239073390743907539076390773907839079390803908139082390833908439085390863908739088390893909039091390923909339094390953909639097390983909939100391013910239103391043910539106391073910839109391103911139112391133911439115391163911739118391193912039121391223912339124391253912639127391283912939130391313913239133391343913539136391373913839139391403914139142391433914439145391463914739148391493915039151391523915339154391553915639157391583915939160391613916239163391643916539166391673916839169391703917139172391733917439175391763917739178391793918039181391823918339184391853918639187391883918939190391913919239193391943919539196391973919839199392003920139202392033920439205392063920739208392093921039211392123921339214392153921639217392183921939220392213922239223392243922539226392273922839229392303923139232392333923439235392363923739238392393924039241392423924339244392453924639247392483924939250392513925239253392543925539256392573925839259392603926139262392633926439265392663926739268392693927039271392723927339274392753927639277392783927939280392813928239283392843928539286392873928839289392903929139292392933929439295392963929739298392993930039301393023930339304393053930639307393083930939310393113931239313393143931539316393173931839319393203932139322393233932439325393263932739328393293933039331393323933339334393353933639337393383933939340393413934239343393443934539346393473934839349393503935139352393533935439355393563935739358393593936039361393623936339364393653936639367393683936939370393713937239373393743937539376393773937839379393803938139382393833938439385393863938739388393893939039391393923939339394393953939639397393983939939400394013940239403394043940539406394073940839409394103941139412394133941439415394163941739418394193942039421394223942339424394253942639427394283942939430394313943239433394343943539436394373943839439394403944139442394433944439445394463944739448394493945039451394523945339454394553945639457394583945939460394613946239463394643946539466394673946839469394703947139472394733947439475394763947739478394793948039481394823948339484394853948639487394883948939490394913949239493394943949539496394973949839499395003950139502395033950439505395063950739508395093951039511395123951339514395153951639517395183951939520395213952239523395243952539526395273952839529395303953139532395333953439535395363953739538395393954039541395423954339544395453954639547395483954939550395513955239553395543955539556395573955839559395603956139562395633956439565395663956739568395693957039571395723957339574395753957639577395783957939580395813958239583395843958539586395873958839589395903959139592395933959439595395963959739598395993960039601396023960339604396053960639607396083960939610396113961239613396143961539616396173961839619396203962139622396233962439625396263962739628396293963039631396323963339634396353963639637396383963939640396413964239643396443964539646396473964839649396503965139652396533965439655396563965739658396593966039661396623966339664396653966639667396683966939670396713967239673396743967539676396773967839679396803968139682396833968439685396863968739688396893969039691396923969339694396953969639697396983969939700397013970239703397043970539706397073970839709397103971139712397133971439715397163971739718397193972039721397223972339724397253972639727397283972939730397313973239733397343973539736397373973839739397403974139742397433974439745397463974739748397493975039751397523975339754397553975639757397583975939760397613976239763397643976539766397673976839769397703977139772397733977439775397763977739778397793978039781397823978339784397853978639787397883978939790397913979239793397943979539796397973979839799398003980139802398033980439805398063980739808398093981039811398123981339814398153981639817398183981939820398213982239823398243982539826398273982839829398303983139832398333983439835398363983739838398393984039841398423984339844398453984639847398483984939850398513985239853398543985539856398573985839859398603986139862398633986439865398663986739868398693987039871398723987339874398753987639877398783987939880398813988239883398843988539886398873988839889398903989139892398933989439895398963989739898398993990039901399023990339904399053990639907399083990939910399113991239913399143991539916399173991839919399203992139922399233992439925399263992739928399293993039931399323993339934399353993639937399383993939940399413994239943399443994539946399473994839949399503995139952399533995439955399563995739958399593996039961399623996339964399653996639967399683996939970399713997239973399743997539976399773997839979399803998139982399833998439985399863998739988399893999039991399923999339994399953999639997399983999940000400014000240003400044000540006400074000840009400104001140012400134001440015400164001740018400194002040021400224002340024400254002640027400284002940030400314003240033400344003540036400374003840039400404004140042400434004440045400464004740048400494005040051400524005340054400554005640057400584005940060400614006240063400644006540066400674006840069400704007140072400734007440075400764007740078400794008040081400824008340084400854008640087400884008940090400914009240093400944009540096400974009840099401004010140102401034010440105401064010740108401094011040111401124011340114401154011640117401184011940120401214012240123401244012540126401274012840129401304013140132401334013440135401364013740138401394014040141401424014340144401454014640147401484014940150401514015240153401544015540156401574015840159401604016140162401634016440165401664016740168401694017040171401724017340174401754017640177401784017940180401814018240183401844018540186401874018840189401904019140192401934019440195401964019740198401994020040201402024020340204402054020640207402084020940210402114021240213402144021540216402174021840219402204022140222402234022440225402264022740228402294023040231402324023340234402354023640237402384023940240402414024240243402444024540246402474024840249402504025140252402534025440255402564025740258402594026040261402624026340264402654026640267402684026940270402714027240273402744027540276402774027840279402804028140282402834028440285402864028740288402894029040291402924029340294402954029640297402984029940300403014030240303403044030540306403074030840309403104031140312403134031440315403164031740318403194032040321403224032340324403254032640327403284032940330403314033240333403344033540336403374033840339403404034140342403434034440345403464034740348403494035040351403524035340354403554035640357403584035940360403614036240363403644036540366403674036840369403704037140372403734037440375403764037740378403794038040381403824038340384403854038640387403884038940390403914039240393403944039540396403974039840399404004040140402404034040440405404064040740408404094041040411404124041340414404154041640417404184041940420404214042240423404244042540426404274042840429404304043140432404334043440435404364043740438404394044040441404424044340444404454044640447404484044940450404514045240453404544045540456404574045840459404604046140462404634046440465404664046740468404694047040471404724047340474404754047640477404784047940480404814048240483404844048540486404874048840489404904049140492404934049440495404964049740498404994050040501405024050340504405054050640507405084050940510405114051240513405144051540516405174051840519405204052140522405234052440525405264052740528405294053040531405324053340534405354053640537405384053940540405414054240543405444054540546405474054840549405504055140552405534055440555405564055740558405594056040561405624056340564405654056640567405684056940570405714057240573405744057540576405774057840579405804058140582405834058440585405864058740588405894059040591405924059340594405954059640597405984059940600406014060240603406044060540606406074060840609406104061140612406134061440615406164061740618406194062040621406224062340624406254062640627406284062940630406314063240633406344063540636406374063840639406404064140642406434064440645406464064740648406494065040651406524065340654406554065640657406584065940660406614066240663406644066540666406674066840669406704067140672406734067440675406764067740678406794068040681406824068340684406854068640687406884068940690406914069240693406944069540696406974069840699407004070140702407034070440705407064070740708407094071040711407124071340714407154071640717407184071940720407214072240723407244072540726407274072840729407304073140732407334073440735407364073740738407394074040741407424074340744407454074640747407484074940750407514075240753407544075540756407574075840759407604076140762407634076440765407664076740768407694077040771407724077340774407754077640777407784077940780407814078240783407844078540786407874078840789407904079140792407934079440795407964079740798407994080040801408024080340804408054080640807408084080940810408114081240813408144081540816408174081840819408204082140822408234082440825408264082740828408294083040831408324083340834408354083640837408384083940840408414084240843408444084540846408474084840849408504085140852408534085440855408564085740858408594086040861408624086340864408654086640867408684086940870408714087240873408744087540876408774087840879408804088140882408834088440885408864088740888408894089040891408924089340894408954089640897408984089940900409014090240903409044090540906409074090840909409104091140912409134091440915409164091740918409194092040921409224092340924409254092640927409284092940930409314093240933409344093540936409374093840939409404094140942409434094440945409464094740948409494095040951409524095340954409554095640957409584095940960409614096240963409644096540966409674096840969409704097140972409734097440975409764097740978409794098040981409824098340984409854098640987409884098940990409914099240993409944099540996409974099840999410004100141002410034100441005410064100741008410094101041011410124101341014410154101641017410184101941020410214102241023410244102541026410274102841029410304103141032410334103441035410364103741038410394104041041410424104341044410454104641047410484104941050410514105241053410544105541056410574105841059410604106141062410634106441065410664106741068410694107041071410724107341074410754107641077410784107941080410814108241083410844108541086410874108841089410904109141092410934109441095410964109741098410994110041101411024110341104411054110641107411084110941110411114111241113411144111541116411174111841119411204112141122411234112441125411264112741128411294113041131411324113341134411354113641137411384113941140411414114241143411444114541146411474114841149411504115141152411534115441155411564115741158411594116041161411624116341164411654116641167411684116941170411714117241173411744117541176411774117841179411804118141182411834118441185411864118741188411894119041191411924119341194411954119641197411984119941200412014120241203412044120541206412074120841209412104121141212412134121441215412164121741218412194122041221412224122341224412254122641227412284122941230412314123241233412344123541236412374123841239412404124141242412434124441245412464124741248412494125041251412524125341254412554125641257412584125941260412614126241263412644126541266412674126841269412704127141272412734127441275412764127741278412794128041281412824128341284412854128641287412884128941290412914129241293412944129541296412974129841299413004130141302413034130441305413064130741308413094131041311413124131341314413154131641317413184131941320413214132241323413244132541326413274132841329413304133141332413334133441335413364133741338413394134041341413424134341344413454134641347413484134941350413514135241353413544135541356413574135841359413604136141362413634136441365413664136741368413694137041371413724137341374413754137641377413784137941380413814138241383413844138541386413874138841389413904139141392413934139441395413964139741398413994140041401414024140341404414054140641407414084140941410414114141241413414144141541416414174141841419414204142141422414234142441425414264142741428414294143041431414324143341434414354143641437414384143941440414414144241443414444144541446414474144841449414504145141452414534145441455414564145741458414594146041461414624146341464414654146641467414684146941470414714147241473414744147541476414774147841479414804148141482414834148441485414864148741488414894149041491414924149341494414954149641497414984149941500415014150241503415044150541506415074150841509415104151141512415134151441515415164151741518415194152041521415224152341524415254152641527415284152941530415314153241533415344153541536415374153841539415404154141542415434154441545415464154741548415494155041551415524155341554415554155641557415584155941560415614156241563415644156541566415674156841569415704157141572415734157441575415764157741578415794158041581415824158341584415854158641587415884158941590415914159241593415944159541596415974159841599416004160141602416034160441605416064160741608416094161041611416124161341614416154161641617416184161941620416214162241623416244162541626416274162841629416304163141632416334163441635416364163741638416394164041641416424164341644416454164641647416484164941650416514165241653416544165541656416574165841659416604166141662416634166441665416664166741668416694167041671416724167341674416754167641677416784167941680416814168241683416844168541686416874168841689416904169141692416934169441695416964169741698416994170041701417024170341704417054170641707417084170941710417114171241713417144171541716417174171841719417204172141722417234172441725417264172741728417294173041731417324173341734417354173641737417384173941740417414174241743417444174541746417474174841749417504175141752417534175441755417564175741758417594176041761417624176341764417654176641767417684176941770417714177241773417744177541776417774177841779417804178141782417834178441785417864178741788417894179041791417924179341794417954179641797417984179941800418014180241803418044180541806418074180841809418104181141812418134181441815418164181741818418194182041821418224182341824418254182641827418284182941830418314183241833418344183541836418374183841839418404184141842418434184441845418464184741848418494185041851418524185341854418554185641857418584185941860418614186241863418644186541866418674186841869418704187141872418734187441875418764187741878418794188041881418824188341884418854188641887418884188941890418914189241893418944189541896418974189841899419004190141902419034190441905419064190741908419094191041911419124191341914419154191641917419184191941920419214192241923419244192541926419274192841929419304193141932419334193441935419364193741938419394194041941419424194341944419454194641947419484194941950419514195241953419544195541956419574195841959419604196141962419634196441965419664196741968419694197041971419724197341974419754197641977419784197941980419814198241983419844198541986419874198841989419904199141992419934199441995419964199741998419994200042001420024200342004420054200642007420084200942010420114201242013420144201542016420174201842019420204202142022420234202442025420264202742028420294203042031420324203342034420354203642037420384203942040420414204242043420444204542046420474204842049420504205142052420534205442055420564205742058420594206042061420624206342064420654206642067420684206942070420714207242073420744207542076420774207842079420804208142082420834208442085420864208742088420894209042091420924209342094420954209642097420984209942100421014210242103421044210542106421074210842109421104211142112421134211442115421164211742118421194212042121421224212342124421254212642127421284212942130421314213242133421344213542136421374213842139421404214142142421434214442145421464214742148421494215042151421524215342154421554215642157421584215942160421614216242163421644216542166421674216842169421704217142172421734217442175421764217742178421794218042181421824218342184421854218642187421884218942190421914219242193421944219542196421974219842199422004220142202422034220442205422064220742208422094221042211422124221342214422154221642217422184221942220422214222242223422244222542226422274222842229422304223142232422334223442235422364223742238422394224042241422424224342244422454224642247422484224942250422514225242253422544225542256422574225842259422604226142262422634226442265422664226742268422694227042271422724227342274422754227642277422784227942280422814228242283422844228542286422874228842289422904229142292422934229442295422964229742298422994230042301423024230342304423054230642307423084230942310423114231242313423144231542316423174231842319423204232142322423234232442325423264232742328423294233042331423324233342334423354233642337423384233942340423414234242343423444234542346423474234842349423504235142352423534235442355423564235742358423594236042361423624236342364423654236642367423684236942370423714237242373423744237542376423774237842379423804238142382423834238442385423864238742388423894239042391423924239342394423954239642397423984239942400424014240242403424044240542406424074240842409424104241142412424134241442415424164241742418424194242042421424224242342424424254242642427424284242942430424314243242433424344243542436424374243842439424404244142442424434244442445424464244742448424494245042451424524245342454424554245642457424584245942460424614246242463424644246542466424674246842469424704247142472424734247442475424764247742478424794248042481424824248342484424854248642487424884248942490424914249242493424944249542496424974249842499425004250142502425034250442505425064250742508425094251042511425124251342514425154251642517425184251942520425214252242523425244252542526425274252842529425304253142532425334253442535425364253742538425394254042541425424254342544425454254642547425484254942550425514255242553425544255542556425574255842559425604256142562425634256442565425664256742568425694257042571425724257342574425754257642577425784257942580425814258242583425844258542586425874258842589425904259142592425934259442595425964259742598425994260042601426024260342604426054260642607426084260942610426114261242613426144261542616426174261842619426204262142622426234262442625426264262742628426294263042631426324263342634426354263642637426384263942640426414264242643426444264542646426474264842649426504265142652426534265442655426564265742658426594266042661426624266342664426654266642667426684266942670426714267242673426744267542676426774267842679426804268142682426834268442685426864268742688426894269042691426924269342694426954269642697426984269942700427014270242703427044270542706427074270842709427104271142712427134271442715427164271742718427194272042721427224272342724427254272642727427284272942730427314273242733427344273542736427374273842739427404274142742427434274442745427464274742748427494275042751427524275342754427554275642757427584275942760427614276242763427644276542766427674276842769427704277142772427734277442775427764277742778427794278042781427824278342784427854278642787427884278942790427914279242793427944279542796427974279842799428004280142802428034280442805428064280742808428094281042811428124281342814428154281642817428184281942820428214282242823428244282542826428274282842829428304283142832428334283442835428364283742838428394284042841428424284342844428454284642847428484284942850428514285242853428544285542856428574285842859428604286142862428634286442865428664286742868428694287042871428724287342874428754287642877428784287942880428814288242883428844288542886428874288842889428904289142892428934289442895428964289742898428994290042901429024290342904429054290642907429084290942910429114291242913429144291542916429174291842919429204292142922429234292442925429264292742928429294293042931429324293342934429354293642937429384293942940429414294242943429444294542946429474294842949429504295142952429534295442955429564295742958429594296042961429624296342964429654296642967429684296942970429714297242973429744297542976429774297842979429804298142982429834298442985429864298742988429894299042991429924299342994429954299642997429984299943000430014300243003430044300543006430074300843009430104301143012430134301443015430164301743018430194302043021430224302343024430254302643027430284302943030430314303243033430344303543036430374303843039430404304143042430434304443045430464304743048430494305043051430524305343054430554305643057430584305943060430614306243063430644306543066430674306843069430704307143072430734307443075430764307743078430794308043081430824308343084430854308643087430884308943090430914309243093430944309543096430974309843099431004310143102431034310443105431064310743108431094311043111431124311343114431154311643117431184311943120431214312243123431244312543126431274312843129431304313143132431334313443135431364313743138431394314043141431424314343144431454314643147431484314943150431514315243153431544315543156431574315843159431604316143162431634316443165431664316743168431694317043171431724317343174431754317643177431784317943180431814318243183431844318543186431874318843189431904319143192431934319443195431964319743198431994320043201432024320343204432054320643207432084320943210432114321243213432144321543216432174321843219432204322143222432234322443225432264322743228432294323043231432324323343234432354323643237432384323943240432414324243243432444324543246432474324843249432504325143252432534325443255432564325743258432594326043261432624326343264432654326643267432684326943270432714327243273432744327543276432774327843279432804328143282432834328443285432864328743288432894329043291432924329343294432954329643297432984329943300433014330243303433044330543306433074330843309433104331143312433134331443315433164331743318433194332043321433224332343324433254332643327433284332943330433314333243333433344333543336433374333843339433404334143342433434334443345433464334743348433494335043351433524335343354433554335643357433584335943360433614336243363433644336543366433674336843369433704337143372433734337443375433764337743378433794338043381433824338343384433854338643387433884338943390433914339243393433944339543396433974339843399434004340143402434034340443405434064340743408434094341043411434124341343414434154341643417434184341943420434214342243423434244342543426434274342843429434304343143432434334343443435434364343743438434394344043441434424344343444434454344643447434484344943450434514345243453434544345543456434574345843459434604346143462434634346443465434664346743468434694347043471434724347343474434754347643477434784347943480434814348243483434844348543486434874348843489434904349143492434934349443495434964349743498434994350043501435024350343504435054350643507435084350943510435114351243513435144351543516435174351843519435204352143522435234352443525435264352743528435294353043531435324353343534435354353643537435384353943540435414354243543435444354543546435474354843549435504355143552435534355443555435564355743558435594356043561435624356343564435654356643567435684356943570435714357243573435744357543576435774357843579435804358143582435834358443585435864358743588435894359043591435924359343594435954359643597435984359943600436014360243603436044360543606436074360843609436104361143612436134361443615436164361743618436194362043621436224362343624436254362643627436284362943630436314363243633436344363543636436374363843639436404364143642436434364443645436464364743648436494365043651436524365343654436554365643657436584365943660436614366243663436644366543666436674366843669436704367143672436734367443675436764367743678436794368043681436824368343684436854368643687436884368943690436914369243693436944369543696436974369843699437004370143702437034370443705437064370743708437094371043711437124371343714437154371643717437184371943720437214372243723437244372543726437274372843729437304373143732437334373443735437364373743738437394374043741437424374343744437454374643747437484374943750437514375243753437544375543756437574375843759437604376143762437634376443765437664376743768437694377043771437724377343774437754377643777437784377943780437814378243783437844378543786437874378843789437904379143792437934379443795437964379743798437994380043801438024380343804438054380643807438084380943810438114381243813438144381543816438174381843819438204382143822438234382443825438264382743828438294383043831438324383343834438354383643837438384383943840438414384243843438444384543846438474384843849438504385143852438534385443855438564385743858438594386043861438624386343864438654386643867438684386943870438714387243873438744387543876438774387843879438804388143882438834388443885438864388743888438894389043891438924389343894438954389643897438984389943900439014390243903439044390543906439074390843909439104391143912439134391443915439164391743918439194392043921439224392343924439254392643927439284392943930439314393243933439344393543936439374393843939439404394143942439434394443945439464394743948439494395043951439524395343954439554395643957439584395943960439614396243963439644396543966439674396843969439704397143972439734397443975439764397743978439794398043981439824398343984439854398643987439884398943990439914399243993439944399543996439974399843999440004400144002440034400444005440064400744008440094401044011440124401344014440154401644017440184401944020440214402244023440244402544026440274402844029440304403144032440334403444035440364403744038440394404044041440424404344044440454404644047440484404944050440514405244053440544405544056440574405844059440604406144062440634406444065440664406744068440694407044071440724407344074440754407644077440784407944080440814408244083440844408544086440874408844089440904409144092440934409444095440964409744098440994410044101441024410344104441054410644107441084410944110441114411244113441144411544116441174411844119441204412144122441234412444125441264412744128441294413044131441324413344134441354413644137441384413944140441414414244143441444414544146441474414844149441504415144152441534415444155441564415744158441594416044161441624416344164441654416644167441684416944170441714417244173441744417544176441774417844179441804418144182441834418444185441864418744188441894419044191441924419344194441954419644197441984419944200442014420244203442044420544206442074420844209442104421144212442134421444215442164421744218442194422044221442224422344224442254422644227442284422944230442314423244233442344423544236442374423844239442404424144242442434424444245442464424744248442494425044251442524425344254442554425644257442584425944260442614426244263442644426544266442674426844269442704427144272442734427444275442764427744278442794428044281442824428344284442854428644287442884428944290442914429244293442944429544296442974429844299443004430144302443034430444305443064430744308443094431044311443124431344314443154431644317443184431944320443214432244323443244432544326443274432844329443304433144332443334433444335443364433744338443394434044341443424434344344443454434644347443484434944350443514435244353443544435544356443574435844359443604436144362443634436444365443664436744368443694437044371443724437344374443754437644377443784437944380443814438244383443844438544386443874438844389443904439144392443934439444395443964439744398443994440044401444024440344404444054440644407444084440944410444114441244413444144441544416444174441844419444204442144422444234442444425444264442744428444294443044431444324443344434444354443644437444384443944440444414444244443444444444544446444474444844449444504445144452444534445444455444564445744458444594446044461444624446344464444654446644467444684446944470444714447244473444744447544476444774447844479444804448144482444834448444485444864448744488444894449044491444924449344494444954449644497444984449944500445014450244503445044450544506445074450844509445104451144512445134451444515445164451744518445194452044521445224452344524445254452644527445284452944530445314453244533445344453544536445374453844539445404454144542445434454444545445464454744548445494455044551445524455344554445554455644557445584455944560445614456244563445644456544566445674456844569445704457144572445734457444575445764457744578445794458044581445824458344584445854458644587445884458944590445914459244593445944459544596445974459844599446004460144602446034460444605446064460744608446094461044611446124461344614446154461644617446184461944620446214462244623446244462544626446274462844629446304463144632446334463444635446364463744638446394464044641446424464344644446454464644647446484464944650446514465244653446544465544656446574465844659446604466144662446634466444665446664466744668446694467044671446724467344674446754467644677446784467944680446814468244683446844468544686446874468844689446904469144692446934469444695446964469744698446994470044701447024470344704447054470644707447084470944710447114471244713447144471544716447174471844719447204472144722447234472444725447264472744728447294473044731447324473344734447354473644737447384473944740447414474244743447444474544746447474474844749447504475144752447534475444755447564475744758447594476044761447624476344764447654476644767447684476944770447714477244773447744477544776447774477844779447804478144782447834478444785447864478744788447894479044791447924479344794447954479644797447984479944800448014480244803448044480544806448074480844809448104481144812448134481444815448164481744818448194482044821448224482344824448254482644827448284482944830448314483244833448344483544836448374483844839448404484144842448434484444845448464484744848448494485044851448524485344854448554485644857448584485944860448614486244863448644486544866448674486844869448704487144872448734487444875448764487744878448794488044881448824488344884448854488644887448884488944890448914489244893448944489544896448974489844899449004490144902449034490444905449064490744908449094491044911449124491344914449154491644917449184491944920449214492244923449244492544926449274492844929449304493144932449334493444935449364493744938449394494044941449424494344944449454494644947449484494944950449514495244953449544495544956449574495844959449604496144962449634496444965449664496744968449694497044971449724497344974449754497644977449784497944980449814498244983449844498544986449874498844989449904499144992449934499444995449964499744998449994500045001450024500345004450054500645007450084500945010450114501245013450144501545016450174501845019450204502145022450234502445025450264502745028450294503045031450324503345034450354503645037450384503945040450414504245043450444504545046450474504845049450504505145052450534505445055450564505745058450594506045061450624506345064450654506645067450684506945070450714507245073450744507545076450774507845079450804508145082450834508445085450864508745088450894509045091450924509345094450954509645097450984509945100451014510245103451044510545106451074510845109451104511145112451134511445115451164511745118451194512045121451224512345124451254512645127451284512945130451314513245133451344513545136451374513845139451404514145142451434514445145451464514745148451494515045151451524515345154451554515645157451584515945160451614516245163451644516545166451674516845169451704517145172451734517445175451764517745178451794518045181451824518345184451854518645187451884518945190451914519245193451944519545196451974519845199452004520145202452034520445205452064520745208452094521045211452124521345214452154521645217452184521945220452214522245223452244522545226452274522845229452304523145232452334523445235452364523745238452394524045241452424524345244452454524645247452484524945250452514525245253452544525545256452574525845259452604526145262452634526445265452664526745268452694527045271452724527345274452754527645277452784527945280452814528245283452844528545286452874528845289452904529145292452934529445295452964529745298452994530045301453024530345304453054530645307453084530945310453114531245313453144531545316453174531845319453204532145322453234532445325453264532745328453294533045331453324533345334453354533645337453384533945340453414534245343453444534545346453474534845349453504535145352453534535445355453564535745358453594536045361453624536345364453654536645367453684536945370453714537245373453744537545376453774537845379453804538145382453834538445385453864538745388453894539045391453924539345394453954539645397453984539945400454014540245403454044540545406454074540845409454104541145412454134541445415454164541745418454194542045421454224542345424454254542645427454284542945430454314543245433454344543545436454374543845439454404544145442454434544445445454464544745448454494545045451454524545345454454554545645457454584545945460454614546245463454644546545466454674546845469454704547145472454734547445475454764547745478454794548045481454824548345484454854548645487454884548945490454914549245493454944549545496454974549845499455004550145502455034550445505455064550745508455094551045511455124551345514455154551645517455184551945520455214552245523455244552545526455274552845529455304553145532455334553445535455364553745538455394554045541455424554345544455454554645547455484554945550455514555245553455544555545556455574555845559455604556145562455634556445565455664556745568455694557045571455724557345574455754557645577455784557945580455814558245583455844558545586455874558845589455904559145592455934559445595455964559745598455994560045601456024560345604456054560645607456084560945610456114561245613456144561545616456174561845619456204562145622456234562445625456264562745628456294563045631456324563345634456354563645637456384563945640456414564245643456444564545646456474564845649456504565145652456534565445655456564565745658456594566045661456624566345664456654566645667456684566945670456714567245673456744567545676456774567845679456804568145682456834568445685456864568745688456894569045691456924569345694456954569645697456984569945700457014570245703457044570545706457074570845709457104571145712457134571445715457164571745718457194572045721457224572345724457254572645727457284572945730457314573245733457344573545736457374573845739457404574145742457434574445745457464574745748457494575045751457524575345754457554575645757457584575945760457614576245763457644576545766457674576845769457704577145772457734577445775457764577745778457794578045781457824578345784457854578645787457884578945790457914579245793457944579545796457974579845799458004580145802458034580445805458064580745808458094581045811458124581345814458154581645817458184581945820458214582245823458244582545826458274582845829458304583145832458334583445835458364583745838458394584045841458424584345844458454584645847458484584945850458514585245853458544585545856458574585845859458604586145862458634586445865458664586745868458694587045871458724587345874458754587645877458784587945880458814588245883458844588545886458874588845889458904589145892458934589445895458964589745898458994590045901459024590345904459054590645907459084590945910459114591245913459144591545916459174591845919459204592145922459234592445925459264592745928459294593045931459324593345934459354593645937459384593945940459414594245943459444594545946459474594845949459504595145952459534595445955459564595745958459594596045961459624596345964459654596645967459684596945970459714597245973459744597545976459774597845979459804598145982459834598445985459864598745988459894599045991459924599345994459954599645997459984599946000460014600246003460044600546006460074600846009460104601146012460134601446015460164601746018460194602046021460224602346024460254602646027460284602946030460314603246033460344603546036460374603846039460404604146042460434604446045460464604746048460494605046051460524605346054460554605646057460584605946060460614606246063460644606546066460674606846069460704607146072460734607446075460764607746078460794608046081460824608346084460854608646087460884608946090460914609246093460944609546096460974609846099461004610146102461034610446105461064610746108461094611046111461124611346114461154611646117461184611946120461214612246123461244612546126461274612846129461304613146132461334613446135461364613746138461394614046141461424614346144461454614646147461484614946150461514615246153461544615546156461574615846159461604616146162461634616446165461664616746168461694617046171461724617346174461754617646177461784617946180461814618246183461844618546186461874618846189461904619146192461934619446195461964619746198461994620046201462024620346204462054620646207462084620946210462114621246213462144621546216462174621846219462204622146222462234622446225462264622746228462294623046231462324623346234462354623646237462384623946240462414624246243462444624546246462474624846249462504625146252462534625446255462564625746258462594626046261462624626346264462654626646267462684626946270462714627246273462744627546276462774627846279462804628146282462834628446285462864628746288462894629046291462924629346294462954629646297462984629946300463014630246303463044630546306463074630846309463104631146312463134631446315463164631746318463194632046321463224632346324463254632646327463284632946330463314633246333463344633546336463374633846339463404634146342463434634446345463464634746348463494635046351463524635346354463554635646357463584635946360463614636246363463644636546366463674636846369463704637146372463734637446375463764637746378463794638046381463824638346384463854638646387463884638946390463914639246393463944639546396463974639846399464004640146402464034640446405464064640746408464094641046411464124641346414464154641646417464184641946420464214642246423464244642546426464274642846429464304643146432464334643446435464364643746438464394644046441464424644346444464454644646447464484644946450464514645246453464544645546456464574645846459464604646146462464634646446465464664646746468464694647046471464724647346474464754647646477464784647946480464814648246483464844648546486464874648846489464904649146492464934649446495464964649746498464994650046501465024650346504465054650646507465084650946510465114651246513465144651546516465174651846519465204652146522465234652446525465264652746528465294653046531465324653346534465354653646537465384653946540465414654246543465444654546546465474654846549465504655146552465534655446555465564655746558465594656046561465624656346564465654656646567465684656946570465714657246573465744657546576465774657846579465804658146582465834658446585465864658746588465894659046591465924659346594465954659646597465984659946600466014660246603466044660546606466074660846609466104661146612466134661446615466164661746618466194662046621466224662346624466254662646627466284662946630466314663246633466344663546636466374663846639466404664146642466434664446645466464664746648466494665046651466524665346654466554665646657466584665946660466614666246663466644666546666466674666846669466704667146672466734667446675466764667746678466794668046681466824668346684466854668646687466884668946690466914669246693466944669546696466974669846699467004670146702467034670446705467064670746708467094671046711467124671346714467154671646717467184671946720467214672246723467244672546726467274672846729467304673146732467334673446735467364673746738467394674046741467424674346744467454674646747467484674946750467514675246753467544675546756467574675846759467604676146762467634676446765467664676746768467694677046771467724677346774467754677646777467784677946780467814678246783467844678546786467874678846789467904679146792467934679446795467964679746798467994680046801468024680346804468054680646807468084680946810468114681246813468144681546816468174681846819468204682146822468234682446825468264682746828468294683046831468324683346834468354683646837468384683946840468414684246843468444684546846468474684846849468504685146852468534685446855468564685746858468594686046861468624686346864468654686646867468684686946870468714687246873468744687546876468774687846879468804688146882468834688446885468864688746888468894689046891468924689346894468954689646897468984689946900469014690246903469044690546906469074690846909469104691146912469134691446915469164691746918469194692046921469224692346924469254692646927469284692946930469314693246933469344693546936469374693846939469404694146942469434694446945469464694746948469494695046951469524695346954469554695646957469584695946960469614696246963469644696546966469674696846969469704697146972469734697446975469764697746978469794698046981469824698346984469854698646987469884698946990469914699246993469944699546996469974699846999470004700147002470034700447005470064700747008470094701047011470124701347014470154701647017470184701947020470214702247023470244702547026470274702847029470304703147032470334703447035470364703747038470394704047041470424704347044470454704647047470484704947050470514705247053470544705547056470574705847059470604706147062470634706447065470664706747068470694707047071470724707347074470754707647077470784707947080470814708247083470844708547086470874708847089470904709147092470934709447095470964709747098470994710047101471024710347104471054710647107471084710947110471114711247113471144711547116471174711847119471204712147122471234712447125471264712747128471294713047131471324713347134471354713647137471384713947140471414714247143471444714547146471474714847149471504715147152471534715447155471564715747158471594716047161471624716347164471654716647167471684716947170471714717247173471744717547176471774717847179471804718147182471834718447185471864718747188471894719047191471924719347194471954719647197471984719947200472014720247203472044720547206472074720847209472104721147212472134721447215472164721747218472194722047221472224722347224472254722647227472284722947230472314723247233472344723547236472374723847239472404724147242472434724447245472464724747248472494725047251472524725347254472554725647257472584725947260472614726247263472644726547266472674726847269472704727147272472734727447275472764727747278472794728047281472824728347284472854728647287472884728947290472914729247293472944729547296472974729847299473004730147302473034730447305473064730747308473094731047311473124731347314473154731647317473184731947320473214732247323473244732547326473274732847329473304733147332473334733447335473364733747338473394734047341473424734347344473454734647347473484734947350473514735247353473544735547356473574735847359473604736147362473634736447365473664736747368473694737047371473724737347374473754737647377473784737947380473814738247383473844738547386473874738847389473904739147392473934739447395473964739747398473994740047401474024740347404474054740647407474084740947410474114741247413474144741547416474174741847419474204742147422474234742447425474264742747428474294743047431474324743347434474354743647437474384743947440474414744247443474444744547446474474744847449474504745147452474534745447455474564745747458474594746047461474624746347464474654746647467474684746947470474714747247473474744747547476474774747847479474804748147482474834748447485474864748747488474894749047491474924749347494474954749647497474984749947500475014750247503475044750547506475074750847509475104751147512475134751447515475164751747518475194752047521475224752347524475254752647527475284752947530475314753247533475344753547536475374753847539475404754147542475434754447545475464754747548475494755047551475524755347554475554755647557475584755947560475614756247563475644756547566475674756847569475704757147572475734757447575475764757747578475794758047581475824758347584475854758647587475884758947590475914759247593475944759547596475974759847599476004760147602476034760447605476064760747608476094761047611476124761347614476154761647617476184761947620476214762247623476244762547626476274762847629476304763147632476334763447635476364763747638476394764047641476424764347644476454764647647476484764947650476514765247653476544765547656476574765847659476604766147662476634766447665476664766747668476694767047671476724767347674476754767647677476784767947680476814768247683476844768547686476874768847689476904769147692476934769447695476964769747698476994770047701477024770347704477054770647707477084770947710477114771247713477144771547716477174771847719477204772147722477234772447725477264772747728477294773047731477324773347734477354773647737477384773947740477414774247743477444774547746477474774847749477504775147752477534775447755477564775747758477594776047761477624776347764477654776647767477684776947770477714777247773477744777547776477774777847779477804778147782477834778447785477864778747788477894779047791477924779347794477954779647797477984779947800478014780247803478044780547806478074780847809478104781147812478134781447815478164781747818478194782047821478224782347824478254782647827478284782947830478314783247833478344783547836478374783847839478404784147842478434784447845478464784747848478494785047851478524785347854478554785647857478584785947860478614786247863478644786547866478674786847869478704787147872478734787447875478764787747878478794788047881478824788347884478854788647887478884788947890478914789247893478944789547896478974789847899479004790147902479034790447905479064790747908479094791047911479124791347914479154791647917479184791947920479214792247923479244792547926479274792847929479304793147932479334793447935479364793747938479394794047941479424794347944479454794647947479484794947950479514795247953479544795547956479574795847959479604796147962479634796447965479664796747968479694797047971479724797347974479754797647977479784797947980479814798247983479844798547986479874798847989479904799147992479934799447995479964799747998479994800048001480024800348004480054800648007480084800948010480114801248013480144801548016480174801848019480204802148022480234802448025480264802748028480294803048031480324803348034480354803648037480384803948040480414804248043480444804548046480474804848049480504805148052480534805448055480564805748058480594806048061480624806348064480654806648067480684806948070480714807248073480744807548076480774807848079480804808148082480834808448085480864808748088480894809048091480924809348094480954809648097480984809948100481014810248103481044810548106481074810848109481104811148112481134811448115481164811748118481194812048121481224812348124481254812648127481284812948130481314813248133481344813548136481374813848139481404814148142481434814448145481464814748148481494815048151481524815348154481554815648157481584815948160481614816248163481644816548166481674816848169481704817148172481734817448175481764817748178481794818048181481824818348184481854818648187481884818948190481914819248193481944819548196481974819848199482004820148202482034820448205482064820748208482094821048211482124821348214482154821648217482184821948220482214822248223482244822548226482274822848229482304823148232482334823448235482364823748238482394824048241482424824348244482454824648247482484824948250482514825248253482544825548256482574825848259482604826148262482634826448265482664826748268482694827048271482724827348274482754827648277482784827948280482814828248283482844828548286482874828848289482904829148292482934829448295482964829748298482994830048301483024830348304483054830648307483084830948310483114831248313483144831548316483174831848319483204832148322483234832448325483264832748328483294833048331483324833348334483354833648337483384833948340483414834248343483444834548346483474834848349483504835148352483534835448355483564835748358483594836048361483624836348364483654836648367483684836948370483714837248373483744837548376483774837848379483804838148382483834838448385483864838748388483894839048391483924839348394483954839648397483984839948400484014840248403484044840548406484074840848409484104841148412484134841448415484164841748418484194842048421484224842348424484254842648427484284842948430484314843248433484344843548436484374843848439484404844148442484434844448445484464844748448484494845048451484524845348454484554845648457484584845948460484614846248463484644846548466484674846848469484704847148472484734847448475484764847748478484794848048481484824848348484484854848648487484884848948490484914849248493484944849548496484974849848499485004850148502485034850448505485064850748508485094851048511485124851348514485154851648517485184851948520485214852248523485244852548526485274852848529485304853148532485334853448535485364853748538485394854048541485424854348544485454854648547485484854948550485514855248553485544855548556485574855848559485604856148562485634856448565485664856748568485694857048571485724857348574485754857648577485784857948580485814858248583485844858548586485874858848589485904859148592485934859448595485964859748598485994860048601486024860348604486054860648607486084860948610486114861248613486144861548616486174861848619486204862148622486234862448625486264862748628486294863048631486324863348634486354863648637486384863948640486414864248643486444864548646486474864848649486504865148652486534865448655486564865748658486594866048661486624866348664486654866648667486684866948670486714867248673486744867548676486774867848679486804868148682486834868448685486864868748688486894869048691486924869348694486954869648697486984869948700487014870248703487044870548706487074870848709487104871148712487134871448715487164871748718487194872048721487224872348724487254872648727487284872948730487314873248733487344873548736487374873848739487404874148742487434874448745487464874748748487494875048751487524875348754487554875648757487584875948760487614876248763487644876548766487674876848769487704877148772487734877448775487764877748778487794878048781487824878348784487854878648787487884878948790487914879248793487944879548796487974879848799488004880148802488034880448805488064880748808488094881048811488124881348814488154881648817488184881948820488214882248823488244882548826488274882848829488304883148832488334883448835488364883748838488394884048841488424884348844488454884648847488484884948850488514885248853488544885548856488574885848859488604886148862488634886448865488664886748868488694887048871488724887348874488754887648877488784887948880488814888248883488844888548886488874888848889488904889148892488934889448895488964889748898488994890048901489024890348904489054890648907489084890948910489114891248913489144891548916489174891848919489204892148922489234892448925489264892748928489294893048931489324893348934489354893648937489384893948940489414894248943489444894548946489474894848949489504895148952489534895448955489564895748958489594896048961489624896348964489654896648967489684896948970489714897248973489744897548976489774897848979489804898148982489834898448985489864898748988489894899048991489924899348994489954899648997489984899949000490014900249003490044900549006490074900849009490104901149012490134901449015490164901749018490194902049021490224902349024490254902649027490284902949030490314903249033490344903549036490374903849039490404904149042490434904449045490464904749048490494905049051490524905349054490554905649057490584905949060490614906249063490644906549066490674906849069490704907149072490734907449075490764907749078490794908049081490824908349084490854908649087490884908949090490914909249093490944909549096490974909849099491004910149102491034910449105491064910749108491094911049111491124911349114491154911649117491184911949120491214912249123491244912549126491274912849129491304913149132491334913449135491364913749138491394914049141491424914349144491454914649147491484914949150491514915249153491544915549156491574915849159491604916149162491634916449165491664916749168491694917049171491724917349174491754917649177491784917949180491814918249183491844918549186491874918849189491904919149192491934919449195491964919749198491994920049201492024920349204492054920649207492084920949210492114921249213492144921549216492174921849219492204922149222492234922449225492264922749228492294923049231492324923349234492354923649237492384923949240492414924249243492444924549246492474924849249492504925149252492534925449255492564925749258492594926049261492624926349264492654926649267492684926949270492714927249273492744927549276492774927849279492804928149282492834928449285492864928749288492894929049291492924929349294492954929649297492984929949300493014930249303493044930549306493074930849309493104931149312493134931449315493164931749318493194932049321493224932349324493254932649327493284932949330493314933249333493344933549336493374933849339493404934149342493434934449345493464934749348493494935049351493524935349354493554935649357493584935949360493614936249363493644936549366493674936849369493704937149372493734937449375493764937749378493794938049381493824938349384493854938649387493884938949390493914939249393493944939549396493974939849399494004940149402494034940449405494064940749408494094941049411494124941349414494154941649417494184941949420494214942249423494244942549426494274942849429494304943149432494334943449435494364943749438494394944049441494424944349444494454944649447494484944949450494514945249453494544945549456494574945849459494604946149462494634946449465494664946749468494694947049471494724947349474494754947649477494784947949480494814948249483494844948549486494874948849489494904949149492494934949449495494964949749498494994950049501495024950349504495054950649507495084950949510495114951249513495144951549516495174951849519495204952149522495234952449525495264952749528495294953049531495324953349534495354953649537495384953949540495414954249543495444954549546495474954849549495504955149552495534955449555495564955749558495594956049561495624956349564495654956649567495684956949570495714957249573495744957549576495774957849579495804958149582495834958449585495864958749588495894959049591495924959349594495954959649597495984959949600496014960249603496044960549606496074960849609496104961149612496134961449615496164961749618496194962049621496224962349624496254962649627496284962949630496314963249633496344963549636496374963849639496404964149642496434964449645496464964749648496494965049651496524965349654496554965649657496584965949660496614966249663496644966549666496674966849669496704967149672496734967449675496764967749678496794968049681496824968349684496854968649687496884968949690496914969249693496944969549696496974969849699497004970149702497034970449705497064970749708497094971049711497124971349714497154971649717497184971949720497214972249723497244972549726497274972849729497304973149732497334973449735497364973749738497394974049741497424974349744497454974649747497484974949750497514975249753497544975549756497574975849759497604976149762497634976449765497664976749768497694977049771497724977349774497754977649777497784977949780497814978249783497844978549786497874978849789497904979149792497934979449795497964979749798497994980049801498024980349804498054980649807498084980949810498114981249813498144981549816498174981849819498204982149822498234982449825498264982749828498294983049831498324983349834498354983649837498384983949840498414984249843498444984549846498474984849849498504985149852498534985449855498564985749858498594986049861498624986349864498654986649867498684986949870498714987249873498744987549876498774987849879498804988149882498834988449885498864988749888498894989049891498924989349894498954989649897498984989949900499014990249903499044990549906499074990849909499104991149912499134991449915499164991749918499194992049921499224992349924499254992649927499284992949930499314993249933499344993549936499374993849939499404994149942499434994449945499464994749948499494995049951499524995349954499554995649957499584995949960499614996249963499644996549966499674996849969499704997149972499734997449975499764997749978499794998049981499824998349984499854998649987499884998949990499914999249993499944999549996499974999849999500005000150002500035000450005500065000750008500095001050011500125001350014500155001650017500185001950020500215002250023500245002550026500275002850029500305003150032500335003450035500365003750038500395004050041500425004350044500455004650047500485004950050500515005250053500545005550056500575005850059500605006150062500635006450065500665006750068500695007050071500725007350074500755007650077500785007950080500815008250083500845008550086500875008850089500905009150092500935009450095500965009750098500995010050101501025010350104501055010650107501085010950110501115011250113501145011550116501175011850119501205012150122501235012450125501265012750128501295013050131501325013350134501355013650137501385013950140501415014250143501445014550146501475014850149501505015150152501535015450155501565015750158501595016050161501625016350164501655016650167501685016950170501715017250173501745017550176501775017850179501805018150182501835018450185501865018750188501895019050191501925019350194501955019650197501985019950200502015020250203502045020550206502075020850209502105021150212502135021450215502165021750218502195022050221502225022350224502255022650227502285022950230502315023250233502345023550236502375023850239502405024150242502435024450245502465024750248502495025050251502525025350254502555025650257502585025950260502615026250263502645026550266502675026850269502705027150272502735027450275502765027750278502795028050281502825028350284502855028650287502885028950290502915029250293502945029550296502975029850299503005030150302503035030450305503065030750308503095031050311503125031350314503155031650317503185031950320503215032250323503245032550326503275032850329503305033150332503335033450335503365033750338503395034050341503425034350344503455034650347503485034950350503515035250353503545035550356503575035850359503605036150362503635036450365503665036750368503695037050371503725037350374503755037650377503785037950380503815038250383503845038550386503875038850389503905039150392503935039450395503965039750398503995040050401504025040350404504055040650407504085040950410504115041250413504145041550416504175041850419504205042150422504235042450425504265042750428504295043050431504325043350434504355043650437504385043950440504415044250443504445044550446504475044850449504505045150452504535045450455504565045750458504595046050461504625046350464504655046650467504685046950470504715047250473504745047550476504775047850479504805048150482504835048450485504865048750488504895049050491504925049350494504955049650497504985049950500505015050250503505045050550506505075050850509505105051150512505135051450515505165051750518505195052050521505225052350524505255052650527505285052950530505315053250533505345053550536505375053850539505405054150542505435054450545505465054750548505495055050551505525055350554505555055650557505585055950560505615056250563505645056550566505675056850569505705057150572505735057450575505765057750578505795058050581505825058350584505855058650587505885058950590505915059250593505945059550596505975059850599506005060150602506035060450605506065060750608506095061050611506125061350614506155061650617506185061950620506215062250623506245062550626506275062850629506305063150632506335063450635506365063750638506395064050641506425064350644506455064650647506485064950650506515065250653506545065550656506575065850659506605066150662506635066450665506665066750668506695067050671506725067350674506755067650677506785067950680506815068250683506845068550686506875068850689506905069150692506935069450695506965069750698506995070050701507025070350704507055070650707507085070950710507115071250713507145071550716507175071850719507205072150722507235072450725507265072750728507295073050731507325073350734507355073650737507385073950740507415074250743507445074550746507475074850749507505075150752507535075450755507565075750758507595076050761507625076350764507655076650767507685076950770507715077250773507745077550776507775077850779507805078150782507835078450785507865078750788507895079050791507925079350794507955079650797507985079950800508015080250803508045080550806508075080850809508105081150812508135081450815508165081750818508195082050821508225082350824508255082650827508285082950830508315083250833508345083550836508375083850839508405084150842508435084450845508465084750848508495085050851508525085350854508555085650857508585085950860508615086250863508645086550866508675086850869508705087150872508735087450875508765087750878508795088050881508825088350884508855088650887508885088950890508915089250893508945089550896508975089850899509005090150902509035090450905509065090750908509095091050911509125091350914509155091650917509185091950920509215092250923509245092550926509275092850929509305093150932509335093450935509365093750938509395094050941509425094350944509455094650947509485094950950509515095250953509545095550956509575095850959509605096150962509635096450965509665096750968509695097050971509725097350974509755097650977509785097950980509815098250983509845098550986509875098850989509905099150992509935099450995509965099750998509995100051001510025100351004510055100651007510085100951010510115101251013510145101551016510175101851019510205102151022510235102451025510265102751028510295103051031510325103351034510355103651037510385103951040510415104251043510445104551046510475104851049510505105151052510535105451055510565105751058510595106051061510625106351064510655106651067510685106951070510715107251073510745107551076510775107851079510805108151082510835108451085510865108751088510895109051091510925109351094510955109651097510985109951100511015110251103511045110551106511075110851109511105111151112511135111451115511165111751118511195112051121511225112351124511255112651127511285112951130511315113251133511345113551136511375113851139511405114151142511435114451145511465114751148511495115051151511525115351154511555115651157511585115951160511615116251163511645116551166511675116851169511705117151172511735117451175511765117751178511795118051181511825118351184511855118651187511885118951190511915119251193511945119551196511975119851199512005120151202512035120451205512065120751208512095121051211512125121351214512155121651217512185121951220512215122251223512245122551226512275122851229512305123151232512335123451235512365123751238512395124051241512425124351244512455124651247512485124951250512515125251253512545125551256512575125851259512605126151262512635126451265512665126751268512695127051271512725127351274512755127651277512785127951280512815128251283512845128551286512875128851289512905129151292512935129451295512965129751298512995130051301513025130351304513055130651307513085130951310513115131251313513145131551316513175131851319513205132151322513235132451325513265132751328513295133051331513325133351334513355133651337513385133951340513415134251343513445134551346513475134851349513505135151352513535135451355513565135751358513595136051361513625136351364513655136651367513685136951370513715137251373513745137551376513775137851379513805138151382513835138451385513865138751388513895139051391513925139351394513955139651397513985139951400514015140251403514045140551406514075140851409514105141151412514135141451415514165141751418514195142051421514225142351424514255142651427514285142951430514315143251433514345143551436514375143851439514405144151442514435144451445514465144751448514495145051451514525145351454514555145651457514585145951460514615146251463514645146551466514675146851469514705147151472514735147451475514765147751478514795148051481514825148351484514855148651487514885148951490514915149251493514945149551496514975149851499515005150151502515035150451505515065150751508515095151051511515125151351514515155151651517515185151951520515215152251523515245152551526515275152851529515305153151532515335153451535515365153751538515395154051541515425154351544515455154651547515485154951550515515155251553515545155551556515575155851559515605156151562515635156451565515665156751568515695157051571515725157351574515755157651577515785157951580515815158251583515845158551586515875158851589515905159151592515935159451595515965159751598515995160051601516025160351604516055160651607516085160951610516115161251613516145161551616516175161851619516205162151622516235162451625516265162751628516295163051631516325163351634516355163651637516385163951640516415164251643516445164551646516475164851649516505165151652516535165451655516565165751658516595166051661516625166351664516655166651667516685166951670516715167251673516745167551676516775167851679516805168151682516835168451685516865168751688516895169051691516925169351694516955169651697516985169951700517015170251703517045170551706517075170851709517105171151712517135171451715517165171751718517195172051721517225172351724517255172651727517285172951730517315173251733517345173551736517375173851739517405174151742517435174451745517465174751748517495175051751517525175351754517555175651757517585175951760517615176251763517645176551766517675176851769517705177151772517735177451775517765177751778517795178051781517825178351784517855178651787517885178951790517915179251793517945179551796517975179851799518005180151802518035180451805518065180751808518095181051811518125181351814518155181651817518185181951820518215182251823518245182551826518275182851829518305183151832518335183451835518365183751838518395184051841518425184351844518455184651847518485184951850518515185251853518545185551856518575185851859518605186151862518635186451865518665186751868518695187051871518725187351874518755187651877518785187951880518815188251883518845188551886518875188851889518905189151892518935189451895518965189751898518995190051901519025190351904519055190651907519085190951910519115191251913519145191551916519175191851919519205192151922519235192451925519265192751928519295193051931519325193351934519355193651937519385193951940519415194251943519445194551946519475194851949519505195151952519535195451955519565195751958519595196051961519625196351964519655196651967519685196951970519715197251973519745197551976519775197851979519805198151982519835198451985519865198751988519895199051991519925199351994519955199651997519985199952000520015200252003520045200552006520075200852009520105201152012520135201452015520165201752018520195202052021520225202352024520255202652027520285202952030520315203252033520345203552036520375203852039520405204152042520435204452045520465204752048520495205052051520525205352054520555205652057520585205952060520615206252063520645206552066520675206852069520705207152072520735207452075520765207752078520795208052081520825208352084520855208652087520885208952090520915209252093520945209552096520975209852099521005210152102521035210452105521065210752108521095211052111521125211352114521155211652117521185211952120521215212252123521245212552126521275212852129521305213152132521335213452135521365213752138521395214052141521425214352144521455214652147521485214952150521515215252153521545215552156521575215852159521605216152162521635216452165521665216752168521695217052171521725217352174521755217652177521785217952180521815218252183521845218552186521875218852189521905219152192521935219452195521965219752198521995220052201522025220352204522055220652207522085220952210522115221252213522145221552216522175221852219522205222152222522235222452225522265222752228522295223052231522325223352234522355223652237522385223952240522415224252243522445224552246522475224852249522505225152252522535225452255522565225752258522595226052261522625226352264522655226652267522685226952270522715227252273522745227552276522775227852279522805228152282522835228452285522865228752288522895229052291522925229352294522955229652297522985229952300523015230252303523045230552306523075230852309523105231152312523135231452315523165231752318523195232052321523225232352324523255232652327523285232952330523315233252333523345233552336523375233852339523405234152342523435234452345523465234752348523495235052351523525235352354523555235652357523585235952360523615236252363523645236552366523675236852369523705237152372523735237452375523765237752378523795238052381523825238352384523855238652387523885238952390523915239252393523945239552396523975239852399524005240152402524035240452405524065240752408524095241052411524125241352414524155241652417524185241952420524215242252423524245242552426524275242852429524305243152432524335243452435524365243752438524395244052441524425244352444524455244652447524485244952450524515245252453524545245552456524575245852459524605246152462524635246452465524665246752468524695247052471524725247352474524755247652477524785247952480524815248252483524845248552486524875248852489524905249152492524935249452495524965249752498524995250052501525025250352504525055250652507525085250952510525115251252513525145251552516525175251852519525205252152522525235252452525525265252752528525295253052531525325253352534525355253652537525385253952540525415254252543525445254552546525475254852549525505255152552525535255452555525565255752558525595256052561525625256352564525655256652567525685256952570525715257252573525745257552576525775257852579525805258152582525835258452585525865258752588525895259052591525925259352594525955259652597525985259952600526015260252603526045260552606526075260852609526105261152612526135261452615526165261752618526195262052621526225262352624526255262652627526285262952630526315263252633526345263552636526375263852639526405264152642526435264452645526465264752648526495265052651526525265352654526555265652657526585265952660526615266252663526645266552666526675266852669526705267152672526735267452675526765267752678526795268052681526825268352684526855268652687526885268952690526915269252693526945269552696526975269852699527005270152702527035270452705527065270752708527095271052711527125271352714527155271652717527185271952720527215272252723527245272552726527275272852729527305273152732527335273452735527365273752738527395274052741527425274352744527455274652747527485274952750527515275252753527545275552756527575275852759527605276152762527635276452765527665276752768527695277052771527725277352774527755277652777527785277952780527815278252783527845278552786527875278852789527905279152792527935279452795527965279752798527995280052801528025280352804528055280652807528085280952810528115281252813528145281552816528175281852819528205282152822528235282452825528265282752828528295283052831528325283352834528355283652837528385283952840528415284252843528445284552846528475284852849528505285152852528535285452855528565285752858528595286052861528625286352864528655286652867528685286952870528715287252873528745287552876528775287852879528805288152882528835288452885528865288752888528895289052891528925289352894528955289652897528985289952900529015290252903529045290552906529075290852909529105291152912529135291452915529165291752918529195292052921529225292352924529255292652927529285292952930529315293252933529345293552936529375293852939529405294152942529435294452945529465294752948529495295052951529525295352954529555295652957529585295952960529615296252963529645296552966529675296852969529705297152972529735297452975529765297752978529795298052981529825298352984529855298652987529885298952990529915299252993529945299552996529975299852999530005300153002530035300453005530065300753008530095301053011530125301353014530155301653017530185301953020530215302253023530245302553026530275302853029530305303153032530335303453035530365303753038530395304053041530425304353044530455304653047530485304953050530515305253053530545305553056530575305853059530605306153062530635306453065530665306753068530695307053071530725307353074530755307653077530785307953080530815308253083530845308553086530875308853089530905309153092530935309453095530965309753098530995310053101531025310353104531055310653107531085310953110531115311253113531145311553116531175311853119531205312153122531235312453125531265312753128531295313053131531325313353134531355313653137531385313953140531415314253143531445314553146531475314853149531505315153152531535315453155531565315753158531595316053161531625316353164531655316653167531685316953170531715317253173531745317553176531775317853179531805318153182531835318453185531865318753188531895319053191531925319353194531955319653197531985319953200532015320253203532045320553206532075320853209532105321153212532135321453215532165321753218532195322053221532225322353224532255322653227532285322953230532315323253233532345323553236532375323853239532405324153242532435324453245532465324753248532495325053251532525325353254532555325653257532585325953260532615326253263532645326553266532675326853269532705327153272532735327453275532765327753278532795328053281532825328353284532855328653287532885328953290532915329253293532945329553296532975329853299533005330153302533035330453305533065330753308533095331053311533125331353314533155331653317533185331953320533215332253323533245332553326533275332853329533305333153332533335333453335533365333753338533395334053341533425334353344533455334653347533485334953350533515335253353533545335553356533575335853359533605336153362533635336453365533665336753368533695337053371533725337353374533755337653377533785337953380533815338253383533845338553386533875338853389533905339153392533935339453395533965339753398533995340053401534025340353404534055340653407534085340953410534115341253413534145341553416534175341853419534205342153422534235342453425534265342753428534295343053431534325343353434534355343653437534385343953440534415344253443534445344553446534475344853449534505345153452534535345453455534565345753458534595346053461534625346353464534655346653467534685346953470534715347253473534745347553476534775347853479534805348153482534835348453485534865348753488534895349053491534925349353494534955349653497534985349953500535015350253503535045350553506535075350853509535105351153512535135351453515535165351753518535195352053521535225352353524535255352653527535285352953530535315353253533535345353553536535375353853539535405354153542535435354453545535465354753548535495355053551535525355353554535555355653557535585355953560535615356253563535645356553566535675356853569535705357153572535735357453575535765357753578535795358053581535825358353584535855358653587535885358953590535915359253593535945359553596535975359853599536005360153602536035360453605536065360753608536095361053611536125361353614536155361653617536185361953620536215362253623536245362553626536275362853629536305363153632536335363453635536365363753638536395364053641536425364353644536455364653647536485364953650536515365253653536545365553656536575365853659536605366153662536635366453665536665366753668536695367053671536725367353674536755367653677536785367953680536815368253683536845368553686536875368853689536905369153692536935369453695536965369753698536995370053701537025370353704537055370653707537085370953710537115371253713537145371553716537175371853719537205372153722537235372453725537265372753728537295373053731537325373353734537355373653737537385373953740537415374253743537445374553746537475374853749537505375153752537535375453755537565375753758537595376053761537625376353764537655376653767537685376953770537715377253773537745377553776537775377853779537805378153782537835378453785537865378753788537895379053791537925379353794537955379653797537985379953800538015380253803538045380553806538075380853809538105381153812538135381453815538165381753818538195382053821538225382353824538255382653827538285382953830538315383253833538345383553836538375383853839538405384153842538435384453845538465384753848538495385053851538525385353854538555385653857538585385953860538615386253863538645386553866538675386853869538705387153872538735387453875538765387753878538795388053881538825388353884538855388653887538885388953890538915389253893538945389553896538975389853899539005390153902539035390453905539065390753908539095391053911539125391353914539155391653917539185391953920539215392253923539245392553926539275392853929539305393153932539335393453935539365393753938539395394053941539425394353944539455394653947539485394953950539515395253953539545395553956539575395853959539605396153962539635396453965539665396753968539695397053971539725397353974539755397653977539785397953980539815398253983539845398553986539875398853989539905399153992539935399453995539965399753998539995400054001540025400354004540055400654007540085400954010540115401254013540145401554016540175401854019540205402154022540235402454025540265402754028540295403054031540325403354034540355403654037540385403954040540415404254043540445404554046540475404854049540505405154052540535405454055540565405754058540595406054061540625406354064540655406654067540685406954070540715407254073540745407554076540775407854079540805408154082540835408454085540865408754088540895409054091540925409354094540955409654097540985409954100541015410254103541045410554106541075410854109541105411154112541135411454115541165411754118541195412054121541225412354124541255412654127541285412954130541315413254133541345413554136541375413854139541405414154142541435414454145541465414754148541495415054151541525415354154541555415654157541585415954160541615416254163541645416554166541675416854169541705417154172541735417454175541765417754178541795418054181541825418354184541855418654187541885418954190541915419254193541945419554196541975419854199542005420154202542035420454205542065420754208542095421054211542125421354214542155421654217542185421954220542215422254223542245422554226542275422854229542305423154232542335423454235542365423754238542395424054241542425424354244542455424654247542485424954250542515425254253542545425554256542575425854259542605426154262542635426454265542665426754268542695427054271542725427354274542755427654277542785427954280542815428254283542845428554286542875428854289542905429154292542935429454295542965429754298542995430054301543025430354304543055430654307543085430954310543115431254313543145431554316543175431854319543205432154322543235432454325543265432754328543295433054331543325433354334543355433654337543385433954340543415434254343543445434554346543475434854349543505435154352543535435454355543565435754358543595436054361543625436354364543655436654367543685436954370543715437254373543745437554376543775437854379543805438154382543835438454385543865438754388543895439054391543925439354394543955439654397543985439954400544015440254403544045440554406544075440854409544105441154412544135441454415544165441754418544195442054421544225442354424544255442654427544285442954430544315443254433544345443554436544375443854439544405444154442544435444454445544465444754448544495445054451544525445354454544555445654457544585445954460544615446254463544645446554466544675446854469544705447154472544735447454475544765447754478544795448054481544825448354484544855448654487544885448954490544915449254493544945449554496544975449854499545005450154502545035450454505545065450754508545095451054511545125451354514545155451654517545185451954520545215452254523545245452554526545275452854529545305453154532545335453454535545365453754538545395454054541545425454354544545455454654547545485454954550545515455254553545545455554556545575455854559545605456154562545635456454565545665456754568545695457054571545725457354574545755457654577545785457954580545815458254583545845458554586545875458854589545905459154592545935459454595545965459754598545995460054601546025460354604546055460654607546085460954610546115461254613546145461554616546175461854619546205462154622546235462454625546265462754628546295463054631546325463354634546355463654637546385463954640546415464254643546445464554646546475464854649546505465154652546535465454655546565465754658546595466054661546625466354664546655466654667546685466954670546715467254673546745467554676546775467854679546805468154682546835468454685546865468754688546895469054691546925469354694546955469654697546985469954700547015470254703547045470554706547075470854709547105471154712547135471454715547165471754718547195472054721547225472354724547255472654727547285472954730547315473254733547345473554736547375473854739547405474154742547435474454745547465474754748547495475054751547525475354754547555475654757547585475954760547615476254763547645476554766547675476854769547705477154772547735477454775547765477754778547795478054781547825478354784547855478654787547885478954790547915479254793547945479554796547975479854799548005480154802548035480454805548065480754808548095481054811548125481354814548155481654817548185481954820548215482254823548245482554826548275482854829548305483154832548335483454835548365483754838548395484054841548425484354844548455484654847548485484954850548515485254853548545485554856548575485854859548605486154862548635486454865548665486754868548695487054871548725487354874548755487654877548785487954880548815488254883548845488554886548875488854889548905489154892548935489454895548965489754898548995490054901549025490354904549055490654907549085490954910549115491254913549145491554916549175491854919549205492154922549235492454925549265492754928549295493054931549325493354934549355493654937549385493954940549415494254943549445494554946549475494854949549505495154952549535495454955549565495754958549595496054961549625496354964549655496654967549685496954970549715497254973549745497554976549775497854979549805498154982549835498454985549865498754988549895499054991549925499354994549955499654997549985499955000550015500255003550045500555006550075500855009550105501155012550135501455015550165501755018550195502055021550225502355024550255502655027550285502955030550315503255033550345503555036550375503855039550405504155042550435504455045550465504755048550495505055051550525505355054550555505655057550585505955060550615506255063550645506555066550675506855069550705507155072550735507455075550765507755078550795508055081550825508355084550855508655087550885508955090550915509255093550945509555096550975509855099551005510155102551035510455105551065510755108551095511055111551125511355114551155511655117551185511955120551215512255123551245512555126551275512855129551305513155132551335513455135551365513755138551395514055141551425514355144551455514655147551485514955150551515515255153551545515555156551575515855159551605516155162551635516455165551665516755168551695517055171551725517355174551755517655177551785517955180551815518255183551845518555186551875518855189551905519155192551935519455195551965519755198551995520055201552025520355204552055520655207552085520955210552115521255213552145521555216552175521855219552205522155222552235522455225552265522755228552295523055231552325523355234552355523655237552385523955240552415524255243552445524555246552475524855249552505525155252552535525455255552565525755258552595526055261552625526355264552655526655267552685526955270552715527255273552745527555276552775527855279552805528155282552835528455285552865528755288552895529055291552925529355294552955529655297552985529955300553015530255303553045530555306553075530855309553105531155312553135531455315553165531755318553195532055321553225532355324553255532655327553285532955330553315533255333553345533555336553375533855339553405534155342553435534455345553465534755348553495535055351553525535355354553555535655357553585535955360553615536255363553645536555366553675536855369553705537155372553735537455375553765537755378553795538055381553825538355384553855538655387553885538955390553915539255393553945539555396553975539855399554005540155402554035540455405554065540755408554095541055411554125541355414554155541655417554185541955420554215542255423554245542555426554275542855429554305543155432554335543455435554365543755438554395544055441554425544355444554455544655447554485544955450554515545255453554545545555456554575545855459554605546155462554635546455465554665546755468554695547055471554725547355474554755547655477554785547955480554815548255483554845548555486554875548855489554905549155492554935549455495554965549755498554995550055501555025550355504555055550655507555085550955510555115551255513555145551555516555175551855519555205552155522555235552455525555265552755528555295553055531555325553355534555355553655537555385553955540555415554255543555445554555546555475554855549555505555155552555535555455555555565555755558555595556055561555625556355564555655556655567555685556955570555715557255573555745557555576555775557855579555805558155582555835558455585555865558755588555895559055591555925559355594555955559655597555985559955600556015560255603556045560555606556075560855609556105561155612556135561455615556165561755618556195562055621556225562355624556255562655627556285562955630556315563255633556345563555636556375563855639556405564155642556435564455645556465564755648556495565055651556525565355654556555565655657556585565955660556615566255663556645566555666556675566855669556705567155672556735567455675556765567755678556795568055681556825568355684556855568655687556885568955690556915569255693556945569555696556975569855699557005570155702557035570455705557065570755708557095571055711557125571355714557155571655717557185571955720557215572255723557245572555726557275572855729557305573155732557335573455735557365573755738557395574055741557425574355744557455574655747557485574955750557515575255753557545575555756557575575855759557605576155762557635576455765557665576755768557695577055771557725577355774557755577655777557785577955780557815578255783557845578555786557875578855789557905579155792557935579455795557965579755798557995580055801558025580355804558055580655807558085580955810558115581255813558145581555816558175581855819558205582155822558235582455825558265582755828558295583055831558325583355834558355583655837558385583955840558415584255843558445584555846558475584855849558505585155852558535585455855558565585755858558595586055861558625586355864558655586655867558685586955870558715587255873558745587555876558775587855879558805588155882558835588455885558865588755888558895589055891558925589355894558955589655897558985589955900559015590255903559045590555906559075590855909559105591155912559135591455915559165591755918559195592055921559225592355924559255592655927559285592955930559315593255933559345593555936559375593855939559405594155942559435594455945559465594755948559495595055951559525595355954559555595655957559585595955960559615596255963559645596555966559675596855969559705597155972559735597455975559765597755978559795598055981559825598355984559855598655987559885598955990559915599255993559945599555996559975599855999560005600156002560035600456005560065600756008560095601056011560125601356014560155601656017560185601956020560215602256023560245602556026560275602856029560305603156032560335603456035560365603756038560395604056041560425604356044560455604656047560485604956050560515605256053560545605556056560575605856059560605606156062560635606456065560665606756068560695607056071560725607356074560755607656077560785607956080560815608256083560845608556086560875608856089560905609156092560935609456095560965609756098560995610056101561025610356104561055610656107561085610956110561115611256113561145611556116561175611856119561205612156122561235612456125561265612756128561295613056131561325613356134561355613656137561385613956140561415614256143561445614556146561475614856149561505615156152561535615456155561565615756158561595616056161561625616356164561655616656167561685616956170561715617256173561745617556176561775617856179561805618156182561835618456185561865618756188561895619056191561925619356194561955619656197561985619956200562015620256203562045620556206562075620856209562105621156212562135621456215562165621756218562195622056221562225622356224562255622656227562285622956230562315623256233562345623556236562375623856239562405624156242562435624456245562465624756248562495625056251562525625356254562555625656257562585625956260562615626256263562645626556266562675626856269562705627156272562735627456275562765627756278562795628056281562825628356284562855628656287562885628956290562915629256293562945629556296562975629856299563005630156302563035630456305563065630756308563095631056311563125631356314563155631656317563185631956320563215632256323563245632556326563275632856329563305633156332563335633456335563365633756338563395634056341563425634356344563455634656347563485634956350563515635256353563545635556356563575635856359563605636156362563635636456365563665636756368563695637056371563725637356374563755637656377563785637956380563815638256383563845638556386563875638856389563905639156392563935639456395563965639756398563995640056401564025640356404564055640656407564085640956410564115641256413564145641556416564175641856419564205642156422564235642456425564265642756428564295643056431564325643356434564355643656437564385643956440564415644256443564445644556446564475644856449564505645156452564535645456455564565645756458564595646056461564625646356464564655646656467564685646956470564715647256473564745647556476564775647856479564805648156482564835648456485564865648756488564895649056491564925649356494564955649656497564985649956500565015650256503565045650556506565075650856509565105651156512565135651456515565165651756518565195652056521565225652356524565255652656527565285652956530565315653256533565345653556536565375653856539565405654156542565435654456545565465654756548565495655056551565525655356554565555655656557565585655956560565615656256563565645656556566565675656856569565705657156572565735657456575565765657756578565795658056581565825658356584565855658656587565885658956590565915659256593565945659556596565975659856599566005660156602566035660456605566065660756608566095661056611566125661356614566155661656617566185661956620566215662256623566245662556626566275662856629566305663156632566335663456635566365663756638566395664056641566425664356644566455664656647566485664956650566515665256653566545665556656566575665856659566605666156662566635666456665566665666756668566695667056671566725667356674566755667656677566785667956680566815668256683566845668556686566875668856689566905669156692566935669456695566965669756698566995670056701567025670356704567055670656707567085670956710567115671256713567145671556716567175671856719567205672156722567235672456725567265672756728567295673056731567325673356734567355673656737567385673956740567415674256743567445674556746567475674856749567505675156752567535675456755567565675756758567595676056761567625676356764567655676656767567685676956770567715677256773567745677556776567775677856779567805678156782567835678456785567865678756788567895679056791567925679356794567955679656797567985679956800568015680256803568045680556806568075680856809568105681156812568135681456815568165681756818568195682056821568225682356824568255682656827568285682956830568315683256833568345683556836568375683856839568405684156842568435684456845568465684756848568495685056851568525685356854568555685656857568585685956860568615686256863568645686556866568675686856869
  1. From 9964a43723df02a84b7f132695193cd452d45b58 Mon Sep 17 00:00:00 2001
  2. From: popcornmix <popcornmix@gmail.com>
  3. Date: Wed, 1 May 2013 19:46:17 +0100
  4. Subject: [PATCH 004/114] Add dwc_otg driver
  5. Signed-off-by: popcornmix <popcornmix@gmail.com>
  6. usb: dwc: fix lockdep false positive
  7. Signed-off-by: Kari Suvanto <karis79@gmail.com>
  8. usb: dwc: fix inconsistent lock state
  9. Signed-off-by: Kari Suvanto <karis79@gmail.com>
  10. ---
  11. drivers/usb/Makefile | 1 +
  12. drivers/usb/core/generic.c | 1 +
  13. drivers/usb/core/message.c | 79 +
  14. drivers/usb/core/otg_whitelist.h | 114 +-
  15. drivers/usb/gadget/file_storage.c | 3676 ++++++++++
  16. drivers/usb/host/Kconfig | 13 +
  17. drivers/usb/host/Makefile | 2 +
  18. drivers/usb/host/dwc_common_port/Makefile | 58 +
  19. drivers/usb/host/dwc_common_port/Makefile.fbsd | 17 +
  20. drivers/usb/host/dwc_common_port/Makefile.linux | 49 +
  21. drivers/usb/host/dwc_common_port/changes.txt | 174 +
  22. drivers/usb/host/dwc_common_port/doc/doxygen.cfg | 270 +
  23. drivers/usb/host/dwc_common_port/dwc_cc.c | 532 ++
  24. drivers/usb/host/dwc_common_port/dwc_cc.h | 224 +
  25. drivers/usb/host/dwc_common_port/dwc_common_fbsd.c | 1308 ++++
  26. .../usb/host/dwc_common_port/dwc_common_linux.c | 1429 ++++
  27. drivers/usb/host/dwc_common_port/dwc_common_nbsd.c | 1275 ++++
  28. drivers/usb/host/dwc_common_port/dwc_crypto.c | 308 +
  29. drivers/usb/host/dwc_common_port/dwc_crypto.h | 111 +
  30. drivers/usb/host/dwc_common_port/dwc_dh.c | 291 +
  31. drivers/usb/host/dwc_common_port/dwc_dh.h | 106 +
  32. drivers/usb/host/dwc_common_port/dwc_list.h | 594 ++
  33. drivers/usb/host/dwc_common_port/dwc_mem.c | 245 +
  34. drivers/usb/host/dwc_common_port/dwc_modpow.c | 636 ++
  35. drivers/usb/host/dwc_common_port/dwc_modpow.h | 34 +
  36. drivers/usb/host/dwc_common_port/dwc_notifier.c | 319 +
  37. drivers/usb/host/dwc_common_port/dwc_notifier.h | 122 +
  38. drivers/usb/host/dwc_common_port/dwc_os.h | 1274 ++++
  39. drivers/usb/host/dwc_common_port/usb.h | 946 +++
  40. drivers/usb/host/dwc_otg/Makefile | 80 +
  41. drivers/usb/host/dwc_otg/doc/doxygen.cfg | 224 +
  42. drivers/usb/host/dwc_otg/dummy_audio.c | 1575 +++++
  43. drivers/usb/host/dwc_otg/dwc_cfi_common.h | 142 +
  44. drivers/usb/host/dwc_otg/dwc_otg_adp.c | 854 +++
  45. drivers/usb/host/dwc_otg/dwc_otg_adp.h | 80 +
  46. drivers/usb/host/dwc_otg/dwc_otg_attr.c | 1210 ++++
  47. drivers/usb/host/dwc_otg/dwc_otg_attr.h | 89 +
  48. drivers/usb/host/dwc_otg/dwc_otg_cfi.c | 1876 +++++
  49. drivers/usb/host/dwc_otg/dwc_otg_cfi.h | 320 +
  50. drivers/usb/host/dwc_otg/dwc_otg_cil.c | 7151 ++++++++++++++++++++
  51. drivers/usb/host/dwc_otg/dwc_otg_cil.h | 1464 ++++
  52. drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 1563 +++++
  53. drivers/usb/host/dwc_otg/dwc_otg_core_if.h | 705 ++
  54. drivers/usb/host/dwc_otg/dwc_otg_dbg.h | 116 +
  55. drivers/usb/host/dwc_otg/dwc_otg_driver.c | 1700 +++++
  56. drivers/usb/host/dwc_otg/dwc_otg_driver.h | 86 +
  57. drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 3479 ++++++++++
  58. drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 824 +++
  59. drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 1133 ++++
  60. drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h | 412 ++
  61. drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 2106 ++++++
  62. drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 893 +++
  63. drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 923 +++
  64. drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 185 +
  65. drivers/usb/host/dwc_otg/dwc_otg_pcd.c | 2712 ++++++++
  66. drivers/usb/host/dwc_otg/dwc_otg_pcd.h | 266 +
  67. drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h | 360 +
  68. drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c | 5147 ++++++++++++++
  69. drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 1358 ++++
  70. drivers/usb/host/dwc_otg/dwc_otg_regs.h | 2550 +++++++
  71. drivers/usb/host/dwc_otg/test/Makefile | 16 +
  72. drivers/usb/host/dwc_otg/test/dwc_otg_test.pm | 337 +
  73. drivers/usb/host/dwc_otg/test/test_mod_param.pl | 133 +
  74. drivers/usb/host/dwc_otg/test/test_sysfs.pl | 193 +
  75. 64 files changed, 56458 insertions(+), 12 deletions(-)
  76. create mode 100644 drivers/usb/gadget/file_storage.c
  77. create mode 100644 drivers/usb/host/dwc_common_port/Makefile
  78. create mode 100644 drivers/usb/host/dwc_common_port/Makefile.fbsd
  79. create mode 100644 drivers/usb/host/dwc_common_port/Makefile.linux
  80. create mode 100644 drivers/usb/host/dwc_common_port/changes.txt
  81. create mode 100644 drivers/usb/host/dwc_common_port/doc/doxygen.cfg
  82. create mode 100644 drivers/usb/host/dwc_common_port/dwc_cc.c
  83. create mode 100644 drivers/usb/host/dwc_common_port/dwc_cc.h
  84. create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_fbsd.c
  85. create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_linux.c
  86. create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_nbsd.c
  87. create mode 100644 drivers/usb/host/dwc_common_port/dwc_crypto.c
  88. create mode 100644 drivers/usb/host/dwc_common_port/dwc_crypto.h
  89. create mode 100644 drivers/usb/host/dwc_common_port/dwc_dh.c
  90. create mode 100644 drivers/usb/host/dwc_common_port/dwc_dh.h
  91. create mode 100644 drivers/usb/host/dwc_common_port/dwc_list.h
  92. create mode 100644 drivers/usb/host/dwc_common_port/dwc_mem.c
  93. create mode 100644 drivers/usb/host/dwc_common_port/dwc_modpow.c
  94. create mode 100644 drivers/usb/host/dwc_common_port/dwc_modpow.h
  95. create mode 100644 drivers/usb/host/dwc_common_port/dwc_notifier.c
  96. create mode 100644 drivers/usb/host/dwc_common_port/dwc_notifier.h
  97. create mode 100644 drivers/usb/host/dwc_common_port/dwc_os.h
  98. create mode 100644 drivers/usb/host/dwc_common_port/usb.h
  99. create mode 100644 drivers/usb/host/dwc_otg/Makefile
  100. create mode 100644 drivers/usb/host/dwc_otg/doc/doxygen.cfg
  101. create mode 100644 drivers/usb/host/dwc_otg/dummy_audio.c
  102. create mode 100644 drivers/usb/host/dwc_otg/dwc_cfi_common.h
  103. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_adp.c
  104. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_adp.h
  105. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.c
  106. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.h
  107. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cfi.c
  108. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cfi.h
  109. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.c
  110. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.h
  111. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
  112. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_core_if.h
  113. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_dbg.h
  114. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_driver.c
  115. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_driver.h
  116. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.c
  117. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.h
  118. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
  119. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
  120. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
  121. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
  122. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
  123. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
  124. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd.c
  125. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd.h
  126. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
  127. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
  128. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
  129. create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_regs.h
  130. create mode 100644 drivers/usb/host/dwc_otg/test/Makefile
  131. create mode 100644 drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
  132. create mode 100644 drivers/usb/host/dwc_otg/test/test_mod_param.pl
  133. create mode 100644 drivers/usb/host/dwc_otg/test/test_sysfs.pl
  134. --- a/drivers/usb/Makefile
  135. +++ b/drivers/usb/Makefile
  136. @@ -24,6 +24,7 @@ obj-$(CONFIG_USB_U132_HCD) += host/
  137. obj-$(CONFIG_USB_R8A66597_HCD) += host/
  138. obj-$(CONFIG_USB_HWA_HCD) += host/
  139. obj-$(CONFIG_USB_ISP1760_HCD) += host/
  140. +obj-$(CONFIG_USB_DWCOTG) += host/
  141. obj-$(CONFIG_USB_IMX21_HCD) += host/
  142. obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/
  143. obj-$(CONFIG_USB_FUSBH200_HCD) += host/
  144. --- a/drivers/usb/core/generic.c
  145. +++ b/drivers/usb/core/generic.c
  146. @@ -152,6 +152,7 @@ int usb_choose_configuration(struct usb_
  147. dev_warn(&udev->dev,
  148. "no configuration chosen from %d choice%s\n",
  149. num_configs, plural(num_configs));
  150. + dev_warn(&udev->dev, "No support over %dmA\n", udev->bus_mA);
  151. }
  152. return i;
  153. }
  154. --- a/drivers/usb/core/message.c
  155. +++ b/drivers/usb/core/message.c
  156. @@ -1872,6 +1872,85 @@ free_interfaces:
  157. if (cp->string == NULL &&
  158. !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
  159. cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
  160. +/* Uncomment this define to enable the HS Electrical Test support */
  161. +#define DWC_HS_ELECT_TST 1
  162. +#ifdef DWC_HS_ELECT_TST
  163. + /* Here we implement the HS Electrical Test support. The
  164. + * tester uses a vendor ID of 0x1A0A to indicate we should
  165. + * run a special test sequence. The product ID tells us
  166. + * which sequence to run. We invoke the test sequence by
  167. + * sending a non-standard SetFeature command to our root
  168. + * hub port. Our dwc_otg_hcd_hub_control() routine will
  169. + * recognize the command and perform the desired test
  170. + * sequence.
  171. + */
  172. + if (dev->descriptor.idVendor == 0x1A0A) {
  173. + /* HSOTG Electrical Test */
  174. + dev_warn(&dev->dev, "VID from HSOTG Electrical Test Fixture\n");
  175. +
  176. + if (dev->bus && dev->bus->root_hub) {
  177. + struct usb_device *hdev = dev->bus->root_hub;
  178. + dev_warn(&dev->dev, "Got PID 0x%x\n", dev->descriptor.idProduct);
  179. +
  180. + switch (dev->descriptor.idProduct) {
  181. + case 0x0101: /* TEST_SE0_NAK */
  182. + dev_warn(&dev->dev, "TEST_SE0_NAK\n");
  183. + usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
  184. + USB_REQ_SET_FEATURE, USB_RT_PORT,
  185. + USB_PORT_FEAT_TEST, 0x300, NULL, 0, HZ);
  186. + break;
  187. +
  188. + case 0x0102: /* TEST_J */
  189. + dev_warn(&dev->dev, "TEST_J\n");
  190. + usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
  191. + USB_REQ_SET_FEATURE, USB_RT_PORT,
  192. + USB_PORT_FEAT_TEST, 0x100, NULL, 0, HZ);
  193. + break;
  194. +
  195. + case 0x0103: /* TEST_K */
  196. + dev_warn(&dev->dev, "TEST_K\n");
  197. + usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
  198. + USB_REQ_SET_FEATURE, USB_RT_PORT,
  199. + USB_PORT_FEAT_TEST, 0x200, NULL, 0, HZ);
  200. + break;
  201. +
  202. + case 0x0104: /* TEST_PACKET */
  203. + dev_warn(&dev->dev, "TEST_PACKET\n");
  204. + usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
  205. + USB_REQ_SET_FEATURE, USB_RT_PORT,
  206. + USB_PORT_FEAT_TEST, 0x400, NULL, 0, HZ);
  207. + break;
  208. +
  209. + case 0x0105: /* TEST_FORCE_ENABLE */
  210. + dev_warn(&dev->dev, "TEST_FORCE_ENABLE\n");
  211. + usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
  212. + USB_REQ_SET_FEATURE, USB_RT_PORT,
  213. + USB_PORT_FEAT_TEST, 0x500, NULL, 0, HZ);
  214. + break;
  215. +
  216. + case 0x0106: /* HS_HOST_PORT_SUSPEND_RESUME */
  217. + dev_warn(&dev->dev, "HS_HOST_PORT_SUSPEND_RESUME\n");
  218. + usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
  219. + USB_REQ_SET_FEATURE, USB_RT_PORT,
  220. + USB_PORT_FEAT_TEST, 0x600, NULL, 0, 40 * HZ);
  221. + break;
  222. +
  223. + case 0x0107: /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
  224. + dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup\n");
  225. + usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
  226. + USB_REQ_SET_FEATURE, USB_RT_PORT,
  227. + USB_PORT_FEAT_TEST, 0x700, NULL, 0, 40 * HZ);
  228. + break;
  229. +
  230. + case 0x0108: /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
  231. + dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute\n");
  232. + usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
  233. + USB_REQ_SET_FEATURE, USB_RT_PORT,
  234. + USB_PORT_FEAT_TEST, 0x800, NULL, 0, 40 * HZ);
  235. + }
  236. + }
  237. + }
  238. +#endif /* DWC_HS_ELECT_TST */
  239. /* Now that the interfaces are installed, re-enable LPM. */
  240. usb_unlocked_enable_lpm(dev);
  241. --- a/drivers/usb/core/otg_whitelist.h
  242. +++ b/drivers/usb/core/otg_whitelist.h
  243. @@ -19,33 +19,82 @@
  244. static struct usb_device_id whitelist_table [] = {
  245. /* hubs are optional in OTG, but very handy ... */
  246. +#define CERT_WITHOUT_HUBS
  247. +#if defined(CERT_WITHOUT_HUBS)
  248. +{ USB_DEVICE( 0x0000, 0x0000 ), }, /* Root HUB Only*/
  249. +#else
  250. { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), },
  251. { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), },
  252. +{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 2), },
  253. +#endif
  254. #ifdef CONFIG_USB_PRINTER /* ignoring nonstatic linkage! */
  255. /* FIXME actually, printers are NOT supposed to use device classes;
  256. * they're supposed to use interface classes...
  257. */
  258. -{ USB_DEVICE_INFO(7, 1, 1) },
  259. -{ USB_DEVICE_INFO(7, 1, 2) },
  260. -{ USB_DEVICE_INFO(7, 1, 3) },
  261. +//{ USB_DEVICE_INFO(7, 1, 1) },
  262. +//{ USB_DEVICE_INFO(7, 1, 2) },
  263. +//{ USB_DEVICE_INFO(7, 1, 3) },
  264. #endif
  265. #ifdef CONFIG_USB_NET_CDCETHER
  266. /* Linux-USB CDC Ethernet gadget */
  267. -{ USB_DEVICE(0x0525, 0xa4a1), },
  268. +//{ USB_DEVICE(0x0525, 0xa4a1), },
  269. /* Linux-USB CDC Ethernet + RNDIS gadget */
  270. -{ USB_DEVICE(0x0525, 0xa4a2), },
  271. +//{ USB_DEVICE(0x0525, 0xa4a2), },
  272. #endif
  273. #if defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE)
  274. /* gadget zero, for testing */
  275. -{ USB_DEVICE(0x0525, 0xa4a0), },
  276. +//{ USB_DEVICE(0x0525, 0xa4a0), },
  277. #endif
  278. +/* OPT Tester */
  279. +{ USB_DEVICE( 0x1a0a, 0x0101 ), }, /* TEST_SE0_NAK */
  280. +{ USB_DEVICE( 0x1a0a, 0x0102 ), }, /* Test_J */
  281. +{ USB_DEVICE( 0x1a0a, 0x0103 ), }, /* Test_K */
  282. +{ USB_DEVICE( 0x1a0a, 0x0104 ), }, /* Test_PACKET */
  283. +{ USB_DEVICE( 0x1a0a, 0x0105 ), }, /* Test_FORCE_ENABLE */
  284. +{ USB_DEVICE( 0x1a0a, 0x0106 ), }, /* HS_PORT_SUSPEND_RESUME */
  285. +{ USB_DEVICE( 0x1a0a, 0x0107 ), }, /* SINGLE_STEP_GET_DESCRIPTOR setup */
  286. +{ USB_DEVICE( 0x1a0a, 0x0108 ), }, /* SINGLE_STEP_GET_DESCRIPTOR execute */
  287. +
  288. +/* Sony cameras */
  289. +{ USB_DEVICE_VER(0x054c,0x0010,0x0410, 0x0500), },
  290. +
  291. +/* Memory Devices */
  292. +//{ USB_DEVICE( 0x0781, 0x5150 ), }, /* SanDisk */
  293. +//{ USB_DEVICE( 0x05DC, 0x0080 ), }, /* Lexar */
  294. +//{ USB_DEVICE( 0x4146, 0x9281 ), }, /* IOMEGA */
  295. +//{ USB_DEVICE( 0x067b, 0x2507 ), }, /* Hammer 20GB External HD */
  296. +{ USB_DEVICE( 0x0EA0, 0x2168 ), }, /* Ours Technology Inc. (BUFFALO ClipDrive)*/
  297. +//{ USB_DEVICE( 0x0457, 0x0150 ), }, /* Silicon Integrated Systems Corp. */
  298. +
  299. +/* HP Printers */
  300. +//{ USB_DEVICE( 0x03F0, 0x1102 ), }, /* HP Photosmart 245 */
  301. +//{ USB_DEVICE( 0x03F0, 0x1302 ), }, /* HP Photosmart 370 Series */
  302. +
  303. +/* Speakers */
  304. +//{ USB_DEVICE( 0x0499, 0x3002 ), }, /* YAMAHA YST-MS35D USB Speakers */
  305. +//{ USB_DEVICE( 0x0672, 0x1041 ), }, /* Labtec USB Headset */
  306. +
  307. { } /* Terminating entry */
  308. };
  309. +static inline void report_errors(struct usb_device *dev)
  310. +{
  311. + /* OTG MESSAGE: report errors here, customize to match your product */
  312. + dev_info(&dev->dev, "device Vendor:%04x Product:%04x is not supported\n",
  313. + le16_to_cpu(dev->descriptor.idVendor),
  314. + le16_to_cpu(dev->descriptor.idProduct));
  315. + if (USB_CLASS_HUB == dev->descriptor.bDeviceClass){
  316. + dev_printk(KERN_CRIT, &dev->dev, "Unsupported Hub Topology\n");
  317. + } else {
  318. + dev_printk(KERN_CRIT, &dev->dev, "Attached Device is not Supported\n");
  319. + }
  320. +}
  321. +
  322. +
  323. static int is_targeted(struct usb_device *dev)
  324. {
  325. struct usb_device_id *id = whitelist_table;
  326. @@ -95,16 +144,57 @@ static int is_targeted(struct usb_device
  327. continue;
  328. return 1;
  329. - }
  330. + /* NOTE: can't use usb_match_id() since interface caches
  331. + * aren't set up yet. this is cut/paste from that code.
  332. + */
  333. + for (id = whitelist_table; id->match_flags; id++) {
  334. +#ifdef DEBUG
  335. + dev_dbg(&dev->dev,
  336. + "ID: V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n",
  337. + id->idVendor,
  338. + id->idProduct,
  339. + id->bDeviceClass,
  340. + id->bDeviceSubClass,
  341. + id->bDeviceProtocol);
  342. +#endif
  343. - /* add other match criteria here ... */
  344. + if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
  345. + id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
  346. + continue;
  347. +
  348. + if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
  349. + id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
  350. + continue;
  351. +
  352. + /* No need to test id->bcdDevice_lo != 0, since 0 is never
  353. + greater than any unsigned number. */
  354. + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
  355. + (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
  356. + continue;
  357. +
  358. + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
  359. + (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
  360. + continue;
  361. +
  362. + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
  363. + (id->bDeviceClass != dev->descriptor.bDeviceClass))
  364. + continue;
  365. +
  366. + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
  367. + (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
  368. + continue;
  369. +
  370. + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
  371. + (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
  372. + continue;
  373. + return 1;
  374. + }
  375. + }
  376. - /* OTG MESSAGE: report errors here, customize to match your product */
  377. - dev_err(&dev->dev, "device v%04x p%04x is not supported\n",
  378. - le16_to_cpu(dev->descriptor.idVendor),
  379. - le16_to_cpu(dev->descriptor.idProduct));
  380. + /* add other match criteria here ... */
  381. + report_errors(dev);
  382. return 0;
  383. }
  384. --- /dev/null
  385. +++ b/drivers/usb/gadget/file_storage.c
  386. @@ -0,0 +1,3676 @@
  387. +/*
  388. + * file_storage.c -- File-backed USB Storage Gadget, for USB development
  389. + *
  390. + * Copyright (C) 2003-2008 Alan Stern
  391. + * All rights reserved.
  392. + *
  393. + * Redistribution and use in source and binary forms, with or without
  394. + * modification, are permitted provided that the following conditions
  395. + * are met:
  396. + * 1. Redistributions of source code must retain the above copyright
  397. + * notice, this list of conditions, and the following disclaimer,
  398. + * without modification.
  399. + * 2. Redistributions in binary form must reproduce the above copyright
  400. + * notice, this list of conditions and the following disclaimer in the
  401. + * documentation and/or other materials provided with the distribution.
  402. + * 3. The names of the above-listed copyright holders may not be used
  403. + * to endorse or promote products derived from this software without
  404. + * specific prior written permission.
  405. + *
  406. + * ALTERNATIVELY, this software may be distributed under the terms of the
  407. + * GNU General Public License ("GPL") as published by the Free Software
  408. + * Foundation, either version 2 of that License or (at your option) any
  409. + * later version.
  410. + *
  411. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  412. + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  413. + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  414. + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  415. + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  416. + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  417. + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  418. + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  419. + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  420. + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  421. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  422. + */
  423. +
  424. +
  425. +/*
  426. + * The File-backed Storage Gadget acts as a USB Mass Storage device,
  427. + * appearing to the host as a disk drive or as a CD-ROM drive. In addition
  428. + * to providing an example of a genuinely useful gadget driver for a USB
  429. + * device, it also illustrates a technique of double-buffering for increased
  430. + * throughput. Last but not least, it gives an easy way to probe the
  431. + * behavior of the Mass Storage drivers in a USB host.
  432. + *
  433. + * Backing storage is provided by a regular file or a block device, specified
  434. + * by the "file" module parameter. Access can be limited to read-only by
  435. + * setting the optional "ro" module parameter. (For CD-ROM emulation,
  436. + * access is always read-only.) The gadget will indicate that it has
  437. + * removable media if the optional "removable" module parameter is set.
  438. + *
  439. + * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),
  440. + * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected
  441. + * by the optional "transport" module parameter. It also supports the
  442. + * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03),
  443. + * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by
  444. + * the optional "protocol" module parameter. In addition, the default
  445. + * Vendor ID, Product ID, release number and serial number can be overridden.
  446. + *
  447. + * There is support for multiple logical units (LUNs), each of which has
  448. + * its own backing file. The number of LUNs can be set using the optional
  449. + * "luns" module parameter (anywhere from 1 to 8), and the corresponding
  450. + * files are specified using comma-separated lists for "file" and "ro".
  451. + * The default number of LUNs is taken from the number of "file" elements;
  452. + * it is 1 if "file" is not given. If "removable" is not set then a backing
  453. + * file must be specified for each LUN. If it is set, then an unspecified
  454. + * or empty backing filename means the LUN's medium is not loaded. Ideally
  455. + * each LUN would be settable independently as a disk drive or a CD-ROM
  456. + * drive, but currently all LUNs have to be the same type. The CD-ROM
  457. + * emulation includes a single data track and no audio tracks; hence there
  458. + * need be only one backing file per LUN.
  459. + *
  460. + * Requirements are modest; only a bulk-in and a bulk-out endpoint are
  461. + * needed (an interrupt-out endpoint is also needed for CBI). The memory
  462. + * requirement amounts to two 16K buffers, size configurable by a parameter.
  463. + * Support is included for both full-speed and high-speed operation.
  464. + *
  465. + * Note that the driver is slightly non-portable in that it assumes a
  466. + * single memory/DMA buffer will be useable for bulk-in, bulk-out, and
  467. + * interrupt-in endpoints. With most device controllers this isn't an
  468. + * issue, but there may be some with hardware restrictions that prevent
  469. + * a buffer from being used by more than one endpoint.
  470. + *
  471. + * Module options:
  472. + *
  473. + * file=filename[,filename...]
  474. + * Required if "removable" is not set, names of
  475. + * the files or block devices used for
  476. + * backing storage
  477. + * serial=HHHH... Required serial number (string of hex chars)
  478. + * ro=b[,b...] Default false, booleans for read-only access
  479. + * removable Default false, boolean for removable media
  480. + * luns=N Default N = number of filenames, number of
  481. + * LUNs to support
  482. + * nofua=b[,b...] Default false, booleans for ignore FUA flag
  483. + * in SCSI WRITE(10,12) commands
  484. + * stall Default determined according to the type of
  485. + * USB device controller (usually true),
  486. + * boolean to permit the driver to halt
  487. + * bulk endpoints
  488. + * cdrom Default false, boolean for whether to emulate
  489. + * a CD-ROM drive
  490. + * transport=XXX Default BBB, transport name (CB, CBI, or BBB)
  491. + * protocol=YYY Default SCSI, protocol name (RBC, 8020 or
  492. + * ATAPI, QIC, UFI, 8070, or SCSI;
  493. + * also 1 - 6)
  494. + * vendor=0xVVVV Default 0x0525 (NetChip), USB Vendor ID
  495. + * product=0xPPPP Default 0xa4a5 (FSG), USB Product ID
  496. + * release=0xRRRR Override the USB release number (bcdDevice)
  497. + * buflen=N Default N=16384, buffer size used (will be
  498. + * rounded down to a multiple of
  499. + * PAGE_CACHE_SIZE)
  500. + *
  501. + * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro",
  502. + * "removable", "luns", "nofua", "stall", and "cdrom" options are available;
  503. + * default values are used for everything else.
  504. + *
  505. + * The pathnames of the backing files and the ro settings are available in
  506. + * the attribute files "file", "nofua", and "ro" in the lun<n> subdirectory of
  507. + * the gadget's sysfs directory. If the "removable" option is set, writing to
  508. + * these files will simulate ejecting/loading the medium (writing an empty
  509. + * line means eject) and adjusting a write-enable tab. Changes to the ro
  510. + * setting are not allowed when the medium is loaded or if CD-ROM emulation
  511. + * is being used.
  512. + *
  513. + * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
  514. + * The driver's SCSI command interface was based on the "Information
  515. + * technology - Small Computer System Interface - 2" document from
  516. + * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at
  517. + * <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>. The single exception
  518. + * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the
  519. + * "Universal Serial Bus Mass Storage Class UFI Command Specification"
  520. + * document, Revision 1.0, December 14, 1998, available at
  521. + * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>.
  522. + */
  523. +
  524. +
  525. +/*
  526. + * Driver Design
  527. + *
  528. + * The FSG driver is fairly straightforward. There is a main kernel
  529. + * thread that handles most of the work. Interrupt routines field
  530. + * callbacks from the controller driver: bulk- and interrupt-request
  531. + * completion notifications, endpoint-0 events, and disconnect events.
  532. + * Completion events are passed to the main thread by wakeup calls. Many
  533. + * ep0 requests are handled at interrupt time, but SetInterface,
  534. + * SetConfiguration, and device reset requests are forwarded to the
  535. + * thread in the form of "exceptions" using SIGUSR1 signals (since they
  536. + * should interrupt any ongoing file I/O operations).
  537. + *
  538. + * The thread's main routine implements the standard command/data/status
  539. + * parts of a SCSI interaction. It and its subroutines are full of tests
  540. + * for pending signals/exceptions -- all this polling is necessary since
  541. + * the kernel has no setjmp/longjmp equivalents. (Maybe this is an
  542. + * indication that the driver really wants to be running in userspace.)
  543. + * An important point is that so long as the thread is alive it keeps an
  544. + * open reference to the backing file. This will prevent unmounting
  545. + * the backing file's underlying filesystem and could cause problems
  546. + * during system shutdown, for example. To prevent such problems, the
  547. + * thread catches INT, TERM, and KILL signals and converts them into
  548. + * an EXIT exception.
  549. + *
  550. + * In normal operation the main thread is started during the gadget's
  551. + * fsg_bind() callback and stopped during fsg_unbind(). But it can also
  552. + * exit when it receives a signal, and there's no point leaving the
  553. + * gadget running when the thread is dead. So just before the thread
  554. + * exits, it deregisters the gadget driver. This makes things a little
  555. + * tricky: The driver is deregistered at two places, and the exiting
  556. + * thread can indirectly call fsg_unbind() which in turn can tell the
  557. + * thread to exit. The first problem is resolved through the use of the
  558. + * REGISTERED atomic bitflag; the driver will only be deregistered once.
  559. + * The second problem is resolved by having fsg_unbind() check
  560. + * fsg->state; it won't try to stop the thread if the state is already
  561. + * FSG_STATE_TERMINATED.
  562. + *
  563. + * To provide maximum throughput, the driver uses a circular pipeline of
  564. + * buffer heads (struct fsg_buffhd). In principle the pipeline can be
  565. + * arbitrarily long; in practice the benefits don't justify having more
  566. + * than 2 stages (i.e., double buffering). But it helps to think of the
  567. + * pipeline as being a long one. Each buffer head contains a bulk-in and
  568. + * a bulk-out request pointer (since the buffer can be used for both
  569. + * output and input -- directions always are given from the host's
  570. + * point of view) as well as a pointer to the buffer and various state
  571. + * variables.
  572. + *
  573. + * Use of the pipeline follows a simple protocol. There is a variable
  574. + * (fsg->next_buffhd_to_fill) that points to the next buffer head to use.
  575. + * At any time that buffer head may still be in use from an earlier
  576. + * request, so each buffer head has a state variable indicating whether
  577. + * it is EMPTY, FULL, or BUSY. Typical use involves waiting for the
  578. + * buffer head to be EMPTY, filling the buffer either by file I/O or by
  579. + * USB I/O (during which the buffer head is BUSY), and marking the buffer
  580. + * head FULL when the I/O is complete. Then the buffer will be emptied
  581. + * (again possibly by USB I/O, during which it is marked BUSY) and
  582. + * finally marked EMPTY again (possibly by a completion routine).
  583. + *
  584. + * A module parameter tells the driver to avoid stalling the bulk
  585. + * endpoints wherever the transport specification allows. This is
  586. + * necessary for some UDCs like the SuperH, which cannot reliably clear a
  587. + * halt on a bulk endpoint. However, under certain circumstances the
  588. + * Bulk-only specification requires a stall. In such cases the driver
  589. + * will halt the endpoint and set a flag indicating that it should clear
  590. + * the halt in software during the next device reset. Hopefully this
  591. + * will permit everything to work correctly. Furthermore, although the
  592. + * specification allows the bulk-out endpoint to halt when the host sends
  593. + * too much data, implementing this would cause an unavoidable race.
  594. + * The driver will always use the "no-stall" approach for OUT transfers.
  595. + *
  596. + * One subtle point concerns sending status-stage responses for ep0
  597. + * requests. Some of these requests, such as device reset, can involve
  598. + * interrupting an ongoing file I/O operation, which might take an
  599. + * arbitrarily long time. During that delay the host might give up on
  600. + * the original ep0 request and issue a new one. When that happens the
  601. + * driver should not notify the host about completion of the original
  602. + * request, as the host will no longer be waiting for it. So the driver
  603. + * assigns to each ep0 request a unique tag, and it keeps track of the
  604. + * tag value of the request associated with a long-running exception
  605. + * (device-reset, interface-change, or configuration-change). When the
  606. + * exception handler is finished, the status-stage response is submitted
  607. + * only if the current ep0 request tag is equal to the exception request
  608. + * tag. Thus only the most recently received ep0 request will get a
  609. + * status-stage response.
  610. + *
  611. + * Warning: This driver source file is too long. It ought to be split up
  612. + * into a header file plus about 3 separate .c files, to handle the details
  613. + * of the Gadget, USB Mass Storage, and SCSI protocols.
  614. + */
  615. +
  616. +
  617. +/* #define VERBOSE_DEBUG */
  618. +/* #define DUMP_MSGS */
  619. +
  620. +
  621. +#include <linux/blkdev.h>
  622. +#include <linux/completion.h>
  623. +#include <linux/dcache.h>
  624. +#include <linux/delay.h>
  625. +#include <linux/device.h>
  626. +#include <linux/fcntl.h>
  627. +#include <linux/file.h>
  628. +#include <linux/fs.h>
  629. +#include <linux/kref.h>
  630. +#include <linux/kthread.h>
  631. +#include <linux/limits.h>
  632. +#include <linux/module.h>
  633. +#include <linux/rwsem.h>
  634. +#include <linux/slab.h>
  635. +#include <linux/spinlock.h>
  636. +#include <linux/string.h>
  637. +#include <linux/freezer.h>
  638. +#include <linux/utsname.h>
  639. +
  640. +#include <linux/usb/ch9.h>
  641. +#include <linux/usb/gadget.h>
  642. +
  643. +#include "gadget_chips.h"
  644. +
  645. +
  646. +
  647. +/*
  648. + * Kbuild is not very cooperative with respect to linking separately
  649. + * compiled library objects into one module. So for now we won't use
  650. + * separate compilation ... ensuring init/exit sections work to shrink
  651. + * the runtime footprint, and giving us at least some parts of what
  652. + * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  653. + */
  654. +#include "usbstring.c"
  655. +#include "config.c"
  656. +#include "epautoconf.c"
  657. +
  658. +/*-------------------------------------------------------------------------*/
  659. +
  660. +#define DRIVER_DESC "File-backed Storage Gadget"
  661. +#define DRIVER_NAME "g_file_storage"
  662. +#define DRIVER_VERSION "1 September 2010"
  663. +
  664. +static char fsg_string_manufacturer[64];
  665. +static const char fsg_string_product[] = DRIVER_DESC;
  666. +static const char fsg_string_config[] = "Self-powered";
  667. +static const char fsg_string_interface[] = "Mass Storage";
  668. +
  669. +
  670. +#include "storage_common.c"
  671. +
  672. +
  673. +MODULE_DESCRIPTION(DRIVER_DESC);
  674. +MODULE_AUTHOR("Alan Stern");
  675. +MODULE_LICENSE("Dual BSD/GPL");
  676. +
  677. +/*
  678. + * This driver assumes self-powered hardware and has no way for users to
  679. + * trigger remote wakeup. It uses autoconfiguration to select endpoints
  680. + * and endpoint addresses.
  681. + */
  682. +
  683. +
  684. +/*-------------------------------------------------------------------------*/
  685. +
  686. +
  687. +/* Encapsulate the module parameter settings */
  688. +
  689. +static struct {
  690. + char *file[FSG_MAX_LUNS];
  691. + char *serial;
  692. + bool ro[FSG_MAX_LUNS];
  693. + bool nofua[FSG_MAX_LUNS];
  694. + unsigned int num_filenames;
  695. + unsigned int num_ros;
  696. + unsigned int num_nofuas;
  697. + unsigned int nluns;
  698. +
  699. + bool removable;
  700. + bool can_stall;
  701. + bool cdrom;
  702. +
  703. + char *transport_parm;
  704. + char *protocol_parm;
  705. + unsigned short vendor;
  706. + unsigned short product;
  707. + unsigned short release;
  708. + unsigned int buflen;
  709. +
  710. + int transport_type;
  711. + char *transport_name;
  712. + int protocol_type;
  713. + char *protocol_name;
  714. +
  715. +} mod_data = { // Default values
  716. + .transport_parm = "BBB",
  717. + .protocol_parm = "SCSI",
  718. + .removable = 0,
  719. + .can_stall = 1,
  720. + .cdrom = 0,
  721. + .vendor = FSG_VENDOR_ID,
  722. + .product = FSG_PRODUCT_ID,
  723. + .release = 0xffff, // Use controller chip type
  724. + .buflen = 16384,
  725. + };
  726. +
  727. +
  728. +module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames,
  729. + S_IRUGO);
  730. +MODULE_PARM_DESC(file, "names of backing files or devices");
  731. +
  732. +module_param_named(serial, mod_data.serial, charp, S_IRUGO);
  733. +MODULE_PARM_DESC(serial, "USB serial number");
  734. +
  735. +module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO);
  736. +MODULE_PARM_DESC(ro, "true to force read-only");
  737. +
  738. +module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas,
  739. + S_IRUGO);
  740. +MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit");
  741. +
  742. +module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
  743. +MODULE_PARM_DESC(luns, "number of LUNs");
  744. +
  745. +module_param_named(removable, mod_data.removable, bool, S_IRUGO);
  746. +MODULE_PARM_DESC(removable, "true to simulate removable media");
  747. +
  748. +module_param_named(stall, mod_data.can_stall, bool, S_IRUGO);
  749. +MODULE_PARM_DESC(stall, "false to prevent bulk stalls");
  750. +
  751. +module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO);
  752. +MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk");
  753. +
  754. +/* In the non-TEST version, only the module parameters listed above
  755. + * are available. */
  756. +#ifdef CONFIG_USB_FILE_STORAGE_TEST
  757. +
  758. +module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO);
  759. +MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)");
  760. +
  761. +module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO);
  762. +MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, "
  763. + "8070, or SCSI)");
  764. +
  765. +module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO);
  766. +MODULE_PARM_DESC(vendor, "USB Vendor ID");
  767. +
  768. +module_param_named(product, mod_data.product, ushort, S_IRUGO);
  769. +MODULE_PARM_DESC(product, "USB Product ID");
  770. +
  771. +module_param_named(release, mod_data.release, ushort, S_IRUGO);
  772. +MODULE_PARM_DESC(release, "USB release number");
  773. +
  774. +module_param_named(buflen, mod_data.buflen, uint, S_IRUGO);
  775. +MODULE_PARM_DESC(buflen, "I/O buffer size");
  776. +
  777. +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
  778. +
  779. +
  780. +/*
  781. + * These definitions will permit the compiler to avoid generating code for
  782. + * parts of the driver that aren't used in the non-TEST version. Even gcc
  783. + * can recognize when a test of a constant expression yields a dead code
  784. + * path.
  785. + */
  786. +
  787. +#ifdef CONFIG_USB_FILE_STORAGE_TEST
  788. +
  789. +#define transport_is_bbb() (mod_data.transport_type == USB_PR_BULK)
  790. +#define transport_is_cbi() (mod_data.transport_type == USB_PR_CBI)
  791. +#define protocol_is_scsi() (mod_data.protocol_type == USB_SC_SCSI)
  792. +
  793. +#else
  794. +
  795. +#define transport_is_bbb() 1
  796. +#define transport_is_cbi() 0
  797. +#define protocol_is_scsi() 1
  798. +
  799. +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
  800. +
  801. +
  802. +/*-------------------------------------------------------------------------*/
  803. +
  804. +
  805. +struct fsg_dev {
  806. + /* lock protects: state, all the req_busy's, and cbbuf_cmnd */
  807. + spinlock_t lock;
  808. + struct usb_gadget *gadget;
  809. +
  810. + /* filesem protects: backing files in use */
  811. + struct rw_semaphore filesem;
  812. +
  813. + /* reference counting: wait until all LUNs are released */
  814. + struct kref ref;
  815. +
  816. + struct usb_ep *ep0; // Handy copy of gadget->ep0
  817. + struct usb_request *ep0req; // For control responses
  818. + unsigned int ep0_req_tag;
  819. + const char *ep0req_name;
  820. +
  821. + struct usb_request *intreq; // For interrupt responses
  822. + int intreq_busy;
  823. + struct fsg_buffhd *intr_buffhd;
  824. +
  825. + unsigned int bulk_out_maxpacket;
  826. + enum fsg_state state; // For exception handling
  827. + unsigned int exception_req_tag;
  828. +
  829. + u8 config, new_config;
  830. +
  831. + unsigned int running : 1;
  832. + unsigned int bulk_in_enabled : 1;
  833. + unsigned int bulk_out_enabled : 1;
  834. + unsigned int intr_in_enabled : 1;
  835. + unsigned int phase_error : 1;
  836. + unsigned int short_packet_received : 1;
  837. + unsigned int bad_lun_okay : 1;
  838. +
  839. + unsigned long atomic_bitflags;
  840. +#define REGISTERED 0
  841. +#define IGNORE_BULK_OUT 1
  842. +#define SUSPENDED 2
  843. +
  844. + struct usb_ep *bulk_in;
  845. + struct usb_ep *bulk_out;
  846. + struct usb_ep *intr_in;
  847. +
  848. + struct fsg_buffhd *next_buffhd_to_fill;
  849. + struct fsg_buffhd *next_buffhd_to_drain;
  850. +
  851. + int thread_wakeup_needed;
  852. + struct completion thread_notifier;
  853. + struct task_struct *thread_task;
  854. +
  855. + int cmnd_size;
  856. + u8 cmnd[MAX_COMMAND_SIZE];
  857. + enum data_direction data_dir;
  858. + u32 data_size;
  859. + u32 data_size_from_cmnd;
  860. + u32 tag;
  861. + unsigned int lun;
  862. + u32 residue;
  863. + u32 usb_amount_left;
  864. +
  865. + /* The CB protocol offers no way for a host to know when a command
  866. + * has completed. As a result the next command may arrive early,
  867. + * and we will still have to handle it. For that reason we need
  868. + * a buffer to store new commands when using CB (or CBI, which
  869. + * does not oblige a host to wait for command completion either). */
  870. + int cbbuf_cmnd_size;
  871. + u8 cbbuf_cmnd[MAX_COMMAND_SIZE];
  872. +
  873. + unsigned int nluns;
  874. + struct fsg_lun *luns;
  875. + struct fsg_lun *curlun;
  876. + /* Must be the last entry */
  877. + struct fsg_buffhd buffhds[];
  878. +};
  879. +
  880. +typedef void (*fsg_routine_t)(struct fsg_dev *);
  881. +
  882. +static int exception_in_progress(struct fsg_dev *fsg)
  883. +{
  884. + return (fsg->state > FSG_STATE_IDLE);
  885. +}
  886. +
  887. +/* Make bulk-out requests be divisible by the maxpacket size */
  888. +static void set_bulk_out_req_length(struct fsg_dev *fsg,
  889. + struct fsg_buffhd *bh, unsigned int length)
  890. +{
  891. + unsigned int rem;
  892. +
  893. + bh->bulk_out_intended_length = length;
  894. + rem = length % fsg->bulk_out_maxpacket;
  895. + if (rem > 0)
  896. + length += fsg->bulk_out_maxpacket - rem;
  897. + bh->outreq->length = length;
  898. +}
  899. +
  900. +static struct fsg_dev *the_fsg;
  901. +static struct usb_gadget_driver fsg_driver;
  902. +
  903. +
  904. +/*-------------------------------------------------------------------------*/
  905. +
  906. +static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
  907. +{
  908. + const char *name;
  909. +
  910. + if (ep == fsg->bulk_in)
  911. + name = "bulk-in";
  912. + else if (ep == fsg->bulk_out)
  913. + name = "bulk-out";
  914. + else
  915. + name = ep->name;
  916. + DBG(fsg, "%s set halt\n", name);
  917. + return usb_ep_set_halt(ep);
  918. +}
  919. +
  920. +
  921. +/*-------------------------------------------------------------------------*/
  922. +
  923. +/*
  924. + * DESCRIPTORS ... most are static, but strings and (full) configuration
  925. + * descriptors are built on demand. Also the (static) config and interface
  926. + * descriptors are adjusted during fsg_bind().
  927. + */
  928. +
  929. +/* There is only one configuration. */
  930. +#define CONFIG_VALUE 1
  931. +
  932. +static struct usb_device_descriptor
  933. +device_desc = {
  934. + .bLength = sizeof device_desc,
  935. + .bDescriptorType = USB_DT_DEVICE,
  936. +
  937. + .bcdUSB = cpu_to_le16(0x0200),
  938. + .bDeviceClass = USB_CLASS_PER_INTERFACE,
  939. +
  940. + /* The next three values can be overridden by module parameters */
  941. + .idVendor = cpu_to_le16(FSG_VENDOR_ID),
  942. + .idProduct = cpu_to_le16(FSG_PRODUCT_ID),
  943. + .bcdDevice = cpu_to_le16(0xffff),
  944. +
  945. + .iManufacturer = FSG_STRING_MANUFACTURER,
  946. + .iProduct = FSG_STRING_PRODUCT,
  947. + .iSerialNumber = FSG_STRING_SERIAL,
  948. + .bNumConfigurations = 1,
  949. +};
  950. +
  951. +static struct usb_config_descriptor
  952. +config_desc = {
  953. + .bLength = sizeof config_desc,
  954. + .bDescriptorType = USB_DT_CONFIG,
  955. +
  956. + /* wTotalLength computed by usb_gadget_config_buf() */
  957. + .bNumInterfaces = 1,
  958. + .bConfigurationValue = CONFIG_VALUE,
  959. + .iConfiguration = FSG_STRING_CONFIG,
  960. + .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
  961. + .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2,
  962. +};
  963. +
  964. +
  965. +static struct usb_qualifier_descriptor
  966. +dev_qualifier = {
  967. + .bLength = sizeof dev_qualifier,
  968. + .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
  969. +
  970. + .bcdUSB = cpu_to_le16(0x0200),
  971. + .bDeviceClass = USB_CLASS_PER_INTERFACE,
  972. +
  973. + .bNumConfigurations = 1,
  974. +};
  975. +
  976. +static int populate_bos(struct fsg_dev *fsg, u8 *buf)
  977. +{
  978. + memcpy(buf, &fsg_bos_desc, USB_DT_BOS_SIZE);
  979. + buf += USB_DT_BOS_SIZE;
  980. +
  981. + memcpy(buf, &fsg_ext_cap_desc, USB_DT_USB_EXT_CAP_SIZE);
  982. + buf += USB_DT_USB_EXT_CAP_SIZE;
  983. +
  984. + memcpy(buf, &fsg_ss_cap_desc, USB_DT_USB_SS_CAP_SIZE);
  985. +
  986. + return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE
  987. + + USB_DT_USB_EXT_CAP_SIZE;
  988. +}
  989. +
  990. +/*
  991. + * Config descriptors must agree with the code that sets configurations
  992. + * and with code managing interfaces and their altsettings. They must
  993. + * also handle different speeds and other-speed requests.
  994. + */
  995. +static int populate_config_buf(struct usb_gadget *gadget,
  996. + u8 *buf, u8 type, unsigned index)
  997. +{
  998. + enum usb_device_speed speed = gadget->speed;
  999. + int len;
  1000. + const struct usb_descriptor_header **function;
  1001. +
  1002. + if (index > 0)
  1003. + return -EINVAL;
  1004. +
  1005. + if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG)
  1006. + speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed;
  1007. + function = gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH
  1008. + ? (const struct usb_descriptor_header **)fsg_hs_function
  1009. + : (const struct usb_descriptor_header **)fsg_fs_function;
  1010. +
  1011. + /* for now, don't advertise srp-only devices */
  1012. + if (!gadget_is_otg(gadget))
  1013. + function++;
  1014. +
  1015. + len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);
  1016. + ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
  1017. + return len;
  1018. +}
  1019. +
  1020. +
  1021. +/*-------------------------------------------------------------------------*/
  1022. +
  1023. +/* These routines may be called in process context or in_irq */
  1024. +
  1025. +/* Caller must hold fsg->lock */
  1026. +static void wakeup_thread(struct fsg_dev *fsg)
  1027. +{
  1028. + /* Tell the main thread that something has happened */
  1029. + fsg->thread_wakeup_needed = 1;
  1030. + if (fsg->thread_task)
  1031. + wake_up_process(fsg->thread_task);
  1032. +}
  1033. +
  1034. +
  1035. +static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state)
  1036. +{
  1037. + unsigned long flags;
  1038. +
  1039. + /* Do nothing if a higher-priority exception is already in progress.
  1040. + * If a lower-or-equal priority exception is in progress, preempt it
  1041. + * and notify the main thread by sending it a signal. */
  1042. + spin_lock_irqsave(&fsg->lock, flags);
  1043. + if (fsg->state <= new_state) {
  1044. + fsg->exception_req_tag = fsg->ep0_req_tag;
  1045. + fsg->state = new_state;
  1046. + if (fsg->thread_task)
  1047. + send_sig_info(SIGUSR1, SEND_SIG_FORCED,
  1048. + fsg->thread_task);
  1049. + }
  1050. + spin_unlock_irqrestore(&fsg->lock, flags);
  1051. +}
  1052. +
  1053. +
  1054. +/*-------------------------------------------------------------------------*/
  1055. +
  1056. +/* The disconnect callback and ep0 routines. These always run in_irq,
  1057. + * except that ep0_queue() is called in the main thread to acknowledge
  1058. + * completion of various requests: set config, set interface, and
  1059. + * Bulk-only device reset. */
  1060. +
  1061. +static void fsg_disconnect(struct usb_gadget *gadget)
  1062. +{
  1063. + struct fsg_dev *fsg = get_gadget_data(gadget);
  1064. +
  1065. + DBG(fsg, "disconnect or port reset\n");
  1066. + raise_exception(fsg, FSG_STATE_DISCONNECT);
  1067. +}
  1068. +
  1069. +
  1070. +static int ep0_queue(struct fsg_dev *fsg)
  1071. +{
  1072. + int rc;
  1073. +
  1074. + rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC);
  1075. + if (rc != 0 && rc != -ESHUTDOWN) {
  1076. +
  1077. + /* We can't do much more than wait for a reset */
  1078. + WARNING(fsg, "error in submission: %s --> %d\n",
  1079. + fsg->ep0->name, rc);
  1080. + }
  1081. + return rc;
  1082. +}
  1083. +
  1084. +static void ep0_complete(struct usb_ep *ep, struct usb_request *req)
  1085. +{
  1086. + struct fsg_dev *fsg = ep->driver_data;
  1087. +
  1088. + if (req->actual > 0)
  1089. + dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual);
  1090. + if (req->status || req->actual != req->length)
  1091. + DBG(fsg, "%s --> %d, %u/%u\n", __func__,
  1092. + req->status, req->actual, req->length);
  1093. + if (req->status == -ECONNRESET) // Request was cancelled
  1094. + usb_ep_fifo_flush(ep);
  1095. +
  1096. + if (req->status == 0 && req->context)
  1097. + ((fsg_routine_t) (req->context))(fsg);
  1098. +}
  1099. +
  1100. +
  1101. +/*-------------------------------------------------------------------------*/
  1102. +
  1103. +/* Bulk and interrupt endpoint completion handlers.
  1104. + * These always run in_irq. */
  1105. +
  1106. +static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
  1107. +{
  1108. + struct fsg_dev *fsg = ep->driver_data;
  1109. + struct fsg_buffhd *bh = req->context;
  1110. +
  1111. + if (req->status || req->actual != req->length)
  1112. + DBG(fsg, "%s --> %d, %u/%u\n", __func__,
  1113. + req->status, req->actual, req->length);
  1114. + if (req->status == -ECONNRESET) // Request was cancelled
  1115. + usb_ep_fifo_flush(ep);
  1116. +
  1117. + /* Hold the lock while we update the request and buffer states */
  1118. + smp_wmb();
  1119. + spin_lock(&fsg->lock);
  1120. + bh->inreq_busy = 0;
  1121. + bh->state = BUF_STATE_EMPTY;
  1122. + wakeup_thread(fsg);
  1123. + spin_unlock(&fsg->lock);
  1124. +}
  1125. +
  1126. +static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
  1127. +{
  1128. + struct fsg_dev *fsg = ep->driver_data;
  1129. + struct fsg_buffhd *bh = req->context;
  1130. +
  1131. + dump_msg(fsg, "bulk-out", req->buf, req->actual);
  1132. + if (req->status || req->actual != bh->bulk_out_intended_length)
  1133. + DBG(fsg, "%s --> %d, %u/%u\n", __func__,
  1134. + req->status, req->actual,
  1135. + bh->bulk_out_intended_length);
  1136. + if (req->status == -ECONNRESET) // Request was cancelled
  1137. + usb_ep_fifo_flush(ep);
  1138. +
  1139. + /* Hold the lock while we update the request and buffer states */
  1140. + smp_wmb();
  1141. + spin_lock(&fsg->lock);
  1142. + bh->outreq_busy = 0;
  1143. + bh->state = BUF_STATE_FULL;
  1144. + wakeup_thread(fsg);
  1145. + spin_unlock(&fsg->lock);
  1146. +}
  1147. +
  1148. +
  1149. +#ifdef CONFIG_USB_FILE_STORAGE_TEST
  1150. +static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
  1151. +{
  1152. + struct fsg_dev *fsg = ep->driver_data;
  1153. + struct fsg_buffhd *bh = req->context;
  1154. +
  1155. + if (req->status || req->actual != req->length)
  1156. + DBG(fsg, "%s --> %d, %u/%u\n", __func__,
  1157. + req->status, req->actual, req->length);
  1158. + if (req->status == -ECONNRESET) // Request was cancelled
  1159. + usb_ep_fifo_flush(ep);
  1160. +
  1161. + /* Hold the lock while we update the request and buffer states */
  1162. + smp_wmb();
  1163. + spin_lock(&fsg->lock);
  1164. + fsg->intreq_busy = 0;
  1165. + bh->state = BUF_STATE_EMPTY;
  1166. + wakeup_thread(fsg);
  1167. + spin_unlock(&fsg->lock);
  1168. +}
  1169. +
  1170. +#else
  1171. +static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
  1172. +{}
  1173. +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
  1174. +
  1175. +
  1176. +/*-------------------------------------------------------------------------*/
  1177. +
  1178. +/* Ep0 class-specific handlers. These always run in_irq. */
  1179. +
  1180. +#ifdef CONFIG_USB_FILE_STORAGE_TEST
  1181. +static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
  1182. +{
  1183. + struct usb_request *req = fsg->ep0req;
  1184. + static u8 cbi_reset_cmnd[6] = {
  1185. + SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
  1186. +
  1187. + /* Error in command transfer? */
  1188. + if (req->status || req->length != req->actual ||
  1189. + req->actual < 6 || req->actual > MAX_COMMAND_SIZE) {
  1190. +
  1191. + /* Not all controllers allow a protocol stall after
  1192. + * receiving control-out data, but we'll try anyway. */
  1193. + fsg_set_halt(fsg, fsg->ep0);
  1194. + return; // Wait for reset
  1195. + }
  1196. +
  1197. + /* Is it the special reset command? */
  1198. + if (req->actual >= sizeof cbi_reset_cmnd &&
  1199. + memcmp(req->buf, cbi_reset_cmnd,
  1200. + sizeof cbi_reset_cmnd) == 0) {
  1201. +
  1202. + /* Raise an exception to stop the current operation
  1203. + * and reinitialize our state. */
  1204. + DBG(fsg, "cbi reset request\n");
  1205. + raise_exception(fsg, FSG_STATE_RESET);
  1206. + return;
  1207. + }
  1208. +
  1209. + VDBG(fsg, "CB[I] accept device-specific command\n");
  1210. + spin_lock(&fsg->lock);
  1211. +
  1212. + /* Save the command for later */
  1213. + if (fsg->cbbuf_cmnd_size)
  1214. + WARNING(fsg, "CB[I] overwriting previous command\n");
  1215. + fsg->cbbuf_cmnd_size = req->actual;
  1216. + memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
  1217. +
  1218. + wakeup_thread(fsg);
  1219. + spin_unlock(&fsg->lock);
  1220. +}
  1221. +
  1222. +#else
  1223. +static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
  1224. +{}
  1225. +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
  1226. +
  1227. +
  1228. +static int class_setup_req(struct fsg_dev *fsg,
  1229. + const struct usb_ctrlrequest *ctrl)
  1230. +{
  1231. + struct usb_request *req = fsg->ep0req;
  1232. + int value = -EOPNOTSUPP;
  1233. + u16 w_index = le16_to_cpu(ctrl->wIndex);
  1234. + u16 w_value = le16_to_cpu(ctrl->wValue);
  1235. + u16 w_length = le16_to_cpu(ctrl->wLength);
  1236. +
  1237. + if (!fsg->config)
  1238. + return value;
  1239. +
  1240. + /* Handle Bulk-only class-specific requests */
  1241. + if (transport_is_bbb()) {
  1242. + switch (ctrl->bRequest) {
  1243. +
  1244. + case US_BULK_RESET_REQUEST:
  1245. + if (ctrl->bRequestType != (USB_DIR_OUT |
  1246. + USB_TYPE_CLASS | USB_RECIP_INTERFACE))
  1247. + break;
  1248. + if (w_index != 0 || w_value != 0 || w_length != 0) {
  1249. + value = -EDOM;
  1250. + break;
  1251. + }
  1252. +
  1253. + /* Raise an exception to stop the current operation
  1254. + * and reinitialize our state. */
  1255. + DBG(fsg, "bulk reset request\n");
  1256. + raise_exception(fsg, FSG_STATE_RESET);
  1257. + value = DELAYED_STATUS;
  1258. + break;
  1259. +
  1260. + case US_BULK_GET_MAX_LUN:
  1261. + if (ctrl->bRequestType != (USB_DIR_IN |
  1262. + USB_TYPE_CLASS | USB_RECIP_INTERFACE))
  1263. + break;
  1264. + if (w_index != 0 || w_value != 0 || w_length != 1) {
  1265. + value = -EDOM;
  1266. + break;
  1267. + }
  1268. + VDBG(fsg, "get max LUN\n");
  1269. + *(u8 *) req->buf = fsg->nluns - 1;
  1270. + value = 1;
  1271. + break;
  1272. + }
  1273. + }
  1274. +
  1275. + /* Handle CBI class-specific requests */
  1276. + else {
  1277. + switch (ctrl->bRequest) {
  1278. +
  1279. + case USB_CBI_ADSC_REQUEST:
  1280. + if (ctrl->bRequestType != (USB_DIR_OUT |
  1281. + USB_TYPE_CLASS | USB_RECIP_INTERFACE))
  1282. + break;
  1283. + if (w_index != 0 || w_value != 0) {
  1284. + value = -EDOM;
  1285. + break;
  1286. + }
  1287. + if (w_length > MAX_COMMAND_SIZE) {
  1288. + value = -EOVERFLOW;
  1289. + break;
  1290. + }
  1291. + value = w_length;
  1292. + fsg->ep0req->context = received_cbi_adsc;
  1293. + break;
  1294. + }
  1295. + }
  1296. +
  1297. + if (value == -EOPNOTSUPP)
  1298. + VDBG(fsg,
  1299. + "unknown class-specific control req "
  1300. + "%02x.%02x v%04x i%04x l%u\n",
  1301. + ctrl->bRequestType, ctrl->bRequest,
  1302. + le16_to_cpu(ctrl->wValue), w_index, w_length);
  1303. + return value;
  1304. +}
  1305. +
  1306. +
  1307. +/*-------------------------------------------------------------------------*/
  1308. +
  1309. +/* Ep0 standard request handlers. These always run in_irq. */
  1310. +
  1311. +static int standard_setup_req(struct fsg_dev *fsg,
  1312. + const struct usb_ctrlrequest *ctrl)
  1313. +{
  1314. + struct usb_request *req = fsg->ep0req;
  1315. + int value = -EOPNOTSUPP;
  1316. + u16 w_index = le16_to_cpu(ctrl->wIndex);
  1317. + u16 w_value = le16_to_cpu(ctrl->wValue);
  1318. +
  1319. + /* Usually this just stores reply data in the pre-allocated ep0 buffer,
  1320. + * but config change events will also reconfigure hardware. */
  1321. + switch (ctrl->bRequest) {
  1322. +
  1323. + case USB_REQ_GET_DESCRIPTOR:
  1324. + if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
  1325. + USB_RECIP_DEVICE))
  1326. + break;
  1327. + switch (w_value >> 8) {
  1328. +
  1329. + case USB_DT_DEVICE:
  1330. + VDBG(fsg, "get device descriptor\n");
  1331. + device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
  1332. + value = sizeof device_desc;
  1333. + memcpy(req->buf, &device_desc, value);
  1334. + break;
  1335. + case USB_DT_DEVICE_QUALIFIER:
  1336. + VDBG(fsg, "get device qualifier\n");
  1337. + if (!gadget_is_dualspeed(fsg->gadget) ||
  1338. + fsg->gadget->speed == USB_SPEED_SUPER)
  1339. + break;
  1340. + /*
  1341. + * Assume ep0 uses the same maxpacket value for both
  1342. + * speeds
  1343. + */
  1344. + dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
  1345. + value = sizeof dev_qualifier;
  1346. + memcpy(req->buf, &dev_qualifier, value);
  1347. + break;
  1348. +
  1349. + case USB_DT_OTHER_SPEED_CONFIG:
  1350. + VDBG(fsg, "get other-speed config descriptor\n");
  1351. + if (!gadget_is_dualspeed(fsg->gadget) ||
  1352. + fsg->gadget->speed == USB_SPEED_SUPER)
  1353. + break;
  1354. + goto get_config;
  1355. + case USB_DT_CONFIG:
  1356. + VDBG(fsg, "get configuration descriptor\n");
  1357. +get_config:
  1358. + value = populate_config_buf(fsg->gadget,
  1359. + req->buf,
  1360. + w_value >> 8,
  1361. + w_value & 0xff);
  1362. + break;
  1363. +
  1364. + case USB_DT_STRING:
  1365. + VDBG(fsg, "get string descriptor\n");
  1366. +
  1367. + /* wIndex == language code */
  1368. + value = usb_gadget_get_string(&fsg_stringtab,
  1369. + w_value & 0xff, req->buf);
  1370. + break;
  1371. +
  1372. + case USB_DT_BOS:
  1373. + VDBG(fsg, "get bos descriptor\n");
  1374. +
  1375. + if (gadget_is_superspeed(fsg->gadget))
  1376. + value = populate_bos(fsg, req->buf);
  1377. + break;
  1378. + }
  1379. +
  1380. + break;
  1381. +
  1382. + /* One config, two speeds */
  1383. + case USB_REQ_SET_CONFIGURATION:
  1384. + if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD |
  1385. + USB_RECIP_DEVICE))
  1386. + break;
  1387. + VDBG(fsg, "set configuration\n");
  1388. + if (w_value == CONFIG_VALUE || w_value == 0) {
  1389. + fsg->new_config = w_value;
  1390. +
  1391. + /* Raise an exception to wipe out previous transaction
  1392. + * state (queued bufs, etc) and set the new config. */
  1393. + raise_exception(fsg, FSG_STATE_CONFIG_CHANGE);
  1394. + value = DELAYED_STATUS;
  1395. + }
  1396. + break;
  1397. + case USB_REQ_GET_CONFIGURATION:
  1398. + if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
  1399. + USB_RECIP_DEVICE))
  1400. + break;
  1401. + VDBG(fsg, "get configuration\n");
  1402. + *(u8 *) req->buf = fsg->config;
  1403. + value = 1;
  1404. + break;
  1405. +
  1406. + case USB_REQ_SET_INTERFACE:
  1407. + if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD |
  1408. + USB_RECIP_INTERFACE))
  1409. + break;
  1410. + if (fsg->config && w_index == 0) {
  1411. +
  1412. + /* Raise an exception to wipe out previous transaction
  1413. + * state (queued bufs, etc) and install the new
  1414. + * interface altsetting. */
  1415. + raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE);
  1416. + value = DELAYED_STATUS;
  1417. + }
  1418. + break;
  1419. + case USB_REQ_GET_INTERFACE:
  1420. + if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
  1421. + USB_RECIP_INTERFACE))
  1422. + break;
  1423. + if (!fsg->config)
  1424. + break;
  1425. + if (w_index != 0) {
  1426. + value = -EDOM;
  1427. + break;
  1428. + }
  1429. + VDBG(fsg, "get interface\n");
  1430. + *(u8 *) req->buf = 0;
  1431. + value = 1;
  1432. + break;
  1433. +
  1434. + default:
  1435. + VDBG(fsg,
  1436. + "unknown control req %02x.%02x v%04x i%04x l%u\n",
  1437. + ctrl->bRequestType, ctrl->bRequest,
  1438. + w_value, w_index, le16_to_cpu(ctrl->wLength));
  1439. + }
  1440. +
  1441. + return value;
  1442. +}
  1443. +
  1444. +
  1445. +static int fsg_setup(struct usb_gadget *gadget,
  1446. + const struct usb_ctrlrequest *ctrl)
  1447. +{
  1448. + struct fsg_dev *fsg = get_gadget_data(gadget);
  1449. + int rc;
  1450. + int w_length = le16_to_cpu(ctrl->wLength);
  1451. +
  1452. + ++fsg->ep0_req_tag; // Record arrival of a new request
  1453. + fsg->ep0req->context = NULL;
  1454. + fsg->ep0req->length = 0;
  1455. + dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl));
  1456. +
  1457. + if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS)
  1458. + rc = class_setup_req(fsg, ctrl);
  1459. + else
  1460. + rc = standard_setup_req(fsg, ctrl);
  1461. +
  1462. + /* Respond with data/status or defer until later? */
  1463. + if (rc >= 0 && rc != DELAYED_STATUS) {
  1464. + rc = min(rc, w_length);
  1465. + fsg->ep0req->length = rc;
  1466. + fsg->ep0req->zero = rc < w_length;
  1467. + fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
  1468. + "ep0-in" : "ep0-out");
  1469. + rc = ep0_queue(fsg);
  1470. + }
  1471. +
  1472. + /* Device either stalls (rc < 0) or reports success */
  1473. + return rc;
  1474. +}
  1475. +
  1476. +
  1477. +/*-------------------------------------------------------------------------*/
  1478. +
  1479. +/* All the following routines run in process context */
  1480. +
  1481. +
  1482. +/* Use this for bulk or interrupt transfers, not ep0 */
  1483. +static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
  1484. + struct usb_request *req, int *pbusy,
  1485. + enum fsg_buffer_state *state)
  1486. +{
  1487. + int rc;
  1488. +
  1489. + if (ep == fsg->bulk_in)
  1490. + dump_msg(fsg, "bulk-in", req->buf, req->length);
  1491. + else if (ep == fsg->intr_in)
  1492. + dump_msg(fsg, "intr-in", req->buf, req->length);
  1493. +
  1494. + spin_lock_irq(&fsg->lock);
  1495. + *pbusy = 1;
  1496. + *state = BUF_STATE_BUSY;
  1497. + spin_unlock_irq(&fsg->lock);
  1498. + rc = usb_ep_queue(ep, req, GFP_KERNEL);
  1499. + if (rc != 0) {
  1500. + *pbusy = 0;
  1501. + *state = BUF_STATE_EMPTY;
  1502. +
  1503. + /* We can't do much more than wait for a reset */
  1504. +
  1505. + /* Note: currently the net2280 driver fails zero-length
  1506. + * submissions if DMA is enabled. */
  1507. + if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP &&
  1508. + req->length == 0))
  1509. + WARNING(fsg, "error in submission: %s --> %d\n",
  1510. + ep->name, rc);
  1511. + }
  1512. +}
  1513. +
  1514. +
  1515. +static int sleep_thread(struct fsg_dev *fsg)
  1516. +{
  1517. + int rc = 0;
  1518. +
  1519. + /* Wait until a signal arrives or we are woken up */
  1520. + for (;;) {
  1521. + try_to_freeze();
  1522. + set_current_state(TASK_INTERRUPTIBLE);
  1523. + if (signal_pending(current)) {
  1524. + rc = -EINTR;
  1525. + break;
  1526. + }
  1527. + if (fsg->thread_wakeup_needed)
  1528. + break;
  1529. + schedule();
  1530. + }
  1531. + __set_current_state(TASK_RUNNING);
  1532. + fsg->thread_wakeup_needed = 0;
  1533. + return rc;
  1534. +}
  1535. +
  1536. +
  1537. +/*-------------------------------------------------------------------------*/
  1538. +
  1539. +static int do_read(struct fsg_dev *fsg)
  1540. +{
  1541. + struct fsg_lun *curlun = fsg->curlun;
  1542. + u32 lba;
  1543. + struct fsg_buffhd *bh;
  1544. + int rc;
  1545. + u32 amount_left;
  1546. + loff_t file_offset, file_offset_tmp;
  1547. + unsigned int amount;
  1548. + ssize_t nread;
  1549. +
  1550. + /* Get the starting Logical Block Address and check that it's
  1551. + * not too big */
  1552. + if (fsg->cmnd[0] == READ_6)
  1553. + lba = get_unaligned_be24(&fsg->cmnd[1]);
  1554. + else {
  1555. + lba = get_unaligned_be32(&fsg->cmnd[2]);
  1556. +
  1557. + /* We allow DPO (Disable Page Out = don't save data in the
  1558. + * cache) and FUA (Force Unit Access = don't read from the
  1559. + * cache), but we don't implement them. */
  1560. + if ((fsg->cmnd[1] & ~0x18) != 0) {
  1561. + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
  1562. + return -EINVAL;
  1563. + }
  1564. + }
  1565. + if (lba >= curlun->num_sectors) {
  1566. + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
  1567. + return -EINVAL;
  1568. + }
  1569. + file_offset = ((loff_t) lba) << curlun->blkbits;
  1570. +
  1571. + /* Carry out the file reads */
  1572. + amount_left = fsg->data_size_from_cmnd;
  1573. + if (unlikely(amount_left == 0))
  1574. + return -EIO; // No default reply
  1575. +
  1576. + for (;;) {
  1577. +
  1578. + /* Figure out how much we need to read:
  1579. + * Try to read the remaining amount.
  1580. + * But don't read more than the buffer size.
  1581. + * And don't try to read past the end of the file.
  1582. + */
  1583. + amount = min((unsigned int) amount_left, mod_data.buflen);
  1584. + amount = min((loff_t) amount,
  1585. + curlun->file_length - file_offset);
  1586. +
  1587. + /* Wait for the next buffer to become available */
  1588. + bh = fsg->next_buffhd_to_fill;
  1589. + while (bh->state != BUF_STATE_EMPTY) {
  1590. + rc = sleep_thread(fsg);
  1591. + if (rc)
  1592. + return rc;
  1593. + }
  1594. +
  1595. + /* If we were asked to read past the end of file,
  1596. + * end with an empty buffer. */
  1597. + if (amount == 0) {
  1598. + curlun->sense_data =
  1599. + SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
  1600. + curlun->sense_data_info = file_offset >> curlun->blkbits;
  1601. + curlun->info_valid = 1;
  1602. + bh->inreq->length = 0;
  1603. + bh->state = BUF_STATE_FULL;
  1604. + break;
  1605. + }
  1606. +
  1607. + /* Perform the read */
  1608. + file_offset_tmp = file_offset;
  1609. + nread = vfs_read(curlun->filp,
  1610. + (char __user *) bh->buf,
  1611. + amount, &file_offset_tmp);
  1612. + VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
  1613. + (unsigned long long) file_offset,
  1614. + (int) nread);
  1615. + if (signal_pending(current))
  1616. + return -EINTR;
  1617. +
  1618. + if (nread < 0) {
  1619. + LDBG(curlun, "error in file read: %d\n",
  1620. + (int) nread);
  1621. + nread = 0;
  1622. + } else if (nread < amount) {
  1623. + LDBG(curlun, "partial file read: %d/%u\n",
  1624. + (int) nread, amount);
  1625. + nread = round_down(nread, curlun->blksize);
  1626. + }
  1627. + file_offset += nread;
  1628. + amount_left -= nread;
  1629. + fsg->residue -= nread;
  1630. +
  1631. + /* Except at the end of the transfer, nread will be
  1632. + * equal to the buffer size, which is divisible by the
  1633. + * bulk-in maxpacket size.
  1634. + */
  1635. + bh->inreq->length = nread;
  1636. + bh->state = BUF_STATE_FULL;
  1637. +
  1638. + /* If an error occurred, report it and its position */
  1639. + if (nread < amount) {
  1640. + curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
  1641. + curlun->sense_data_info = file_offset >> curlun->blkbits;
  1642. + curlun->info_valid = 1;
  1643. + break;
  1644. + }
  1645. +
  1646. + if (amount_left == 0)
  1647. + break; // No more left to read
  1648. +
  1649. + /* Send this buffer and go read some more */
  1650. + bh->inreq->zero = 0;
  1651. + start_transfer(fsg, fsg->bulk_in, bh->inreq,
  1652. + &bh->inreq_busy, &bh->state);
  1653. + fsg->next_buffhd_to_fill = bh->next;
  1654. + }
  1655. +
  1656. + return -EIO; // No default reply
  1657. +}
  1658. +
  1659. +
  1660. +/*-------------------------------------------------------------------------*/
  1661. +
  1662. +static int do_write(struct fsg_dev *fsg)
  1663. +{
  1664. + struct fsg_lun *curlun = fsg->curlun;
  1665. + u32 lba;
  1666. + struct fsg_buffhd *bh;
  1667. + int get_some_more;
  1668. + u32 amount_left_to_req, amount_left_to_write;
  1669. + loff_t usb_offset, file_offset, file_offset_tmp;
  1670. + unsigned int amount;
  1671. + ssize_t nwritten;
  1672. + int rc;
  1673. +
  1674. + if (curlun->ro) {
  1675. + curlun->sense_data = SS_WRITE_PROTECTED;
  1676. + return -EINVAL;
  1677. + }
  1678. + spin_lock(&curlun->filp->f_lock);
  1679. + curlun->filp->f_flags &= ~O_SYNC; // Default is not to wait
  1680. + spin_unlock(&curlun->filp->f_lock);
  1681. +
  1682. + /* Get the starting Logical Block Address and check that it's
  1683. + * not too big */
  1684. + if (fsg->cmnd[0] == WRITE_6)
  1685. + lba = get_unaligned_be24(&fsg->cmnd[1]);
  1686. + else {
  1687. + lba = get_unaligned_be32(&fsg->cmnd[2]);
  1688. +
  1689. + /* We allow DPO (Disable Page Out = don't save data in the
  1690. + * cache) and FUA (Force Unit Access = write directly to the
  1691. + * medium). We don't implement DPO; we implement FUA by
  1692. + * performing synchronous output. */
  1693. + if ((fsg->cmnd[1] & ~0x18) != 0) {
  1694. + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
  1695. + return -EINVAL;
  1696. + }
  1697. + /* FUA */
  1698. + if (!curlun->nofua && (fsg->cmnd[1] & 0x08)) {
  1699. + spin_lock(&curlun->filp->f_lock);
  1700. + curlun->filp->f_flags |= O_DSYNC;
  1701. + spin_unlock(&curlun->filp->f_lock);
  1702. + }
  1703. + }
  1704. + if (lba >= curlun->num_sectors) {
  1705. + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
  1706. + return -EINVAL;
  1707. + }
  1708. +
  1709. + /* Carry out the file writes */
  1710. + get_some_more = 1;
  1711. + file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits;
  1712. + amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd;
  1713. +
  1714. + while (amount_left_to_write > 0) {
  1715. +
  1716. + /* Queue a request for more data from the host */
  1717. + bh = fsg->next_buffhd_to_fill;
  1718. + if (bh->state == BUF_STATE_EMPTY && get_some_more) {
  1719. +
  1720. + /* Figure out how much we want to get:
  1721. + * Try to get the remaining amount,
  1722. + * but not more than the buffer size.
  1723. + */
  1724. + amount = min(amount_left_to_req, mod_data.buflen);
  1725. +
  1726. + /* Beyond the end of the backing file? */
  1727. + if (usb_offset >= curlun->file_length) {
  1728. + get_some_more = 0;
  1729. + curlun->sense_data =
  1730. + SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
  1731. + curlun->sense_data_info = usb_offset >> curlun->blkbits;
  1732. + curlun->info_valid = 1;
  1733. + continue;
  1734. + }
  1735. +
  1736. + /* Get the next buffer */
  1737. + usb_offset += amount;
  1738. + fsg->usb_amount_left -= amount;
  1739. + amount_left_to_req -= amount;
  1740. + if (amount_left_to_req == 0)
  1741. + get_some_more = 0;
  1742. +
  1743. + /* Except at the end of the transfer, amount will be
  1744. + * equal to the buffer size, which is divisible by
  1745. + * the bulk-out maxpacket size.
  1746. + */
  1747. + set_bulk_out_req_length(fsg, bh, amount);
  1748. + start_transfer(fsg, fsg->bulk_out, bh->outreq,
  1749. + &bh->outreq_busy, &bh->state);
  1750. + fsg->next_buffhd_to_fill = bh->next;
  1751. + continue;
  1752. + }
  1753. +
  1754. + /* Write the received data to the backing file */
  1755. + bh = fsg->next_buffhd_to_drain;
  1756. + if (bh->state == BUF_STATE_EMPTY && !get_some_more)
  1757. + break; // We stopped early
  1758. + if (bh->state == BUF_STATE_FULL) {
  1759. + smp_rmb();
  1760. + fsg->next_buffhd_to_drain = bh->next;
  1761. + bh->state = BUF_STATE_EMPTY;
  1762. +
  1763. + /* Did something go wrong with the transfer? */
  1764. + if (bh->outreq->status != 0) {
  1765. + curlun->sense_data = SS_COMMUNICATION_FAILURE;
  1766. + curlun->sense_data_info = file_offset >> curlun->blkbits;
  1767. + curlun->info_valid = 1;
  1768. + break;
  1769. + }
  1770. +
  1771. + amount = bh->outreq->actual;
  1772. + if (curlun->file_length - file_offset < amount) {
  1773. + LERROR(curlun,
  1774. + "write %u @ %llu beyond end %llu\n",
  1775. + amount, (unsigned long long) file_offset,
  1776. + (unsigned long long) curlun->file_length);
  1777. + amount = curlun->file_length - file_offset;
  1778. + }
  1779. +
  1780. + /* Don't accept excess data. The spec doesn't say
  1781. + * what to do in this case. We'll ignore the error.
  1782. + */
  1783. + amount = min(amount, bh->bulk_out_intended_length);
  1784. +
  1785. + /* Don't write a partial block */
  1786. + amount = round_down(amount, curlun->blksize);
  1787. + if (amount == 0)
  1788. + goto empty_write;
  1789. +
  1790. + /* Perform the write */
  1791. + file_offset_tmp = file_offset;
  1792. + nwritten = vfs_write(curlun->filp,
  1793. + (char __user *) bh->buf,
  1794. + amount, &file_offset_tmp);
  1795. + VLDBG(curlun, "file write %u @ %llu -> %d\n", amount,
  1796. + (unsigned long long) file_offset,
  1797. + (int) nwritten);
  1798. + if (signal_pending(current))
  1799. + return -EINTR; // Interrupted!
  1800. +
  1801. + if (nwritten < 0) {
  1802. + LDBG(curlun, "error in file write: %d\n",
  1803. + (int) nwritten);
  1804. + nwritten = 0;
  1805. + } else if (nwritten < amount) {
  1806. + LDBG(curlun, "partial file write: %d/%u\n",
  1807. + (int) nwritten, amount);
  1808. + nwritten = round_down(nwritten, curlun->blksize);
  1809. + }
  1810. + file_offset += nwritten;
  1811. + amount_left_to_write -= nwritten;
  1812. + fsg->residue -= nwritten;
  1813. +
  1814. + /* If an error occurred, report it and its position */
  1815. + if (nwritten < amount) {
  1816. + curlun->sense_data = SS_WRITE_ERROR;
  1817. + curlun->sense_data_info = file_offset >> curlun->blkbits;
  1818. + curlun->info_valid = 1;
  1819. + break;
  1820. + }
  1821. +
  1822. + empty_write:
  1823. + /* Did the host decide to stop early? */
  1824. + if (bh->outreq->actual < bh->bulk_out_intended_length) {
  1825. + fsg->short_packet_received = 1;
  1826. + break;
  1827. + }
  1828. + continue;
  1829. + }
  1830. +
  1831. + /* Wait for something to happen */
  1832. + rc = sleep_thread(fsg);
  1833. + if (rc)
  1834. + return rc;
  1835. + }
  1836. +
  1837. + return -EIO; // No default reply
  1838. +}
  1839. +
  1840. +
  1841. +/*-------------------------------------------------------------------------*/
  1842. +
  1843. +static int do_synchronize_cache(struct fsg_dev *fsg)
  1844. +{
  1845. + struct fsg_lun *curlun = fsg->curlun;
  1846. + int rc;
  1847. +
  1848. + /* We ignore the requested LBA and write out all file's
  1849. + * dirty data buffers. */
  1850. + rc = fsg_lun_fsync_sub(curlun);
  1851. + if (rc)
  1852. + curlun->sense_data = SS_WRITE_ERROR;
  1853. + return 0;
  1854. +}
  1855. +
  1856. +
  1857. +/*-------------------------------------------------------------------------*/
  1858. +
  1859. +static void invalidate_sub(struct fsg_lun *curlun)
  1860. +{
  1861. + struct file *filp = curlun->filp;
  1862. + struct inode *inode = filp->f_path.dentry->d_inode;
  1863. + unsigned long rc;
  1864. +
  1865. + rc = invalidate_mapping_pages(inode->i_mapping, 0, -1);
  1866. + VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc);
  1867. +}
  1868. +
  1869. +static int do_verify(struct fsg_dev *fsg)
  1870. +{
  1871. + struct fsg_lun *curlun = fsg->curlun;
  1872. + u32 lba;
  1873. + u32 verification_length;
  1874. + struct fsg_buffhd *bh = fsg->next_buffhd_to_fill;
  1875. + loff_t file_offset, file_offset_tmp;
  1876. + u32 amount_left;
  1877. + unsigned int amount;
  1878. + ssize_t nread;
  1879. +
  1880. + /* Get the starting Logical Block Address and check that it's
  1881. + * not too big */
  1882. + lba = get_unaligned_be32(&fsg->cmnd[2]);
  1883. + if (lba >= curlun->num_sectors) {
  1884. + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
  1885. + return -EINVAL;
  1886. + }
  1887. +
  1888. + /* We allow DPO (Disable Page Out = don't save data in the
  1889. + * cache) but we don't implement it. */
  1890. + if ((fsg->cmnd[1] & ~0x10) != 0) {
  1891. + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
  1892. + return -EINVAL;
  1893. + }
  1894. +
  1895. + verification_length = get_unaligned_be16(&fsg->cmnd[7]);
  1896. + if (unlikely(verification_length == 0))
  1897. + return -EIO; // No default reply
  1898. +
  1899. + /* Prepare to carry out the file verify */
  1900. + amount_left = verification_length << curlun->blkbits;
  1901. + file_offset = ((loff_t) lba) << curlun->blkbits;
  1902. +
  1903. + /* Write out all the dirty buffers before invalidating them */
  1904. + fsg_lun_fsync_sub(curlun);
  1905. + if (signal_pending(current))
  1906. + return -EINTR;
  1907. +
  1908. + invalidate_sub(curlun);
  1909. + if (signal_pending(current))
  1910. + return -EINTR;
  1911. +
  1912. + /* Just try to read the requested blocks */
  1913. + while (amount_left > 0) {
  1914. +
  1915. + /* Figure out how much we need to read:
  1916. + * Try to read the remaining amount, but not more than
  1917. + * the buffer size.
  1918. + * And don't try to read past the end of the file.
  1919. + */
  1920. + amount = min((unsigned int) amount_left, mod_data.buflen);
  1921. + amount = min((loff_t) amount,
  1922. + curlun->file_length - file_offset);
  1923. + if (amount == 0) {
  1924. + curlun->sense_data =
  1925. + SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
  1926. + curlun->sense_data_info = file_offset >> curlun->blkbits;
  1927. + curlun->info_valid = 1;
  1928. + break;
  1929. + }
  1930. +
  1931. + /* Perform the read */
  1932. + file_offset_tmp = file_offset;
  1933. + nread = vfs_read(curlun->filp,
  1934. + (char __user *) bh->buf,
  1935. + amount, &file_offset_tmp);
  1936. + VLDBG(curlun, "file read %u @ %llu -> %d\n", amount,
  1937. + (unsigned long long) file_offset,
  1938. + (int) nread);
  1939. + if (signal_pending(current))
  1940. + return -EINTR;
  1941. +
  1942. + if (nread < 0) {
  1943. + LDBG(curlun, "error in file verify: %d\n",
  1944. + (int) nread);
  1945. + nread = 0;
  1946. + } else if (nread < amount) {
  1947. + LDBG(curlun, "partial file verify: %d/%u\n",
  1948. + (int) nread, amount);
  1949. + nread = round_down(nread, curlun->blksize);
  1950. + }
  1951. + if (nread == 0) {
  1952. + curlun->sense_data = SS_UNRECOVERED_READ_ERROR;
  1953. + curlun->sense_data_info = file_offset >> curlun->blkbits;
  1954. + curlun->info_valid = 1;
  1955. + break;
  1956. + }
  1957. + file_offset += nread;
  1958. + amount_left -= nread;
  1959. + }
  1960. + return 0;
  1961. +}
  1962. +
  1963. +
  1964. +/*-------------------------------------------------------------------------*/
  1965. +
  1966. +static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh)
  1967. +{
  1968. + u8 *buf = (u8 *) bh->buf;
  1969. +
  1970. + static char vendor_id[] = "Linux ";
  1971. + static char product_disk_id[] = "File-Stor Gadget";
  1972. + static char product_cdrom_id[] = "File-CD Gadget ";
  1973. +
  1974. + if (!fsg->curlun) { // Unsupported LUNs are okay
  1975. + fsg->bad_lun_okay = 1;
  1976. + memset(buf, 0, 36);
  1977. + buf[0] = 0x7f; // Unsupported, no device-type
  1978. + buf[4] = 31; // Additional length
  1979. + return 36;
  1980. + }
  1981. +
  1982. + memset(buf, 0, 8);
  1983. + buf[0] = (mod_data.cdrom ? TYPE_ROM : TYPE_DISK);
  1984. + if (mod_data.removable)
  1985. + buf[1] = 0x80;
  1986. + buf[2] = 2; // ANSI SCSI level 2
  1987. + buf[3] = 2; // SCSI-2 INQUIRY data format
  1988. + buf[4] = 31; // Additional length
  1989. + // No special options
  1990. + sprintf(buf + 8, "%-8s%-16s%04x", vendor_id,
  1991. + (mod_data.cdrom ? product_cdrom_id :
  1992. + product_disk_id),
  1993. + mod_data.release);
  1994. + return 36;
  1995. +}
  1996. +
  1997. +
  1998. +static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
  1999. +{
  2000. + struct fsg_lun *curlun = fsg->curlun;
  2001. + u8 *buf = (u8 *) bh->buf;
  2002. + u32 sd, sdinfo;
  2003. + int valid;
  2004. +
  2005. + /*
  2006. + * From the SCSI-2 spec., section 7.9 (Unit attention condition):
  2007. + *
  2008. + * If a REQUEST SENSE command is received from an initiator
  2009. + * with a pending unit attention condition (before the target
  2010. + * generates the contingent allegiance condition), then the
  2011. + * target shall either:
  2012. + * a) report any pending sense data and preserve the unit
  2013. + * attention condition on the logical unit, or,
  2014. + * b) report the unit attention condition, may discard any
  2015. + * pending sense data, and clear the unit attention
  2016. + * condition on the logical unit for that initiator.
  2017. + *
  2018. + * FSG normally uses option a); enable this code to use option b).
  2019. + */
  2020. +#if 0
  2021. + if (curlun && curlun->unit_attention_data != SS_NO_SENSE) {
  2022. + curlun->sense_data = curlun->unit_attention_data;
  2023. + curlun->unit_attention_data = SS_NO_SENSE;
  2024. + }
  2025. +#endif
  2026. +
  2027. + if (!curlun) { // Unsupported LUNs are okay
  2028. + fsg->bad_lun_okay = 1;
  2029. + sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
  2030. + sdinfo = 0;
  2031. + valid = 0;
  2032. + } else {
  2033. + sd = curlun->sense_data;
  2034. + sdinfo = curlun->sense_data_info;
  2035. + valid = curlun->info_valid << 7;
  2036. + curlun->sense_data = SS_NO_SENSE;
  2037. + curlun->sense_data_info = 0;
  2038. + curlun->info_valid = 0;
  2039. + }
  2040. +
  2041. + memset(buf, 0, 18);
  2042. + buf[0] = valid | 0x70; // Valid, current error
  2043. + buf[2] = SK(sd);
  2044. + put_unaligned_be32(sdinfo, &buf[3]); /* Sense information */
  2045. + buf[7] = 18 - 8; // Additional sense length
  2046. + buf[12] = ASC(sd);
  2047. + buf[13] = ASCQ(sd);
  2048. + return 18;
  2049. +}
  2050. +
  2051. +
  2052. +static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh)
  2053. +{
  2054. + struct fsg_lun *curlun = fsg->curlun;
  2055. + u32 lba = get_unaligned_be32(&fsg->cmnd[2]);
  2056. + int pmi = fsg->cmnd[8];
  2057. + u8 *buf = (u8 *) bh->buf;
  2058. +
  2059. + /* Check the PMI and LBA fields */
  2060. + if (pmi > 1 || (pmi == 0 && lba != 0)) {
  2061. + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
  2062. + return -EINVAL;
  2063. + }
  2064. +
  2065. + put_unaligned_be32(curlun->num_sectors - 1, &buf[0]);
  2066. + /* Max logical block */
  2067. + put_unaligned_be32(curlun->blksize, &buf[4]); /* Block length */
  2068. + return 8;
  2069. +}
  2070. +
  2071. +
  2072. +static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh)
  2073. +{
  2074. + struct fsg_lun *curlun = fsg->curlun;
  2075. + int msf = fsg->cmnd[1] & 0x02;
  2076. + u32 lba = get_unaligned_be32(&fsg->cmnd[2]);
  2077. + u8 *buf = (u8 *) bh->buf;
  2078. +
  2079. + if ((fsg->cmnd[1] & ~0x02) != 0) { /* Mask away MSF */
  2080. + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
  2081. + return -EINVAL;
  2082. + }
  2083. + if (lba >= curlun->num_sectors) {
  2084. + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
  2085. + return -EINVAL;
  2086. + }
  2087. +
  2088. + memset(buf, 0, 8);
  2089. + buf[0] = 0x01; /* 2048 bytes of user data, rest is EC */
  2090. + store_cdrom_address(&buf[4], msf, lba);
  2091. + return 8;
  2092. +}
  2093. +
  2094. +
  2095. +static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
  2096. +{
  2097. + struct fsg_lun *curlun = fsg->curlun;
  2098. + int msf = fsg->cmnd[1] & 0x02;
  2099. + int start_track = fsg->cmnd[6];
  2100. + u8 *buf = (u8 *) bh->buf;
  2101. +
  2102. + if ((fsg->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */
  2103. + start_track > 1) {
  2104. + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
  2105. + return -EINVAL;
  2106. + }
  2107. +
  2108. + memset(buf, 0, 20);
  2109. + buf[1] = (20-2); /* TOC data length */
  2110. + buf[2] = 1; /* First track number */
  2111. + buf[3] = 1; /* Last track number */
  2112. + buf[5] = 0x16; /* Data track, copying allowed */
  2113. + buf[6] = 0x01; /* Only track is number 1 */
  2114. + store_cdrom_address(&buf[8], msf, 0);
  2115. +
  2116. + buf[13] = 0x16; /* Lead-out track is data */
  2117. + buf[14] = 0xAA; /* Lead-out track number */
  2118. + store_cdrom_address(&buf[16], msf, curlun->num_sectors);
  2119. + return 20;
  2120. +}
  2121. +
  2122. +
  2123. +static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh)
  2124. +{
  2125. + struct fsg_lun *curlun = fsg->curlun;
  2126. + int mscmnd = fsg->cmnd[0];
  2127. + u8 *buf = (u8 *) bh->buf;
  2128. + u8 *buf0 = buf;
  2129. + int pc, page_code;
  2130. + int changeable_values, all_pages;
  2131. + int valid_page = 0;
  2132. + int len, limit;
  2133. +
  2134. + if ((fsg->cmnd[1] & ~0x08) != 0) { // Mask away DBD
  2135. + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
  2136. + return -EINVAL;
  2137. + }
  2138. + pc = fsg->cmnd[2] >> 6;
  2139. + page_code = fsg->cmnd[2] & 0x3f;
  2140. + if (pc == 3) {
  2141. + curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
  2142. + return -EINVAL;
  2143. + }
  2144. + changeable_values = (pc == 1);
  2145. + all_pages = (page_code == 0x3f);
  2146. +
  2147. + /* Write the mode parameter header. Fixed values are: default
  2148. + * medium type, no cache control (DPOFUA), and no block descriptors.
  2149. + * The only variable value is the WriteProtect bit. We will fill in
  2150. + * the mode data length later. */
  2151. + memset(buf, 0, 8);
  2152. + if (mscmnd == MODE_SENSE) {
  2153. + buf[2] = (curlun->ro ? 0x80 : 0x00); // WP, DPOFUA
  2154. + buf += 4;
  2155. + limit = 255;
  2156. + } else { // MODE_SENSE_10
  2157. + buf[3] = (curlun->ro ? 0x80 : 0x00); // WP, DPOFUA
  2158. + buf += 8;
  2159. + limit = 65535; // Should really be mod_data.buflen
  2160. + }
  2161. +
  2162. + /* No block descriptors */
  2163. +
  2164. + /* The mode pages, in numerical order. The only page we support
  2165. + * is the Caching page. */
  2166. + if (page_code == 0x08 || all_pages) {
  2167. + valid_page = 1;
  2168. + buf[0] = 0x08; // Page code
  2169. + buf[1] = 10; // Page length
  2170. + memset(buf+2, 0, 10); // None of the fields are changeable
  2171. +
  2172. + if (!changeable_values) {
  2173. + buf[2] = 0x04; // Write cache enable,
  2174. + // Read cache not disabled
  2175. + // No cache retention priorities
  2176. + put_unaligned_be16(0xffff, &buf[4]);
  2177. + /* Don't disable prefetch */
  2178. + /* Minimum prefetch = 0 */
  2179. + put_unaligned_be16(0xffff, &buf[8]);
  2180. + /* Maximum prefetch */
  2181. + put_unaligned_be16(0xffff, &buf[10]);
  2182. + /* Maximum prefetch ceiling */
  2183. + }
  2184. + buf += 12;
  2185. + }
  2186. +
  2187. + /* Check that a valid page was requested and the mode data length
  2188. + * isn't too long. */
  2189. + len = buf - buf0;
  2190. + if (!valid_page || len > limit) {
  2191. + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
  2192. + return -EINVAL;
  2193. + }
  2194. +
  2195. + /* Store the mode data length */
  2196. + if (mscmnd == MODE_SENSE)
  2197. + buf0[0] = len - 1;
  2198. + else
  2199. + put_unaligned_be16(len - 2, buf0);
  2200. + return len;
  2201. +}
  2202. +
  2203. +
  2204. +static int do_start_stop(struct fsg_dev *fsg)
  2205. +{
  2206. + struct fsg_lun *curlun = fsg->curlun;
  2207. + int loej, start;
  2208. +
  2209. + if (!mod_data.removable) {
  2210. + curlun->sense_data = SS_INVALID_COMMAND;
  2211. + return -EINVAL;
  2212. + }
  2213. +
  2214. + // int immed = fsg->cmnd[1] & 0x01;
  2215. + loej = fsg->cmnd[4] & 0x02;
  2216. + start = fsg->cmnd[4] & 0x01;
  2217. +
  2218. +#ifdef CONFIG_USB_FILE_STORAGE_TEST
  2219. + if ((fsg->cmnd[1] & ~0x01) != 0 || // Mask away Immed
  2220. + (fsg->cmnd[4] & ~0x03) != 0) { // Mask LoEj, Start
  2221. + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
  2222. + return -EINVAL;
  2223. + }
  2224. +
  2225. + if (!start) {
  2226. +
  2227. + /* Are we allowed to unload the media? */
  2228. + if (curlun->prevent_medium_removal) {
  2229. + LDBG(curlun, "unload attempt prevented\n");
  2230. + curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED;
  2231. + return -EINVAL;
  2232. + }
  2233. + if (loej) { // Simulate an unload/eject
  2234. + up_read(&fsg->filesem);
  2235. + down_write(&fsg->filesem);
  2236. + fsg_lun_close(curlun);
  2237. + up_write(&fsg->filesem);
  2238. + down_read(&fsg->filesem);
  2239. + }
  2240. + } else {
  2241. +
  2242. + /* Our emulation doesn't support mounting; the medium is
  2243. + * available for use as soon as it is loaded. */
  2244. + if (!fsg_lun_is_open(curlun)) {
  2245. + curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
  2246. + return -EINVAL;
  2247. + }
  2248. + }
  2249. +#endif
  2250. + return 0;
  2251. +}
  2252. +
  2253. +
  2254. +static int do_prevent_allow(struct fsg_dev *fsg)
  2255. +{
  2256. + struct fsg_lun *curlun = fsg->curlun;
  2257. + int prevent;
  2258. +
  2259. + if (!mod_data.removable) {
  2260. + curlun->sense_data = SS_INVALID_COMMAND;
  2261. + return -EINVAL;
  2262. + }
  2263. +
  2264. + prevent = fsg->cmnd[4] & 0x01;
  2265. + if ((fsg->cmnd[4] & ~0x01) != 0) { // Mask away Prevent
  2266. + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
  2267. + return -EINVAL;
  2268. + }
  2269. +
  2270. + if (curlun->prevent_medium_removal && !prevent)
  2271. + fsg_lun_fsync_sub(curlun);
  2272. + curlun->prevent_medium_removal = prevent;
  2273. + return 0;
  2274. +}
  2275. +
  2276. +
  2277. +static int do_read_format_capacities(struct fsg_dev *fsg,
  2278. + struct fsg_buffhd *bh)
  2279. +{
  2280. + struct fsg_lun *curlun = fsg->curlun;
  2281. + u8 *buf = (u8 *) bh->buf;
  2282. +
  2283. + buf[0] = buf[1] = buf[2] = 0;
  2284. + buf[3] = 8; // Only the Current/Maximum Capacity Descriptor
  2285. + buf += 4;
  2286. +
  2287. + put_unaligned_be32(curlun->num_sectors, &buf[0]);
  2288. + /* Number of blocks */
  2289. + put_unaligned_be32(curlun->blksize, &buf[4]); /* Block length */
  2290. + buf[4] = 0x02; /* Current capacity */
  2291. + return 12;
  2292. +}
  2293. +
  2294. +
  2295. +static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh)
  2296. +{
  2297. + struct fsg_lun *curlun = fsg->curlun;
  2298. +
  2299. + /* We don't support MODE SELECT */
  2300. + curlun->sense_data = SS_INVALID_COMMAND;
  2301. + return -EINVAL;
  2302. +}
  2303. +
  2304. +
  2305. +/*-------------------------------------------------------------------------*/
  2306. +
  2307. +static int halt_bulk_in_endpoint(struct fsg_dev *fsg)
  2308. +{
  2309. + int rc;
  2310. +
  2311. + rc = fsg_set_halt(fsg, fsg->bulk_in);
  2312. + if (rc == -EAGAIN)
  2313. + VDBG(fsg, "delayed bulk-in endpoint halt\n");
  2314. + while (rc != 0) {
  2315. + if (rc != -EAGAIN) {
  2316. + WARNING(fsg, "usb_ep_set_halt -> %d\n", rc);
  2317. + rc = 0;
  2318. + break;
  2319. + }
  2320. +
  2321. + /* Wait for a short time and then try again */
  2322. + if (msleep_interruptible(100) != 0)
  2323. + return -EINTR;
  2324. + rc = usb_ep_set_halt(fsg->bulk_in);
  2325. + }
  2326. + return rc;
  2327. +}
  2328. +
  2329. +static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
  2330. +{
  2331. + int rc;
  2332. +
  2333. + DBG(fsg, "bulk-in set wedge\n");
  2334. + rc = usb_ep_set_wedge(fsg->bulk_in);
  2335. + if (rc == -EAGAIN)
  2336. + VDBG(fsg, "delayed bulk-in endpoint wedge\n");
  2337. + while (rc != 0) {
  2338. + if (rc != -EAGAIN) {
  2339. + WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc);
  2340. + rc = 0;
  2341. + break;
  2342. + }
  2343. +
  2344. + /* Wait for a short time and then try again */
  2345. + if (msleep_interruptible(100) != 0)
  2346. + return -EINTR;
  2347. + rc = usb_ep_set_wedge(fsg->bulk_in);
  2348. + }
  2349. + return rc;
  2350. +}
  2351. +
  2352. +static int throw_away_data(struct fsg_dev *fsg)
  2353. +{
  2354. + struct fsg_buffhd *bh;
  2355. + u32 amount;
  2356. + int rc;
  2357. +
  2358. + while ((bh = fsg->next_buffhd_to_drain)->state != BUF_STATE_EMPTY ||
  2359. + fsg->usb_amount_left > 0) {
  2360. +
  2361. + /* Throw away the data in a filled buffer */
  2362. + if (bh->state == BUF_STATE_FULL) {
  2363. + smp_rmb();
  2364. + bh->state = BUF_STATE_EMPTY;
  2365. + fsg->next_buffhd_to_drain = bh->next;
  2366. +
  2367. + /* A short packet or an error ends everything */
  2368. + if (bh->outreq->actual < bh->bulk_out_intended_length ||
  2369. + bh->outreq->status != 0) {
  2370. + raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
  2371. + return -EINTR;
  2372. + }
  2373. + continue;
  2374. + }
  2375. +
  2376. + /* Try to submit another request if we need one */
  2377. + bh = fsg->next_buffhd_to_fill;
  2378. + if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) {
  2379. + amount = min(fsg->usb_amount_left,
  2380. + (u32) mod_data.buflen);
  2381. +
  2382. + /* Except at the end of the transfer, amount will be
  2383. + * equal to the buffer size, which is divisible by
  2384. + * the bulk-out maxpacket size.
  2385. + */
  2386. + set_bulk_out_req_length(fsg, bh, amount);
  2387. + start_transfer(fsg, fsg->bulk_out, bh->outreq,
  2388. + &bh->outreq_busy, &bh->state);
  2389. + fsg->next_buffhd_to_fill = bh->next;
  2390. + fsg->usb_amount_left -= amount;
  2391. + continue;
  2392. + }
  2393. +
  2394. + /* Otherwise wait for something to happen */
  2395. + rc = sleep_thread(fsg);
  2396. + if (rc)
  2397. + return rc;
  2398. + }
  2399. + return 0;
  2400. +}
  2401. +
  2402. +
  2403. +static int finish_reply(struct fsg_dev *fsg)
  2404. +{
  2405. + struct fsg_buffhd *bh = fsg->next_buffhd_to_fill;
  2406. + int rc = 0;
  2407. +
  2408. + switch (fsg->data_dir) {
  2409. + case DATA_DIR_NONE:
  2410. + break; // Nothing to send
  2411. +
  2412. + /* If we don't know whether the host wants to read or write,
  2413. + * this must be CB or CBI with an unknown command. We mustn't
  2414. + * try to send or receive any data. So stall both bulk pipes
  2415. + * if we can and wait for a reset. */
  2416. + case DATA_DIR_UNKNOWN:
  2417. + if (mod_data.can_stall) {
  2418. + fsg_set_halt(fsg, fsg->bulk_out);
  2419. + rc = halt_bulk_in_endpoint(fsg);
  2420. + }
  2421. + break;
  2422. +
  2423. + /* All but the last buffer of data must have already been sent */
  2424. + case DATA_DIR_TO_HOST:
  2425. + if (fsg->data_size == 0)
  2426. + ; // Nothing to send
  2427. +
  2428. + /* If there's no residue, simply send the last buffer */
  2429. + else if (fsg->residue == 0) {
  2430. + bh->inreq->zero = 0;
  2431. + start_transfer(fsg, fsg->bulk_in, bh->inreq,
  2432. + &bh->inreq_busy, &bh->state);
  2433. + fsg->next_buffhd_to_fill = bh->next;
  2434. + }
  2435. +
  2436. + /* There is a residue. For CB and CBI, simply mark the end
  2437. + * of the data with a short packet. However, if we are
  2438. + * allowed to stall, there was no data at all (residue ==
  2439. + * data_size), and the command failed (invalid LUN or
  2440. + * sense data is set), then halt the bulk-in endpoint
  2441. + * instead. */
  2442. + else if (!transport_is_bbb()) {
  2443. + if (mod_data.can_stall &&
  2444. + fsg->residue == fsg->data_size &&
  2445. + (!fsg->curlun || fsg->curlun->sense_data != SS_NO_SENSE)) {
  2446. + bh->state = BUF_STATE_EMPTY;
  2447. + rc = halt_bulk_in_endpoint(fsg);
  2448. + } else {
  2449. + bh->inreq->zero = 1;
  2450. + start_transfer(fsg, fsg->bulk_in, bh->inreq,
  2451. + &bh->inreq_busy, &bh->state);
  2452. + fsg->next_buffhd_to_fill = bh->next;
  2453. + }
  2454. + }
  2455. +
  2456. + /*
  2457. + * For Bulk-only, mark the end of the data with a short
  2458. + * packet. If we are allowed to stall, halt the bulk-in
  2459. + * endpoint. (Note: This violates the Bulk-Only Transport
  2460. + * specification, which requires us to pad the data if we
  2461. + * don't halt the endpoint. Presumably nobody will mind.)
  2462. + */
  2463. + else {
  2464. + bh->inreq->zero = 1;
  2465. + start_transfer(fsg, fsg->bulk_in, bh->inreq,
  2466. + &bh->inreq_busy, &bh->state);
  2467. + fsg->next_buffhd_to_fill = bh->next;
  2468. + if (mod_data.can_stall)
  2469. + rc = halt_bulk_in_endpoint(fsg);
  2470. + }
  2471. + break;
  2472. +
  2473. + /* We have processed all we want from the data the host has sent.
  2474. + * There may still be outstanding bulk-out requests. */
  2475. + case DATA_DIR_FROM_HOST:
  2476. + if (fsg->residue == 0)
  2477. + ; // Nothing to receive
  2478. +
  2479. + /* Did the host stop sending unexpectedly early? */
  2480. + else if (fsg->short_packet_received) {
  2481. + raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
  2482. + rc = -EINTR;
  2483. + }
  2484. +
  2485. + /* We haven't processed all the incoming data. Even though
  2486. + * we may be allowed to stall, doing so would cause a race.
  2487. + * The controller may already have ACK'ed all the remaining
  2488. + * bulk-out packets, in which case the host wouldn't see a
  2489. + * STALL. Not realizing the endpoint was halted, it wouldn't
  2490. + * clear the halt -- leading to problems later on. */
  2491. +#if 0
  2492. + else if (mod_data.can_stall) {
  2493. + fsg_set_halt(fsg, fsg->bulk_out);
  2494. + raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
  2495. + rc = -EINTR;
  2496. + }
  2497. +#endif
  2498. +
  2499. + /* We can't stall. Read in the excess data and throw it
  2500. + * all away. */
  2501. + else
  2502. + rc = throw_away_data(fsg);
  2503. + break;
  2504. + }
  2505. + return rc;
  2506. +}
  2507. +
  2508. +
  2509. +static int send_status(struct fsg_dev *fsg)
  2510. +{
  2511. + struct fsg_lun *curlun = fsg->curlun;
  2512. + struct fsg_buffhd *bh;
  2513. + int rc;
  2514. + u8 status = US_BULK_STAT_OK;
  2515. + u32 sd, sdinfo = 0;
  2516. +
  2517. + /* Wait for the next buffer to become available */
  2518. + bh = fsg->next_buffhd_to_fill;
  2519. + while (bh->state != BUF_STATE_EMPTY) {
  2520. + rc = sleep_thread(fsg);
  2521. + if (rc)
  2522. + return rc;
  2523. + }
  2524. +
  2525. + if (curlun) {
  2526. + sd = curlun->sense_data;
  2527. + sdinfo = curlun->sense_data_info;
  2528. + } else if (fsg->bad_lun_okay)
  2529. + sd = SS_NO_SENSE;
  2530. + else
  2531. + sd = SS_LOGICAL_UNIT_NOT_SUPPORTED;
  2532. +
  2533. + if (fsg->phase_error) {
  2534. + DBG(fsg, "sending phase-error status\n");
  2535. + status = US_BULK_STAT_PHASE;
  2536. + sd = SS_INVALID_COMMAND;
  2537. + } else if (sd != SS_NO_SENSE) {
  2538. + DBG(fsg, "sending command-failure status\n");
  2539. + status = US_BULK_STAT_FAIL;
  2540. + VDBG(fsg, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
  2541. + " info x%x\n",
  2542. + SK(sd), ASC(sd), ASCQ(sd), sdinfo);
  2543. + }
  2544. +
  2545. + if (transport_is_bbb()) {
  2546. + struct bulk_cs_wrap *csw = bh->buf;
  2547. +
  2548. + /* Store and send the Bulk-only CSW */
  2549. + csw->Signature = cpu_to_le32(US_BULK_CS_SIGN);
  2550. + csw->Tag = fsg->tag;
  2551. + csw->Residue = cpu_to_le32(fsg->residue);
  2552. + csw->Status = status;
  2553. +
  2554. + bh->inreq->length = US_BULK_CS_WRAP_LEN;
  2555. + bh->inreq->zero = 0;
  2556. + start_transfer(fsg, fsg->bulk_in, bh->inreq,
  2557. + &bh->inreq_busy, &bh->state);
  2558. +
  2559. + } else if (mod_data.transport_type == USB_PR_CB) {
  2560. +
  2561. + /* Control-Bulk transport has no status phase! */
  2562. + return 0;
  2563. +
  2564. + } else { // USB_PR_CBI
  2565. + struct interrupt_data *buf = bh->buf;
  2566. +
  2567. + /* Store and send the Interrupt data. UFI sends the ASC
  2568. + * and ASCQ bytes. Everything else sends a Type (which
  2569. + * is always 0) and the status Value. */
  2570. + if (mod_data.protocol_type == USB_SC_UFI) {
  2571. + buf->bType = ASC(sd);
  2572. + buf->bValue = ASCQ(sd);
  2573. + } else {
  2574. + buf->bType = 0;
  2575. + buf->bValue = status;
  2576. + }
  2577. + fsg->intreq->length = CBI_INTERRUPT_DATA_LEN;
  2578. +
  2579. + fsg->intr_buffhd = bh; // Point to the right buffhd
  2580. + fsg->intreq->buf = bh->inreq->buf;
  2581. + fsg->intreq->context = bh;
  2582. + start_transfer(fsg, fsg->intr_in, fsg->intreq,
  2583. + &fsg->intreq_busy, &bh->state);
  2584. + }
  2585. +
  2586. + fsg->next_buffhd_to_fill = bh->next;
  2587. + return 0;
  2588. +}
  2589. +
  2590. +
  2591. +/*-------------------------------------------------------------------------*/
  2592. +
  2593. +/* Check whether the command is properly formed and whether its data size
  2594. + * and direction agree with the values we already have. */
  2595. +static int check_command(struct fsg_dev *fsg, int cmnd_size,
  2596. + enum data_direction data_dir, unsigned int mask,
  2597. + int needs_medium, const char *name)
  2598. +{
  2599. + int i;
  2600. + int lun = fsg->cmnd[1] >> 5;
  2601. + static const char dirletter[4] = {'u', 'o', 'i', 'n'};
  2602. + char hdlen[20];
  2603. + struct fsg_lun *curlun;
  2604. +
  2605. + /* Adjust the expected cmnd_size for protocol encapsulation padding.
  2606. + * Transparent SCSI doesn't pad. */
  2607. + if (protocol_is_scsi())
  2608. + ;
  2609. +
  2610. + /* There's some disagreement as to whether RBC pads commands or not.
  2611. + * We'll play it safe and accept either form. */
  2612. + else if (mod_data.protocol_type == USB_SC_RBC) {
  2613. + if (fsg->cmnd_size == 12)
  2614. + cmnd_size = 12;
  2615. +
  2616. + /* All the other protocols pad to 12 bytes */
  2617. + } else
  2618. + cmnd_size = 12;
  2619. +
  2620. + hdlen[0] = 0;
  2621. + if (fsg->data_dir != DATA_DIR_UNKNOWN)
  2622. + sprintf(hdlen, ", H%c=%u", dirletter[(int) fsg->data_dir],
  2623. + fsg->data_size);
  2624. + VDBG(fsg, "SCSI command: %s; Dc=%d, D%c=%u; Hc=%d%s\n",
  2625. + name, cmnd_size, dirletter[(int) data_dir],
  2626. + fsg->data_size_from_cmnd, fsg->cmnd_size, hdlen);
  2627. +
  2628. + /* We can't reply at all until we know the correct data direction
  2629. + * and size. */
  2630. + if (fsg->data_size_from_cmnd == 0)
  2631. + data_dir = DATA_DIR_NONE;
  2632. + if (fsg->data_dir == DATA_DIR_UNKNOWN) { // CB or CBI
  2633. + fsg->data_dir = data_dir;
  2634. + fsg->data_size = fsg->data_size_from_cmnd;
  2635. +
  2636. + } else { // Bulk-only
  2637. + if (fsg->data_size < fsg->data_size_from_cmnd) {
  2638. +
  2639. + /* Host data size < Device data size is a phase error.
  2640. + * Carry out the command, but only transfer as much
  2641. + * as we are allowed. */
  2642. + fsg->data_size_from_cmnd = fsg->data_size;
  2643. + fsg->phase_error = 1;
  2644. + }
  2645. + }
  2646. + fsg->residue = fsg->usb_amount_left = fsg->data_size;
  2647. +
  2648. + /* Conflicting data directions is a phase error */
  2649. + if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) {
  2650. + fsg->phase_error = 1;
  2651. + return -EINVAL;
  2652. + }
  2653. +
  2654. + /* Verify the length of the command itself */
  2655. + if (cmnd_size != fsg->cmnd_size) {
  2656. +
  2657. + /* Special case workaround: There are plenty of buggy SCSI
  2658. + * implementations. Many have issues with cbw->Length
  2659. + * field passing a wrong command size. For those cases we
  2660. + * always try to work around the problem by using the length
  2661. + * sent by the host side provided it is at least as large
  2662. + * as the correct command length.
  2663. + * Examples of such cases would be MS-Windows, which issues
  2664. + * REQUEST SENSE with cbw->Length == 12 where it should
  2665. + * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and
  2666. + * REQUEST SENSE with cbw->Length == 10 where it should
  2667. + * be 6 as well.
  2668. + */
  2669. + if (cmnd_size <= fsg->cmnd_size) {
  2670. + DBG(fsg, "%s is buggy! Expected length %d "
  2671. + "but we got %d\n", name,
  2672. + cmnd_size, fsg->cmnd_size);
  2673. + cmnd_size = fsg->cmnd_size;
  2674. + } else {
  2675. + fsg->phase_error = 1;
  2676. + return -EINVAL;
  2677. + }
  2678. + }
  2679. +
  2680. + /* Check that the LUN values are consistent */
  2681. + if (transport_is_bbb()) {
  2682. + if (fsg->lun != lun)
  2683. + DBG(fsg, "using LUN %d from CBW, "
  2684. + "not LUN %d from CDB\n",
  2685. + fsg->lun, lun);
  2686. + }
  2687. +
  2688. + /* Check the LUN */
  2689. + curlun = fsg->curlun;
  2690. + if (curlun) {
  2691. + if (fsg->cmnd[0] != REQUEST_SENSE) {
  2692. + curlun->sense_data = SS_NO_SENSE;
  2693. + curlun->sense_data_info = 0;
  2694. + curlun->info_valid = 0;
  2695. + }
  2696. + } else {
  2697. + fsg->bad_lun_okay = 0;
  2698. +
  2699. + /* INQUIRY and REQUEST SENSE commands are explicitly allowed
  2700. + * to use unsupported LUNs; all others may not. */
  2701. + if (fsg->cmnd[0] != INQUIRY &&
  2702. + fsg->cmnd[0] != REQUEST_SENSE) {
  2703. + DBG(fsg, "unsupported LUN %d\n", fsg->lun);
  2704. + return -EINVAL;
  2705. + }
  2706. + }
  2707. +
  2708. + /* If a unit attention condition exists, only INQUIRY and
  2709. + * REQUEST SENSE commands are allowed; anything else must fail. */
  2710. + if (curlun && curlun->unit_attention_data != SS_NO_SENSE &&
  2711. + fsg->cmnd[0] != INQUIRY &&
  2712. + fsg->cmnd[0] != REQUEST_SENSE) {
  2713. + curlun->sense_data = curlun->unit_attention_data;
  2714. + curlun->unit_attention_data = SS_NO_SENSE;
  2715. + return -EINVAL;
  2716. + }
  2717. +
  2718. + /* Check that only command bytes listed in the mask are non-zero */
  2719. + fsg->cmnd[1] &= 0x1f; // Mask away the LUN
  2720. + for (i = 1; i < cmnd_size; ++i) {
  2721. + if (fsg->cmnd[i] && !(mask & (1 << i))) {
  2722. + if (curlun)
  2723. + curlun->sense_data = SS_INVALID_FIELD_IN_CDB;
  2724. + return -EINVAL;
  2725. + }
  2726. + }
  2727. +
  2728. + /* If the medium isn't mounted and the command needs to access
  2729. + * it, return an error. */
  2730. + if (curlun && !fsg_lun_is_open(curlun) && needs_medium) {
  2731. + curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
  2732. + return -EINVAL;
  2733. + }
  2734. +
  2735. + return 0;
  2736. +}
  2737. +
  2738. +/* wrapper of check_command for data size in blocks handling */
  2739. +static int check_command_size_in_blocks(struct fsg_dev *fsg, int cmnd_size,
  2740. + enum data_direction data_dir, unsigned int mask,
  2741. + int needs_medium, const char *name)
  2742. +{
  2743. + if (fsg->curlun)
  2744. + fsg->data_size_from_cmnd <<= fsg->curlun->blkbits;
  2745. + return check_command(fsg, cmnd_size, data_dir,
  2746. + mask, needs_medium, name);
  2747. +}
  2748. +
  2749. +static int do_scsi_command(struct fsg_dev *fsg)
  2750. +{
  2751. + struct fsg_buffhd *bh;
  2752. + int rc;
  2753. + int reply = -EINVAL;
  2754. + int i;
  2755. + static char unknown[16];
  2756. +
  2757. + dump_cdb(fsg);
  2758. +
  2759. + /* Wait for the next buffer to become available for data or status */
  2760. + bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill;
  2761. + while (bh->state != BUF_STATE_EMPTY) {
  2762. + rc = sleep_thread(fsg);
  2763. + if (rc)
  2764. + return rc;
  2765. + }
  2766. + fsg->phase_error = 0;
  2767. + fsg->short_packet_received = 0;
  2768. +
  2769. + down_read(&fsg->filesem); // We're using the backing file
  2770. + switch (fsg->cmnd[0]) {
  2771. +
  2772. + case INQUIRY:
  2773. + fsg->data_size_from_cmnd = fsg->cmnd[4];
  2774. + if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
  2775. + (1<<4), 0,
  2776. + "INQUIRY")) == 0)
  2777. + reply = do_inquiry(fsg, bh);
  2778. + break;
  2779. +
  2780. + case MODE_SELECT:
  2781. + fsg->data_size_from_cmnd = fsg->cmnd[4];
  2782. + if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST,
  2783. + (1<<1) | (1<<4), 0,
  2784. + "MODE SELECT(6)")) == 0)
  2785. + reply = do_mode_select(fsg, bh);
  2786. + break;
  2787. +
  2788. + case MODE_SELECT_10:
  2789. + fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
  2790. + if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST,
  2791. + (1<<1) | (3<<7), 0,
  2792. + "MODE SELECT(10)")) == 0)
  2793. + reply = do_mode_select(fsg, bh);
  2794. + break;
  2795. +
  2796. + case MODE_SENSE:
  2797. + fsg->data_size_from_cmnd = fsg->cmnd[4];
  2798. + if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
  2799. + (1<<1) | (1<<2) | (1<<4), 0,
  2800. + "MODE SENSE(6)")) == 0)
  2801. + reply = do_mode_sense(fsg, bh);
  2802. + break;
  2803. +
  2804. + case MODE_SENSE_10:
  2805. + fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
  2806. + if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
  2807. + (1<<1) | (1<<2) | (3<<7), 0,
  2808. + "MODE SENSE(10)")) == 0)
  2809. + reply = do_mode_sense(fsg, bh);
  2810. + break;
  2811. +
  2812. + case ALLOW_MEDIUM_REMOVAL:
  2813. + fsg->data_size_from_cmnd = 0;
  2814. + if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
  2815. + (1<<4), 0,
  2816. + "PREVENT-ALLOW MEDIUM REMOVAL")) == 0)
  2817. + reply = do_prevent_allow(fsg);
  2818. + break;
  2819. +
  2820. + case READ_6:
  2821. + i = fsg->cmnd[4];
  2822. + fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
  2823. + if ((reply = check_command_size_in_blocks(fsg, 6,
  2824. + DATA_DIR_TO_HOST,
  2825. + (7<<1) | (1<<4), 1,
  2826. + "READ(6)")) == 0)
  2827. + reply = do_read(fsg);
  2828. + break;
  2829. +
  2830. + case READ_10:
  2831. + fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
  2832. + if ((reply = check_command_size_in_blocks(fsg, 10,
  2833. + DATA_DIR_TO_HOST,
  2834. + (1<<1) | (0xf<<2) | (3<<7), 1,
  2835. + "READ(10)")) == 0)
  2836. + reply = do_read(fsg);
  2837. + break;
  2838. +
  2839. + case READ_12:
  2840. + fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
  2841. + if ((reply = check_command_size_in_blocks(fsg, 12,
  2842. + DATA_DIR_TO_HOST,
  2843. + (1<<1) | (0xf<<2) | (0xf<<6), 1,
  2844. + "READ(12)")) == 0)
  2845. + reply = do_read(fsg);
  2846. + break;
  2847. +
  2848. + case READ_CAPACITY:
  2849. + fsg->data_size_from_cmnd = 8;
  2850. + if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
  2851. + (0xf<<2) | (1<<8), 1,
  2852. + "READ CAPACITY")) == 0)
  2853. + reply = do_read_capacity(fsg, bh);
  2854. + break;
  2855. +
  2856. + case READ_HEADER:
  2857. + if (!mod_data.cdrom)
  2858. + goto unknown_cmnd;
  2859. + fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
  2860. + if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
  2861. + (3<<7) | (0x1f<<1), 1,
  2862. + "READ HEADER")) == 0)
  2863. + reply = do_read_header(fsg, bh);
  2864. + break;
  2865. +
  2866. + case READ_TOC:
  2867. + if (!mod_data.cdrom)
  2868. + goto unknown_cmnd;
  2869. + fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
  2870. + if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
  2871. + (7<<6) | (1<<1), 1,
  2872. + "READ TOC")) == 0)
  2873. + reply = do_read_toc(fsg, bh);
  2874. + break;
  2875. +
  2876. + case READ_FORMAT_CAPACITIES:
  2877. + fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
  2878. + if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST,
  2879. + (3<<7), 1,
  2880. + "READ FORMAT CAPACITIES")) == 0)
  2881. + reply = do_read_format_capacities(fsg, bh);
  2882. + break;
  2883. +
  2884. + case REQUEST_SENSE:
  2885. + fsg->data_size_from_cmnd = fsg->cmnd[4];
  2886. + if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST,
  2887. + (1<<4), 0,
  2888. + "REQUEST SENSE")) == 0)
  2889. + reply = do_request_sense(fsg, bh);
  2890. + break;
  2891. +
  2892. + case START_STOP:
  2893. + fsg->data_size_from_cmnd = 0;
  2894. + if ((reply = check_command(fsg, 6, DATA_DIR_NONE,
  2895. + (1<<1) | (1<<4), 0,
  2896. + "START-STOP UNIT")) == 0)
  2897. + reply = do_start_stop(fsg);
  2898. + break;
  2899. +
  2900. + case SYNCHRONIZE_CACHE:
  2901. + fsg->data_size_from_cmnd = 0;
  2902. + if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
  2903. + (0xf<<2) | (3<<7), 1,
  2904. + "SYNCHRONIZE CACHE")) == 0)
  2905. + reply = do_synchronize_cache(fsg);
  2906. + break;
  2907. +
  2908. + case TEST_UNIT_READY:
  2909. + fsg->data_size_from_cmnd = 0;
  2910. + reply = check_command(fsg, 6, DATA_DIR_NONE,
  2911. + 0, 1,
  2912. + "TEST UNIT READY");
  2913. + break;
  2914. +
  2915. + /* Although optional, this command is used by MS-Windows. We
  2916. + * support a minimal version: BytChk must be 0. */
  2917. + case VERIFY:
  2918. + fsg->data_size_from_cmnd = 0;
  2919. + if ((reply = check_command(fsg, 10, DATA_DIR_NONE,
  2920. + (1<<1) | (0xf<<2) | (3<<7), 1,
  2921. + "VERIFY")) == 0)
  2922. + reply = do_verify(fsg);
  2923. + break;
  2924. +
  2925. + case WRITE_6:
  2926. + i = fsg->cmnd[4];
  2927. + fsg->data_size_from_cmnd = (i == 0) ? 256 : i;
  2928. + if ((reply = check_command_size_in_blocks(fsg, 6,
  2929. + DATA_DIR_FROM_HOST,
  2930. + (7<<1) | (1<<4), 1,
  2931. + "WRITE(6)")) == 0)
  2932. + reply = do_write(fsg);
  2933. + break;
  2934. +
  2935. + case WRITE_10:
  2936. + fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]);
  2937. + if ((reply = check_command_size_in_blocks(fsg, 10,
  2938. + DATA_DIR_FROM_HOST,
  2939. + (1<<1) | (0xf<<2) | (3<<7), 1,
  2940. + "WRITE(10)")) == 0)
  2941. + reply = do_write(fsg);
  2942. + break;
  2943. +
  2944. + case WRITE_12:
  2945. + fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]);
  2946. + if ((reply = check_command_size_in_blocks(fsg, 12,
  2947. + DATA_DIR_FROM_HOST,
  2948. + (1<<1) | (0xf<<2) | (0xf<<6), 1,
  2949. + "WRITE(12)")) == 0)
  2950. + reply = do_write(fsg);
  2951. + break;
  2952. +
  2953. + /* Some mandatory commands that we recognize but don't implement.
  2954. + * They don't mean much in this setting. It's left as an exercise
  2955. + * for anyone interested to implement RESERVE and RELEASE in terms
  2956. + * of Posix locks. */
  2957. + case FORMAT_UNIT:
  2958. + case RELEASE:
  2959. + case RESERVE:
  2960. + case SEND_DIAGNOSTIC:
  2961. + // Fall through
  2962. +
  2963. + default:
  2964. + unknown_cmnd:
  2965. + fsg->data_size_from_cmnd = 0;
  2966. + sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);
  2967. + if ((reply = check_command(fsg, fsg->cmnd_size,
  2968. + DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) {
  2969. + fsg->curlun->sense_data = SS_INVALID_COMMAND;
  2970. + reply = -EINVAL;
  2971. + }
  2972. + break;
  2973. + }
  2974. + up_read(&fsg->filesem);
  2975. +
  2976. + if (reply == -EINTR || signal_pending(current))
  2977. + return -EINTR;
  2978. +
  2979. + /* Set up the single reply buffer for finish_reply() */
  2980. + if (reply == -EINVAL)
  2981. + reply = 0; // Error reply length
  2982. + if (reply >= 0 && fsg->data_dir == DATA_DIR_TO_HOST) {
  2983. + reply = min((u32) reply, fsg->data_size_from_cmnd);
  2984. + bh->inreq->length = reply;
  2985. + bh->state = BUF_STATE_FULL;
  2986. + fsg->residue -= reply;
  2987. + } // Otherwise it's already set
  2988. +
  2989. + return 0;
  2990. +}
  2991. +
  2992. +
  2993. +/*-------------------------------------------------------------------------*/
  2994. +
  2995. +static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
  2996. +{
  2997. + struct usb_request *req = bh->outreq;
  2998. + struct bulk_cb_wrap *cbw = req->buf;
  2999. +
  3000. + /* Was this a real packet? Should it be ignored? */
  3001. + if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
  3002. + return -EINVAL;
  3003. +
  3004. + /* Is the CBW valid? */
  3005. + if (req->actual != US_BULK_CB_WRAP_LEN ||
  3006. + cbw->Signature != cpu_to_le32(
  3007. + US_BULK_CB_SIGN)) {
  3008. + DBG(fsg, "invalid CBW: len %u sig 0x%x\n",
  3009. + req->actual,
  3010. + le32_to_cpu(cbw->Signature));
  3011. +
  3012. + /* The Bulk-only spec says we MUST stall the IN endpoint
  3013. + * (6.6.1), so it's unavoidable. It also says we must
  3014. + * retain this state until the next reset, but there's
  3015. + * no way to tell the controller driver it should ignore
  3016. + * Clear-Feature(HALT) requests.
  3017. + *
  3018. + * We aren't required to halt the OUT endpoint; instead
  3019. + * we can simply accept and discard any data received
  3020. + * until the next reset. */
  3021. + wedge_bulk_in_endpoint(fsg);
  3022. + set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
  3023. + return -EINVAL;
  3024. + }
  3025. +
  3026. + /* Is the CBW meaningful? */
  3027. + if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
  3028. + cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
  3029. + DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
  3030. + "cmdlen %u\n",
  3031. + cbw->Lun, cbw->Flags, cbw->Length);
  3032. +
  3033. + /* We can do anything we want here, so let's stall the
  3034. + * bulk pipes if we are allowed to. */
  3035. + if (mod_data.can_stall) {
  3036. + fsg_set_halt(fsg, fsg->bulk_out);
  3037. + halt_bulk_in_endpoint(fsg);
  3038. + }
  3039. + return -EINVAL;
  3040. + }
  3041. +
  3042. + /* Save the command for later */
  3043. + fsg->cmnd_size = cbw->Length;
  3044. + memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size);
  3045. + if (cbw->Flags & US_BULK_FLAG_IN)
  3046. + fsg->data_dir = DATA_DIR_TO_HOST;
  3047. + else
  3048. + fsg->data_dir = DATA_DIR_FROM_HOST;
  3049. + fsg->data_size = le32_to_cpu(cbw->DataTransferLength);
  3050. + if (fsg->data_size == 0)
  3051. + fsg->data_dir = DATA_DIR_NONE;
  3052. + fsg->lun = cbw->Lun;
  3053. + fsg->tag = cbw->Tag;
  3054. + return 0;
  3055. +}
  3056. +
  3057. +
  3058. +static int get_next_command(struct fsg_dev *fsg)
  3059. +{
  3060. + struct fsg_buffhd *bh;
  3061. + int rc = 0;
  3062. +
  3063. + if (transport_is_bbb()) {
  3064. +
  3065. + /* Wait for the next buffer to become available */
  3066. + bh = fsg->next_buffhd_to_fill;
  3067. + while (bh->state != BUF_STATE_EMPTY) {
  3068. + rc = sleep_thread(fsg);
  3069. + if (rc)
  3070. + return rc;
  3071. + }
  3072. +
  3073. + /* Queue a request to read a Bulk-only CBW */
  3074. + set_bulk_out_req_length(fsg, bh, US_BULK_CB_WRAP_LEN);
  3075. + start_transfer(fsg, fsg->bulk_out, bh->outreq,
  3076. + &bh->outreq_busy, &bh->state);
  3077. +
  3078. + /* We will drain the buffer in software, which means we
  3079. + * can reuse it for the next filling. No need to advance
  3080. + * next_buffhd_to_fill. */
  3081. +
  3082. + /* Wait for the CBW to arrive */
  3083. + while (bh->state != BUF_STATE_FULL) {
  3084. + rc = sleep_thread(fsg);
  3085. + if (rc)
  3086. + return rc;
  3087. + }
  3088. + smp_rmb();
  3089. + rc = received_cbw(fsg, bh);
  3090. + bh->state = BUF_STATE_EMPTY;
  3091. +
  3092. + } else { // USB_PR_CB or USB_PR_CBI
  3093. +
  3094. + /* Wait for the next command to arrive */
  3095. + while (fsg->cbbuf_cmnd_size == 0) {
  3096. + rc = sleep_thread(fsg);
  3097. + if (rc)
  3098. + return rc;
  3099. + }
  3100. +
  3101. + /* Is the previous status interrupt request still busy?
  3102. + * The host is allowed to skip reading the status,
  3103. + * so we must cancel it. */
  3104. + if (fsg->intreq_busy)
  3105. + usb_ep_dequeue(fsg->intr_in, fsg->intreq);
  3106. +
  3107. + /* Copy the command and mark the buffer empty */
  3108. + fsg->data_dir = DATA_DIR_UNKNOWN;
  3109. + spin_lock_irq(&fsg->lock);
  3110. + fsg->cmnd_size = fsg->cbbuf_cmnd_size;
  3111. + memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size);
  3112. + fsg->cbbuf_cmnd_size = 0;
  3113. + spin_unlock_irq(&fsg->lock);
  3114. +
  3115. + /* Use LUN from the command */
  3116. + fsg->lun = fsg->cmnd[1] >> 5;
  3117. + }
  3118. +
  3119. + /* Update current lun */
  3120. + if (fsg->lun >= 0 && fsg->lun < fsg->nluns)
  3121. + fsg->curlun = &fsg->luns[fsg->lun];
  3122. + else
  3123. + fsg->curlun = NULL;
  3124. +
  3125. + return rc;
  3126. +}
  3127. +
  3128. +
  3129. +/*-------------------------------------------------------------------------*/
  3130. +
  3131. +static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep,
  3132. + const struct usb_endpoint_descriptor *d)
  3133. +{
  3134. + int rc;
  3135. +
  3136. + ep->driver_data = fsg;
  3137. + ep->desc = d;
  3138. + rc = usb_ep_enable(ep);
  3139. + if (rc)
  3140. + ERROR(fsg, "can't enable %s, result %d\n", ep->name, rc);
  3141. + return rc;
  3142. +}
  3143. +
  3144. +static int alloc_request(struct fsg_dev *fsg, struct usb_ep *ep,
  3145. + struct usb_request **preq)
  3146. +{
  3147. + *preq = usb_ep_alloc_request(ep, GFP_ATOMIC);
  3148. + if (*preq)
  3149. + return 0;
  3150. + ERROR(fsg, "can't allocate request for %s\n", ep->name);
  3151. + return -ENOMEM;
  3152. +}
  3153. +
  3154. +/*
  3155. + * Reset interface setting and re-init endpoint state (toggle etc).
  3156. + * Call with altsetting < 0 to disable the interface. The only other
  3157. + * available altsetting is 0, which enables the interface.
  3158. + */
  3159. +static int do_set_interface(struct fsg_dev *fsg, int altsetting)
  3160. +{
  3161. + int rc = 0;
  3162. + int i;
  3163. + const struct usb_endpoint_descriptor *d;
  3164. +
  3165. + if (fsg->running)
  3166. + DBG(fsg, "reset interface\n");
  3167. +
  3168. +reset:
  3169. + /* Deallocate the requests */
  3170. + for (i = 0; i < fsg_num_buffers; ++i) {
  3171. + struct fsg_buffhd *bh = &fsg->buffhds[i];
  3172. +
  3173. + if (bh->inreq) {
  3174. + usb_ep_free_request(fsg->bulk_in, bh->inreq);
  3175. + bh->inreq = NULL;
  3176. + }
  3177. + if (bh->outreq) {
  3178. + usb_ep_free_request(fsg->bulk_out, bh->outreq);
  3179. + bh->outreq = NULL;
  3180. + }
  3181. + }
  3182. + if (fsg->intreq) {
  3183. + usb_ep_free_request(fsg->intr_in, fsg->intreq);
  3184. + fsg->intreq = NULL;
  3185. + }
  3186. +
  3187. + /* Disable the endpoints */
  3188. + if (fsg->bulk_in_enabled) {
  3189. + usb_ep_disable(fsg->bulk_in);
  3190. + fsg->bulk_in_enabled = 0;
  3191. + }
  3192. + if (fsg->bulk_out_enabled) {
  3193. + usb_ep_disable(fsg->bulk_out);
  3194. + fsg->bulk_out_enabled = 0;
  3195. + }
  3196. + if (fsg->intr_in_enabled) {
  3197. + usb_ep_disable(fsg->intr_in);
  3198. + fsg->intr_in_enabled = 0;
  3199. + }
  3200. +
  3201. + fsg->running = 0;
  3202. + if (altsetting < 0 || rc != 0)
  3203. + return rc;
  3204. +
  3205. + DBG(fsg, "set interface %d\n", altsetting);
  3206. +
  3207. + /* Enable the endpoints */
  3208. + d = fsg_ep_desc(fsg->gadget,
  3209. + &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc,
  3210. + &fsg_ss_bulk_in_desc);
  3211. + if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0)
  3212. + goto reset;
  3213. + fsg->bulk_in_enabled = 1;
  3214. +
  3215. + d = fsg_ep_desc(fsg->gadget,
  3216. + &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc,
  3217. + &fsg_ss_bulk_out_desc);
  3218. + if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0)
  3219. + goto reset;
  3220. + fsg->bulk_out_enabled = 1;
  3221. + fsg->bulk_out_maxpacket = usb_endpoint_maxp(d);
  3222. + clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
  3223. +
  3224. + if (transport_is_cbi()) {
  3225. + d = fsg_ep_desc(fsg->gadget,
  3226. + &fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc,
  3227. + &fsg_ss_intr_in_desc);
  3228. + if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0)
  3229. + goto reset;
  3230. + fsg->intr_in_enabled = 1;
  3231. + }
  3232. +
  3233. + /* Allocate the requests */
  3234. + for (i = 0; i < fsg_num_buffers; ++i) {
  3235. + struct fsg_buffhd *bh = &fsg->buffhds[i];
  3236. +
  3237. + if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0)
  3238. + goto reset;
  3239. + if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0)
  3240. + goto reset;
  3241. + bh->inreq->buf = bh->outreq->buf = bh->buf;
  3242. + bh->inreq->context = bh->outreq->context = bh;
  3243. + bh->inreq->complete = bulk_in_complete;
  3244. + bh->outreq->complete = bulk_out_complete;
  3245. + }
  3246. + if (transport_is_cbi()) {
  3247. + if ((rc = alloc_request(fsg, fsg->intr_in, &fsg->intreq)) != 0)
  3248. + goto reset;
  3249. + fsg->intreq->complete = intr_in_complete;
  3250. + }
  3251. +
  3252. + fsg->running = 1;
  3253. + for (i = 0; i < fsg->nluns; ++i)
  3254. + fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
  3255. + return rc;
  3256. +}
  3257. +
  3258. +
  3259. +/*
  3260. + * Change our operational configuration. This code must agree with the code
  3261. + * that returns config descriptors, and with interface altsetting code.
  3262. + *
  3263. + * It's also responsible for power management interactions. Some
  3264. + * configurations might not work with our current power sources.
  3265. + * For now we just assume the gadget is always self-powered.
  3266. + */
  3267. +static int do_set_config(struct fsg_dev *fsg, u8 new_config)
  3268. +{
  3269. + int rc = 0;
  3270. +
  3271. + /* Disable the single interface */
  3272. + if (fsg->config != 0) {
  3273. + DBG(fsg, "reset config\n");
  3274. + fsg->config = 0;
  3275. + rc = do_set_interface(fsg, -1);
  3276. + }
  3277. +
  3278. + /* Enable the interface */
  3279. + if (new_config != 0) {
  3280. + fsg->config = new_config;
  3281. + if ((rc = do_set_interface(fsg, 0)) != 0)
  3282. + fsg->config = 0; // Reset on errors
  3283. + else
  3284. + INFO(fsg, "%s config #%d\n",
  3285. + usb_speed_string(fsg->gadget->speed),
  3286. + fsg->config);
  3287. + }
  3288. + return rc;
  3289. +}
  3290. +
  3291. +
  3292. +/*-------------------------------------------------------------------------*/
  3293. +
  3294. +static void handle_exception(struct fsg_dev *fsg)
  3295. +{
  3296. + siginfo_t info;
  3297. + int sig;
  3298. + int i;
  3299. + int num_active;
  3300. + struct fsg_buffhd *bh;
  3301. + enum fsg_state old_state;
  3302. + u8 new_config;
  3303. + struct fsg_lun *curlun;
  3304. + unsigned int exception_req_tag;
  3305. + int rc;
  3306. +
  3307. + /* Clear the existing signals. Anything but SIGUSR1 is converted
  3308. + * into a high-priority EXIT exception. */
  3309. + for (;;) {
  3310. + sig = dequeue_signal_lock(current, &current->blocked, &info);
  3311. + if (!sig)
  3312. + break;
  3313. + if (sig != SIGUSR1) {
  3314. + if (fsg->state < FSG_STATE_EXIT)
  3315. + DBG(fsg, "Main thread exiting on signal\n");
  3316. + raise_exception(fsg, FSG_STATE_EXIT);
  3317. + }
  3318. + }
  3319. +
  3320. + /* Cancel all the pending transfers */
  3321. + if (fsg->intreq_busy)
  3322. + usb_ep_dequeue(fsg->intr_in, fsg->intreq);
  3323. + for (i = 0; i < fsg_num_buffers; ++i) {
  3324. + bh = &fsg->buffhds[i];
  3325. + if (bh->inreq_busy)
  3326. + usb_ep_dequeue(fsg->bulk_in, bh->inreq);
  3327. + if (bh->outreq_busy)
  3328. + usb_ep_dequeue(fsg->bulk_out, bh->outreq);
  3329. + }
  3330. +
  3331. + /* Wait until everything is idle */
  3332. + for (;;) {
  3333. + num_active = fsg->intreq_busy;
  3334. + for (i = 0; i < fsg_num_buffers; ++i) {
  3335. + bh = &fsg->buffhds[i];
  3336. + num_active += bh->inreq_busy + bh->outreq_busy;
  3337. + }
  3338. + if (num_active == 0)
  3339. + break;
  3340. + if (sleep_thread(fsg))
  3341. + return;
  3342. + }
  3343. +
  3344. + /* Clear out the controller's fifos */
  3345. + if (fsg->bulk_in_enabled)
  3346. + usb_ep_fifo_flush(fsg->bulk_in);
  3347. + if (fsg->bulk_out_enabled)
  3348. + usb_ep_fifo_flush(fsg->bulk_out);
  3349. + if (fsg->intr_in_enabled)
  3350. + usb_ep_fifo_flush(fsg->intr_in);
  3351. +
  3352. + /* Reset the I/O buffer states and pointers, the SCSI
  3353. + * state, and the exception. Then invoke the handler. */
  3354. + spin_lock_irq(&fsg->lock);
  3355. +
  3356. + for (i = 0; i < fsg_num_buffers; ++i) {
  3357. + bh = &fsg->buffhds[i];
  3358. + bh->state = BUF_STATE_EMPTY;
  3359. + }
  3360. + fsg->next_buffhd_to_fill = fsg->next_buffhd_to_drain =
  3361. + &fsg->buffhds[0];
  3362. +
  3363. + exception_req_tag = fsg->exception_req_tag;
  3364. + new_config = fsg->new_config;
  3365. + old_state = fsg->state;
  3366. +
  3367. + if (old_state == FSG_STATE_ABORT_BULK_OUT)
  3368. + fsg->state = FSG_STATE_STATUS_PHASE;
  3369. + else {
  3370. + for (i = 0; i < fsg->nluns; ++i) {
  3371. + curlun = &fsg->luns[i];
  3372. + curlun->prevent_medium_removal = 0;
  3373. + curlun->sense_data = curlun->unit_attention_data =
  3374. + SS_NO_SENSE;
  3375. + curlun->sense_data_info = 0;
  3376. + curlun->info_valid = 0;
  3377. + }
  3378. + fsg->state = FSG_STATE_IDLE;
  3379. + }
  3380. + spin_unlock_irq(&fsg->lock);
  3381. +
  3382. + /* Carry out any extra actions required for the exception */
  3383. + switch (old_state) {
  3384. + default:
  3385. + break;
  3386. +
  3387. + case FSG_STATE_ABORT_BULK_OUT:
  3388. + send_status(fsg);
  3389. + spin_lock_irq(&fsg->lock);
  3390. + if (fsg->state == FSG_STATE_STATUS_PHASE)
  3391. + fsg->state = FSG_STATE_IDLE;
  3392. + spin_unlock_irq(&fsg->lock);
  3393. + break;
  3394. +
  3395. + case FSG_STATE_RESET:
  3396. + /* In case we were forced against our will to halt a
  3397. + * bulk endpoint, clear the halt now. (The SuperH UDC
  3398. + * requires this.) */
  3399. + if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
  3400. + usb_ep_clear_halt(fsg->bulk_in);
  3401. +
  3402. + if (transport_is_bbb()) {
  3403. + if (fsg->ep0_req_tag == exception_req_tag)
  3404. + ep0_queue(fsg); // Complete the status stage
  3405. +
  3406. + } else if (transport_is_cbi())
  3407. + send_status(fsg); // Status by interrupt pipe
  3408. +
  3409. + /* Technically this should go here, but it would only be
  3410. + * a waste of time. Ditto for the INTERFACE_CHANGE and
  3411. + * CONFIG_CHANGE cases. */
  3412. + // for (i = 0; i < fsg->nluns; ++i)
  3413. + // fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED;
  3414. + break;
  3415. +
  3416. + case FSG_STATE_INTERFACE_CHANGE:
  3417. + rc = do_set_interface(fsg, 0);
  3418. + if (fsg->ep0_req_tag != exception_req_tag)
  3419. + break;
  3420. + if (rc != 0) // STALL on errors
  3421. + fsg_set_halt(fsg, fsg->ep0);
  3422. + else // Complete the status stage
  3423. + ep0_queue(fsg);
  3424. + break;
  3425. +
  3426. + case FSG_STATE_CONFIG_CHANGE:
  3427. + rc = do_set_config(fsg, new_config);
  3428. + if (fsg->ep0_req_tag != exception_req_tag)
  3429. + break;
  3430. + if (rc != 0) // STALL on errors
  3431. + fsg_set_halt(fsg, fsg->ep0);
  3432. + else // Complete the status stage
  3433. + ep0_queue(fsg);
  3434. + break;
  3435. +
  3436. + case FSG_STATE_DISCONNECT:
  3437. + for (i = 0; i < fsg->nluns; ++i)
  3438. + fsg_lun_fsync_sub(fsg->luns + i);
  3439. + do_set_config(fsg, 0); // Unconfigured state
  3440. + break;
  3441. +
  3442. + case FSG_STATE_EXIT:
  3443. + case FSG_STATE_TERMINATED:
  3444. + do_set_config(fsg, 0); // Free resources
  3445. + spin_lock_irq(&fsg->lock);
  3446. + fsg->state = FSG_STATE_TERMINATED; // Stop the thread
  3447. + spin_unlock_irq(&fsg->lock);
  3448. + break;
  3449. + }
  3450. +}
  3451. +
  3452. +
  3453. +/*-------------------------------------------------------------------------*/
  3454. +
  3455. +static int fsg_main_thread(void *fsg_)
  3456. +{
  3457. + struct fsg_dev *fsg = fsg_;
  3458. +
  3459. + /* Allow the thread to be killed by a signal, but set the signal mask
  3460. + * to block everything but INT, TERM, KILL, and USR1. */
  3461. + allow_signal(SIGINT);
  3462. + allow_signal(SIGTERM);
  3463. + allow_signal(SIGKILL);
  3464. + allow_signal(SIGUSR1);
  3465. +
  3466. + /* Allow the thread to be frozen */
  3467. + set_freezable();
  3468. +
  3469. + /* Arrange for userspace references to be interpreted as kernel
  3470. + * pointers. That way we can pass a kernel pointer to a routine
  3471. + * that expects a __user pointer and it will work okay. */
  3472. + set_fs(get_ds());
  3473. +
  3474. + /* The main loop */
  3475. + while (fsg->state != FSG_STATE_TERMINATED) {
  3476. + if (exception_in_progress(fsg) || signal_pending(current)) {
  3477. + handle_exception(fsg);
  3478. + continue;
  3479. + }
  3480. +
  3481. + if (!fsg->running) {
  3482. + sleep_thread(fsg);
  3483. + continue;
  3484. + }
  3485. +
  3486. + if (get_next_command(fsg))
  3487. + continue;
  3488. +
  3489. + spin_lock_irq(&fsg->lock);
  3490. + if (!exception_in_progress(fsg))
  3491. + fsg->state = FSG_STATE_DATA_PHASE;
  3492. + spin_unlock_irq(&fsg->lock);
  3493. +
  3494. + if (do_scsi_command(fsg) || finish_reply(fsg))
  3495. + continue;
  3496. +
  3497. + spin_lock_irq(&fsg->lock);
  3498. + if (!exception_in_progress(fsg))
  3499. + fsg->state = FSG_STATE_STATUS_PHASE;
  3500. + spin_unlock_irq(&fsg->lock);
  3501. +
  3502. + if (send_status(fsg))
  3503. + continue;
  3504. +
  3505. + spin_lock_irq(&fsg->lock);
  3506. + if (!exception_in_progress(fsg))
  3507. + fsg->state = FSG_STATE_IDLE;
  3508. + spin_unlock_irq(&fsg->lock);
  3509. + }
  3510. +
  3511. + spin_lock_irq(&fsg->lock);
  3512. + fsg->thread_task = NULL;
  3513. + spin_unlock_irq(&fsg->lock);
  3514. +
  3515. + /* If we are exiting because of a signal, unregister the
  3516. + * gadget driver. */
  3517. + if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
  3518. + usb_gadget_unregister_driver(&fsg_driver);
  3519. +
  3520. + /* Let the unbind and cleanup routines know the thread has exited */
  3521. + complete_and_exit(&fsg->thread_notifier, 0);
  3522. +}
  3523. +
  3524. +
  3525. +/*-------------------------------------------------------------------------*/
  3526. +
  3527. +
  3528. +/* The write permissions and store_xxx pointers are set in fsg_bind() */
  3529. +static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL);
  3530. +static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, NULL);
  3531. +static DEVICE_ATTR(file, 0444, fsg_show_file, NULL);
  3532. +
  3533. +
  3534. +/*-------------------------------------------------------------------------*/
  3535. +
  3536. +static void fsg_release(struct kref *ref)
  3537. +{
  3538. + struct fsg_dev *fsg = container_of(ref, struct fsg_dev, ref);
  3539. +
  3540. + kfree(fsg->luns);
  3541. + kfree(fsg);
  3542. +}
  3543. +
  3544. +static void lun_release(struct device *dev)
  3545. +{
  3546. + struct rw_semaphore *filesem = dev_get_drvdata(dev);
  3547. + struct fsg_dev *fsg =
  3548. + container_of(filesem, struct fsg_dev, filesem);
  3549. +
  3550. + kref_put(&fsg->ref, fsg_release);
  3551. +}
  3552. +
  3553. +static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
  3554. +{
  3555. + struct fsg_dev *fsg = get_gadget_data(gadget);
  3556. + int i;
  3557. + struct fsg_lun *curlun;
  3558. + struct usb_request *req = fsg->ep0req;
  3559. +
  3560. + DBG(fsg, "unbind\n");
  3561. + clear_bit(REGISTERED, &fsg->atomic_bitflags);
  3562. +
  3563. + /* If the thread isn't already dead, tell it to exit now */
  3564. + if (fsg->state != FSG_STATE_TERMINATED) {
  3565. + raise_exception(fsg, FSG_STATE_EXIT);
  3566. + wait_for_completion(&fsg->thread_notifier);
  3567. +
  3568. + /* The cleanup routine waits for this completion also */
  3569. + complete(&fsg->thread_notifier);
  3570. + }
  3571. +
  3572. + /* Unregister the sysfs attribute files and the LUNs */
  3573. + for (i = 0; i < fsg->nluns; ++i) {
  3574. + curlun = &fsg->luns[i];
  3575. + if (curlun->registered) {
  3576. + device_remove_file(&curlun->dev, &dev_attr_nofua);
  3577. + device_remove_file(&curlun->dev, &dev_attr_ro);
  3578. + device_remove_file(&curlun->dev, &dev_attr_file);
  3579. + fsg_lun_close(curlun);
  3580. + device_unregister(&curlun->dev);
  3581. + curlun->registered = 0;
  3582. + }
  3583. + }
  3584. +
  3585. + /* Free the data buffers */
  3586. + for (i = 0; i < fsg_num_buffers; ++i)
  3587. + kfree(fsg->buffhds[i].buf);
  3588. +
  3589. + /* Free the request and buffer for endpoint 0 */
  3590. + if (req) {
  3591. + kfree(req->buf);
  3592. + usb_ep_free_request(fsg->ep0, req);
  3593. + }
  3594. +
  3595. + set_gadget_data(gadget, NULL);
  3596. +}
  3597. +
  3598. +
  3599. +static int __init check_parameters(struct fsg_dev *fsg)
  3600. +{
  3601. + int prot;
  3602. + int gcnum;
  3603. +
  3604. + /* Store the default values */
  3605. + mod_data.transport_type = USB_PR_BULK;
  3606. + mod_data.transport_name = "Bulk-only";
  3607. + mod_data.protocol_type = USB_SC_SCSI;
  3608. + mod_data.protocol_name = "Transparent SCSI";
  3609. +
  3610. + /* Some peripheral controllers are known not to be able to
  3611. + * halt bulk endpoints correctly. If one of them is present,
  3612. + * disable stalls.
  3613. + */
  3614. + if (gadget_is_at91(fsg->gadget))
  3615. + mod_data.can_stall = 0;
  3616. +
  3617. + if (mod_data.release == 0xffff) { // Parameter wasn't set
  3618. + gcnum = usb_gadget_controller_number(fsg->gadget);
  3619. + if (gcnum >= 0)
  3620. + mod_data.release = 0x0300 + gcnum;
  3621. + else {
  3622. + WARNING(fsg, "controller '%s' not recognized\n",
  3623. + fsg->gadget->name);
  3624. + mod_data.release = 0x0399;
  3625. + }
  3626. + }
  3627. +
  3628. + prot = simple_strtol(mod_data.protocol_parm, NULL, 0);
  3629. +
  3630. +#ifdef CONFIG_USB_FILE_STORAGE_TEST
  3631. + if (strnicmp(mod_data.transport_parm, "BBB", 10) == 0) {
  3632. + ; // Use default setting
  3633. + } else if (strnicmp(mod_data.transport_parm, "CB", 10) == 0) {
  3634. + mod_data.transport_type = USB_PR_CB;
  3635. + mod_data.transport_name = "Control-Bulk";
  3636. + } else if (strnicmp(mod_data.transport_parm, "CBI", 10) == 0) {
  3637. + mod_data.transport_type = USB_PR_CBI;
  3638. + mod_data.transport_name = "Control-Bulk-Interrupt";
  3639. + } else {
  3640. + ERROR(fsg, "invalid transport: %s\n", mod_data.transport_parm);
  3641. + return -EINVAL;
  3642. + }
  3643. +
  3644. + if (strnicmp(mod_data.protocol_parm, "SCSI", 10) == 0 ||
  3645. + prot == USB_SC_SCSI) {
  3646. + ; // Use default setting
  3647. + } else if (strnicmp(mod_data.protocol_parm, "RBC", 10) == 0 ||
  3648. + prot == USB_SC_RBC) {
  3649. + mod_data.protocol_type = USB_SC_RBC;
  3650. + mod_data.protocol_name = "RBC";
  3651. + } else if (strnicmp(mod_data.protocol_parm, "8020", 4) == 0 ||
  3652. + strnicmp(mod_data.protocol_parm, "ATAPI", 10) == 0 ||
  3653. + prot == USB_SC_8020) {
  3654. + mod_data.protocol_type = USB_SC_8020;
  3655. + mod_data.protocol_name = "8020i (ATAPI)";
  3656. + } else if (strnicmp(mod_data.protocol_parm, "QIC", 3) == 0 ||
  3657. + prot == USB_SC_QIC) {
  3658. + mod_data.protocol_type = USB_SC_QIC;
  3659. + mod_data.protocol_name = "QIC-157";
  3660. + } else if (strnicmp(mod_data.protocol_parm, "UFI", 10) == 0 ||
  3661. + prot == USB_SC_UFI) {
  3662. + mod_data.protocol_type = USB_SC_UFI;
  3663. + mod_data.protocol_name = "UFI";
  3664. + } else if (strnicmp(mod_data.protocol_parm, "8070", 4) == 0 ||
  3665. + prot == USB_SC_8070) {
  3666. + mod_data.protocol_type = USB_SC_8070;
  3667. + mod_data.protocol_name = "8070i";
  3668. + } else {
  3669. + ERROR(fsg, "invalid protocol: %s\n", mod_data.protocol_parm);
  3670. + return -EINVAL;
  3671. + }
  3672. +
  3673. + mod_data.buflen &= PAGE_CACHE_MASK;
  3674. + if (mod_data.buflen <= 0) {
  3675. + ERROR(fsg, "invalid buflen\n");
  3676. + return -ETOOSMALL;
  3677. + }
  3678. +
  3679. +#endif /* CONFIG_USB_FILE_STORAGE_TEST */
  3680. +
  3681. + /* Serial string handling.
  3682. + * On a real device, the serial string would be loaded
  3683. + * from permanent storage. */
  3684. + if (mod_data.serial) {
  3685. + const char *ch;
  3686. + unsigned len = 0;
  3687. +
  3688. + /* Sanity check :
  3689. + * The CB[I] specification limits the serial string to
  3690. + * 12 uppercase hexadecimal characters.
  3691. + * BBB need at least 12 uppercase hexadecimal characters,
  3692. + * with a maximum of 126. */
  3693. + for (ch = mod_data.serial; *ch; ++ch) {
  3694. + ++len;
  3695. + if ((*ch < '0' || *ch > '9') &&
  3696. + (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */
  3697. + WARNING(fsg,
  3698. + "Invalid serial string character: %c\n",
  3699. + *ch);
  3700. + goto no_serial;
  3701. + }
  3702. + }
  3703. + if (len > 126 ||
  3704. + (mod_data.transport_type == USB_PR_BULK && len < 12) ||
  3705. + (mod_data.transport_type != USB_PR_BULK && len > 12)) {
  3706. + WARNING(fsg, "Invalid serial string length!\n");
  3707. + goto no_serial;
  3708. + }
  3709. + fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial;
  3710. + } else {
  3711. + WARNING(fsg, "No serial-number string provided!\n");
  3712. + no_serial:
  3713. + device_desc.iSerialNumber = 0;
  3714. + }
  3715. +
  3716. + return 0;
  3717. +}
  3718. +
  3719. +
  3720. +static int __init fsg_bind(struct usb_gadget *gadget)
  3721. +{
  3722. + struct fsg_dev *fsg = the_fsg;
  3723. + int rc;
  3724. + int i;
  3725. + struct fsg_lun *curlun;
  3726. + struct usb_ep *ep;
  3727. + struct usb_request *req;
  3728. + char *pathbuf, *p;
  3729. +
  3730. + fsg->gadget = gadget;
  3731. + set_gadget_data(gadget, fsg);
  3732. + fsg->ep0 = gadget->ep0;
  3733. + fsg->ep0->driver_data = fsg;
  3734. +
  3735. + if ((rc = check_parameters(fsg)) != 0)
  3736. + goto out;
  3737. +
  3738. + if (mod_data.removable) { // Enable the store_xxx attributes
  3739. + dev_attr_file.attr.mode = 0644;
  3740. + dev_attr_file.store = fsg_store_file;
  3741. + if (!mod_data.cdrom) {
  3742. + dev_attr_ro.attr.mode = 0644;
  3743. + dev_attr_ro.store = fsg_store_ro;
  3744. + }
  3745. + }
  3746. +
  3747. + /* Only for removable media? */
  3748. + dev_attr_nofua.attr.mode = 0644;
  3749. + dev_attr_nofua.store = fsg_store_nofua;
  3750. +
  3751. + /* Find out how many LUNs there should be */
  3752. + i = mod_data.nluns;
  3753. + if (i == 0)
  3754. + i = max(mod_data.num_filenames, 1u);
  3755. + if (i > FSG_MAX_LUNS) {
  3756. + ERROR(fsg, "invalid number of LUNs: %d\n", i);
  3757. + rc = -EINVAL;
  3758. + goto out;
  3759. + }
  3760. +
  3761. + /* Create the LUNs, open their backing files, and register the
  3762. + * LUN devices in sysfs. */
  3763. + fsg->luns = kzalloc(i * sizeof(struct fsg_lun), GFP_KERNEL);
  3764. + if (!fsg->luns) {
  3765. + rc = -ENOMEM;
  3766. + goto out;
  3767. + }
  3768. + fsg->nluns = i;
  3769. +
  3770. + for (i = 0; i < fsg->nluns; ++i) {
  3771. + curlun = &fsg->luns[i];
  3772. + curlun->cdrom = !!mod_data.cdrom;
  3773. + curlun->ro = mod_data.cdrom || mod_data.ro[i];
  3774. + curlun->initially_ro = curlun->ro;
  3775. + curlun->removable = mod_data.removable;
  3776. + curlun->nofua = mod_data.nofua[i];
  3777. + curlun->dev.release = lun_release;
  3778. + curlun->dev.parent = &gadget->dev;
  3779. + curlun->dev.driver = &fsg_driver.driver;
  3780. + dev_set_drvdata(&curlun->dev, &fsg->filesem);
  3781. + dev_set_name(&curlun->dev,"%s-lun%d",
  3782. + dev_name(&gadget->dev), i);
  3783. +
  3784. + kref_get(&fsg->ref);
  3785. + rc = device_register(&curlun->dev);
  3786. + if (rc) {
  3787. + INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
  3788. + put_device(&curlun->dev);
  3789. + goto out;
  3790. + }
  3791. + curlun->registered = 1;
  3792. +
  3793. + rc = device_create_file(&curlun->dev, &dev_attr_ro);
  3794. + if (rc)
  3795. + goto out;
  3796. + rc = device_create_file(&curlun->dev, &dev_attr_nofua);
  3797. + if (rc)
  3798. + goto out;
  3799. + rc = device_create_file(&curlun->dev, &dev_attr_file);
  3800. + if (rc)
  3801. + goto out;
  3802. +
  3803. + if (mod_data.file[i] && *mod_data.file[i]) {
  3804. + rc = fsg_lun_open(curlun, mod_data.file[i]);
  3805. + if (rc)
  3806. + goto out;
  3807. + } else if (!mod_data.removable) {
  3808. + ERROR(fsg, "no file given for LUN%d\n", i);
  3809. + rc = -EINVAL;
  3810. + goto out;
  3811. + }
  3812. + }
  3813. +
  3814. + /* Find all the endpoints we will use */
  3815. + usb_ep_autoconfig_reset(gadget);
  3816. + ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc);
  3817. + if (!ep)
  3818. + goto autoconf_fail;
  3819. + ep->driver_data = fsg; // claim the endpoint
  3820. + fsg->bulk_in = ep;
  3821. +
  3822. + ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc);
  3823. + if (!ep)
  3824. + goto autoconf_fail;
  3825. + ep->driver_data = fsg; // claim the endpoint
  3826. + fsg->bulk_out = ep;
  3827. +
  3828. + if (transport_is_cbi()) {
  3829. + ep = usb_ep_autoconfig(gadget, &fsg_fs_intr_in_desc);
  3830. + if (!ep)
  3831. + goto autoconf_fail;
  3832. + ep->driver_data = fsg; // claim the endpoint
  3833. + fsg->intr_in = ep;
  3834. + }
  3835. +
  3836. + /* Fix up the descriptors */
  3837. + device_desc.idVendor = cpu_to_le16(mod_data.vendor);
  3838. + device_desc.idProduct = cpu_to_le16(mod_data.product);
  3839. + device_desc.bcdDevice = cpu_to_le16(mod_data.release);
  3840. +
  3841. + i = (transport_is_cbi() ? 3 : 2); // Number of endpoints
  3842. + fsg_intf_desc.bNumEndpoints = i;
  3843. + fsg_intf_desc.bInterfaceSubClass = mod_data.protocol_type;
  3844. + fsg_intf_desc.bInterfaceProtocol = mod_data.transport_type;
  3845. + fsg_fs_function[i + FSG_FS_FUNCTION_PRE_EP_ENTRIES] = NULL;
  3846. +
  3847. + if (gadget_is_dualspeed(gadget)) {
  3848. + fsg_hs_function[i + FSG_HS_FUNCTION_PRE_EP_ENTRIES] = NULL;
  3849. +
  3850. + /* Assume endpoint addresses are the same for both speeds */
  3851. + fsg_hs_bulk_in_desc.bEndpointAddress =
  3852. + fsg_fs_bulk_in_desc.bEndpointAddress;
  3853. + fsg_hs_bulk_out_desc.bEndpointAddress =
  3854. + fsg_fs_bulk_out_desc.bEndpointAddress;
  3855. + fsg_hs_intr_in_desc.bEndpointAddress =
  3856. + fsg_fs_intr_in_desc.bEndpointAddress;
  3857. + }
  3858. +
  3859. + if (gadget_is_superspeed(gadget)) {
  3860. + unsigned max_burst;
  3861. +
  3862. + fsg_ss_function[i + FSG_SS_FUNCTION_PRE_EP_ENTRIES] = NULL;
  3863. +
  3864. + /* Calculate bMaxBurst, we know packet size is 1024 */
  3865. + max_burst = min_t(unsigned, mod_data.buflen / 1024, 15);
  3866. +
  3867. + /* Assume endpoint addresses are the same for both speeds */
  3868. + fsg_ss_bulk_in_desc.bEndpointAddress =
  3869. + fsg_fs_bulk_in_desc.bEndpointAddress;
  3870. + fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst;
  3871. +
  3872. + fsg_ss_bulk_out_desc.bEndpointAddress =
  3873. + fsg_fs_bulk_out_desc.bEndpointAddress;
  3874. + fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;
  3875. + }
  3876. +
  3877. + if (gadget_is_otg(gadget))
  3878. + fsg_otg_desc.bmAttributes |= USB_OTG_HNP;
  3879. +
  3880. + rc = -ENOMEM;
  3881. +
  3882. + /* Allocate the request and buffer for endpoint 0 */
  3883. + fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL);
  3884. + if (!req)
  3885. + goto out;
  3886. + req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL);
  3887. + if (!req->buf)
  3888. + goto out;
  3889. + req->complete = ep0_complete;
  3890. +
  3891. + /* Allocate the data buffers */
  3892. + for (i = 0; i < fsg_num_buffers; ++i) {
  3893. + struct fsg_buffhd *bh = &fsg->buffhds[i];
  3894. +
  3895. + /* Allocate for the bulk-in endpoint. We assume that
  3896. + * the buffer will also work with the bulk-out (and
  3897. + * interrupt-in) endpoint. */
  3898. + bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL);
  3899. + if (!bh->buf)
  3900. + goto out;
  3901. + bh->next = bh + 1;
  3902. + }
  3903. + fsg->buffhds[fsg_num_buffers - 1].next = &fsg->buffhds[0];
  3904. +
  3905. + /* This should reflect the actual gadget power source */
  3906. + usb_gadget_set_selfpowered(gadget);
  3907. +
  3908. + snprintf(fsg_string_manufacturer, sizeof fsg_string_manufacturer,
  3909. + "%s %s with %s",
  3910. + init_utsname()->sysname, init_utsname()->release,
  3911. + gadget->name);
  3912. +
  3913. + fsg->thread_task = kthread_create(fsg_main_thread, fsg,
  3914. + "file-storage-gadget");
  3915. + if (IS_ERR(fsg->thread_task)) {
  3916. + rc = PTR_ERR(fsg->thread_task);
  3917. + goto out;
  3918. + }
  3919. +
  3920. + INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
  3921. + INFO(fsg, "NOTE: This driver is deprecated. "
  3922. + "Consider using g_mass_storage instead.\n");
  3923. + INFO(fsg, "Number of LUNs=%d\n", fsg->nluns);
  3924. +
  3925. + pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
  3926. + for (i = 0; i < fsg->nluns; ++i) {
  3927. + curlun = &fsg->luns[i];
  3928. + if (fsg_lun_is_open(curlun)) {
  3929. + p = NULL;
  3930. + if (pathbuf) {
  3931. + p = d_path(&curlun->filp->f_path,
  3932. + pathbuf, PATH_MAX);
  3933. + if (IS_ERR(p))
  3934. + p = NULL;
  3935. + }
  3936. + LINFO(curlun, "ro=%d, nofua=%d, file: %s\n",
  3937. + curlun->ro, curlun->nofua, (p ? p : "(error)"));
  3938. + }
  3939. + }
  3940. + kfree(pathbuf);
  3941. +
  3942. + DBG(fsg, "transport=%s (x%02x)\n",
  3943. + mod_data.transport_name, mod_data.transport_type);
  3944. + DBG(fsg, "protocol=%s (x%02x)\n",
  3945. + mod_data.protocol_name, mod_data.protocol_type);
  3946. + DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n",
  3947. + mod_data.vendor, mod_data.product, mod_data.release);
  3948. + DBG(fsg, "removable=%d, stall=%d, cdrom=%d, buflen=%u\n",
  3949. + mod_data.removable, mod_data.can_stall,
  3950. + mod_data.cdrom, mod_data.buflen);
  3951. + DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task));
  3952. +
  3953. + set_bit(REGISTERED, &fsg->atomic_bitflags);
  3954. +
  3955. + /* Tell the thread to start working */
  3956. + wake_up_process(fsg->thread_task);
  3957. + return 0;
  3958. +
  3959. +autoconf_fail:
  3960. + ERROR(fsg, "unable to autoconfigure all endpoints\n");
  3961. + rc = -ENOTSUPP;
  3962. +
  3963. +out:
  3964. + fsg->state = FSG_STATE_TERMINATED; // The thread is dead
  3965. + fsg_unbind(gadget);
  3966. + complete(&fsg->thread_notifier);
  3967. + return rc;
  3968. +}
  3969. +
  3970. +
  3971. +/*-------------------------------------------------------------------------*/
  3972. +
  3973. +static void fsg_suspend(struct usb_gadget *gadget)
  3974. +{
  3975. + struct fsg_dev *fsg = get_gadget_data(gadget);
  3976. +
  3977. + DBG(fsg, "suspend\n");
  3978. + set_bit(SUSPENDED, &fsg->atomic_bitflags);
  3979. +}
  3980. +
  3981. +static void fsg_resume(struct usb_gadget *gadget)
  3982. +{
  3983. + struct fsg_dev *fsg = get_gadget_data(gadget);
  3984. +
  3985. + DBG(fsg, "resume\n");
  3986. + clear_bit(SUSPENDED, &fsg->atomic_bitflags);
  3987. +}
  3988. +
  3989. +
  3990. +/*-------------------------------------------------------------------------*/
  3991. +
  3992. +static struct usb_gadget_driver fsg_driver = {
  3993. + .max_speed = USB_SPEED_SUPER,
  3994. + .function = (char *) fsg_string_product,
  3995. + .unbind = fsg_unbind,
  3996. + .disconnect = fsg_disconnect,
  3997. + .setup = fsg_setup,
  3998. + .suspend = fsg_suspend,
  3999. + .resume = fsg_resume,
  4000. +
  4001. + .driver = {
  4002. + .name = DRIVER_NAME,
  4003. + .owner = THIS_MODULE,
  4004. + // .release = ...
  4005. + // .suspend = ...
  4006. + // .resume = ...
  4007. + },
  4008. +};
  4009. +
  4010. +
  4011. +static int __init fsg_alloc(void)
  4012. +{
  4013. + struct fsg_dev *fsg;
  4014. +
  4015. + fsg = kzalloc(sizeof *fsg +
  4016. + fsg_num_buffers * sizeof *(fsg->buffhds), GFP_KERNEL);
  4017. +
  4018. + if (!fsg)
  4019. + return -ENOMEM;
  4020. + spin_lock_init(&fsg->lock);
  4021. + init_rwsem(&fsg->filesem);
  4022. + kref_init(&fsg->ref);
  4023. + init_completion(&fsg->thread_notifier);
  4024. +
  4025. + the_fsg = fsg;
  4026. + return 0;
  4027. +}
  4028. +
  4029. +
  4030. +static int __init fsg_init(void)
  4031. +{
  4032. + int rc;
  4033. + struct fsg_dev *fsg;
  4034. +
  4035. + rc = fsg_num_buffers_validate();
  4036. + if (rc != 0)
  4037. + return rc;
  4038. +
  4039. + if ((rc = fsg_alloc()) != 0)
  4040. + return rc;
  4041. + fsg = the_fsg;
  4042. + if ((rc = usb_gadget_probe_driver(&fsg_driver, fsg_bind)) != 0)
  4043. + kref_put(&fsg->ref, fsg_release);
  4044. + return rc;
  4045. +}
  4046. +module_init(fsg_init);
  4047. +
  4048. +
  4049. +static void __exit fsg_cleanup(void)
  4050. +{
  4051. + struct fsg_dev *fsg = the_fsg;
  4052. +
  4053. + /* Unregister the driver iff the thread hasn't already done so */
  4054. + if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags))
  4055. + usb_gadget_unregister_driver(&fsg_driver);
  4056. +
  4057. + /* Wait for the thread to finish up */
  4058. + wait_for_completion(&fsg->thread_notifier);
  4059. +
  4060. + kref_put(&fsg->ref, fsg_release);
  4061. +}
  4062. +module_exit(fsg_cleanup);
  4063. --- a/drivers/usb/host/Kconfig
  4064. +++ b/drivers/usb/host/Kconfig
  4065. @@ -751,6 +751,19 @@ config USB_HWA_HCD
  4066. To compile this driver a module, choose M here: the module
  4067. will be called "hwa-hc".
  4068. +config USB_DWCOTG
  4069. + tristate "Synopsis DWC host support"
  4070. + depends on USB
  4071. + help
  4072. + The Synopsis DWC controller is a dual-role
  4073. + host/peripheral/OTG ("On The Go") USB controllers.
  4074. +
  4075. + Enable this option to support this IP in host controller mode.
  4076. + If unsure, say N.
  4077. +
  4078. + To compile this driver as a module, choose M here: the
  4079. + modules built will be called dwc_otg and dwc_common_port.
  4080. +
  4081. config USB_IMX21_HCD
  4082. tristate "i.MX21 HCD support"
  4083. depends on ARM && ARCH_MXC
  4084. --- a/drivers/usb/host/Makefile
  4085. +++ b/drivers/usb/host/Makefile
  4086. @@ -71,6 +71,8 @@ obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o
  4087. obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
  4088. obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o
  4089. obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o
  4090. +
  4091. +obj-$(CONFIG_USB_DWCOTG) += dwc_otg/ dwc_common_port/
  4092. obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o
  4093. obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o
  4094. obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
  4095. --- /dev/null
  4096. +++ b/drivers/usb/host/dwc_common_port/Makefile
  4097. @@ -0,0 +1,58 @@
  4098. +#
  4099. +# Makefile for DWC_common library
  4100. +#
  4101. +
  4102. +ifneq ($(KERNELRELEASE),)
  4103. +
  4104. +ccflags-y += -DDWC_LINUX
  4105. +#ccflags-y += -DDEBUG
  4106. +#ccflags-y += -DDWC_DEBUG_REGS
  4107. +#ccflags-y += -DDWC_DEBUG_MEMORY
  4108. +
  4109. +ccflags-y += -DDWC_LIBMODULE
  4110. +ccflags-y += -DDWC_CCLIB
  4111. +#ccflags-y += -DDWC_CRYPTOLIB
  4112. +ccflags-y += -DDWC_NOTIFYLIB
  4113. +ccflags-y += -DDWC_UTFLIB
  4114. +
  4115. +obj-$(CONFIG_USB_DWCOTG) += dwc_common_port_lib.o
  4116. +dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \
  4117. + dwc_crypto.o dwc_notifier.o \
  4118. + dwc_common_linux.o dwc_mem.o
  4119. +
  4120. +kernrelwd := $(subst ., ,$(KERNELRELEASE))
  4121. +kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))
  4122. +
  4123. +ifneq ($(kernrel3),2.6.20)
  4124. +# grayg - I only know that we use ccflags-y in 2.6.31 actually
  4125. +ccflags-y += $(CPPFLAGS)
  4126. +endif
  4127. +
  4128. +else
  4129. +
  4130. +#ifeq ($(KDIR),)
  4131. +#$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment)
  4132. +#endif
  4133. +
  4134. +ifeq ($(ARCH),)
  4135. +$(error Must give "ARCH=<arch>" on command line or in environment. Also, if \
  4136. + cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-")
  4137. +endif
  4138. +
  4139. +ifeq ($(DOXYGEN),)
  4140. +DOXYGEN := doxygen
  4141. +endif
  4142. +
  4143. +default:
  4144. + $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
  4145. +
  4146. +docs: $(wildcard *.[hc]) doc/doxygen.cfg
  4147. + $(DOXYGEN) doc/doxygen.cfg
  4148. +
  4149. +tags: $(wildcard *.[hc])
  4150. + $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
  4151. +
  4152. +endif
  4153. +
  4154. +clean:
  4155. + rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/
  4156. --- /dev/null
  4157. +++ b/drivers/usb/host/dwc_common_port/Makefile.fbsd
  4158. @@ -0,0 +1,17 @@
  4159. +CFLAGS += -I/sys/i386/compile/GENERIC -I/sys/i386/include -I/usr/include
  4160. +CFLAGS += -DDWC_FREEBSD
  4161. +CFLAGS += -DDEBUG
  4162. +#CFLAGS += -DDWC_DEBUG_REGS
  4163. +#CFLAGS += -DDWC_DEBUG_MEMORY
  4164. +
  4165. +#CFLAGS += -DDWC_LIBMODULE
  4166. +#CFLAGS += -DDWC_CCLIB
  4167. +#CFLAGS += -DDWC_CRYPTOLIB
  4168. +#CFLAGS += -DDWC_NOTIFYLIB
  4169. +#CFLAGS += -DDWC_UTFLIB
  4170. +
  4171. +KMOD = dwc_common_port_lib
  4172. +SRCS = dwc_cc.c dwc_modpow.c dwc_dh.c dwc_crypto.c dwc_notifier.c \
  4173. + dwc_common_fbsd.c dwc_mem.c
  4174. +
  4175. +.include <bsd.kmod.mk>
  4176. --- /dev/null
  4177. +++ b/drivers/usb/host/dwc_common_port/Makefile.linux
  4178. @@ -0,0 +1,49 @@
  4179. +#
  4180. +# Makefile for DWC_common library
  4181. +#
  4182. +ifneq ($(KERNELRELEASE),)
  4183. +
  4184. +ccflags-y += -DDWC_LINUX
  4185. +#ccflags-y += -DDEBUG
  4186. +#ccflags-y += -DDWC_DEBUG_REGS
  4187. +#ccflags-y += -DDWC_DEBUG_MEMORY
  4188. +
  4189. +ccflags-y += -DDWC_LIBMODULE
  4190. +ccflags-y += -DDWC_CCLIB
  4191. +ccflags-y += -DDWC_CRYPTOLIB
  4192. +ccflags-y += -DDWC_NOTIFYLIB
  4193. +ccflags-y += -DDWC_UTFLIB
  4194. +
  4195. +obj-m := dwc_common_port_lib.o
  4196. +dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \
  4197. + dwc_crypto.o dwc_notifier.o \
  4198. + dwc_common_linux.o dwc_mem.o
  4199. +
  4200. +else
  4201. +
  4202. +ifeq ($(KDIR),)
  4203. +$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment)
  4204. +endif
  4205. +
  4206. +ifeq ($(ARCH),)
  4207. +$(error Must give "ARCH=<arch>" on command line or in environment. Also, if \
  4208. + cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-")
  4209. +endif
  4210. +
  4211. +ifeq ($(DOXYGEN),)
  4212. +DOXYGEN := doxygen
  4213. +endif
  4214. +
  4215. +default:
  4216. + $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
  4217. +
  4218. +docs: $(wildcard *.[hc]) doc/doxygen.cfg
  4219. + $(DOXYGEN) doc/doxygen.cfg
  4220. +
  4221. +tags: $(wildcard *.[hc])
  4222. + $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
  4223. +
  4224. +endif
  4225. +
  4226. +clean:
  4227. + rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/
  4228. --- /dev/null
  4229. +++ b/drivers/usb/host/dwc_common_port/changes.txt
  4230. @@ -0,0 +1,174 @@
  4231. +
  4232. +dwc_read_reg32() and friends now take an additional parameter, a pointer to an
  4233. +IO context struct. The IO context struct should live in an os-dependent struct
  4234. +in your driver. As an example, the dwc_usb3 driver has an os-dependent struct
  4235. +named 'os_dep' embedded in the main device struct. So there these calls look
  4236. +like this:
  4237. +
  4238. + dwc_read_reg32(&usb3_dev->os_dep.ioctx, &pcd->dev_global_regs->dcfg);
  4239. +
  4240. + dwc_write_reg32(&usb3_dev->os_dep.ioctx,
  4241. + &pcd->dev_global_regs->dcfg, 0);
  4242. +
  4243. +Note that for the existing Linux driver ports, it is not necessary to actually
  4244. +define the 'ioctx' member in the os-dependent struct. Since Linux does not
  4245. +require an IO context, its macros for dwc_read_reg32() and friends do not
  4246. +use the context pointer, so it is optimized away by the compiler. But it is
  4247. +necessary to add the pointer parameter to all of the call sites, to be ready
  4248. +for any future ports (such as FreeBSD) which do require an IO context.
  4249. +
  4250. +
  4251. +Similarly, dwc_alloc(), dwc_alloc_atomic(), dwc_strdup(), and dwc_free() now
  4252. +take an additional parameter, a pointer to a memory context. Examples:
  4253. +
  4254. + addr = dwc_alloc(&usb3_dev->os_dep.memctx, size);
  4255. +
  4256. + dwc_free(&usb3_dev->os_dep.memctx, addr);
  4257. +
  4258. +Again, for the Linux ports, it is not necessary to actually define the memctx
  4259. +member, but it is necessary to add the pointer parameter to all of the call
  4260. +sites.
  4261. +
  4262. +
  4263. +Same for dwc_dma_alloc() and dwc_dma_free(). Examples:
  4264. +
  4265. + virt_addr = dwc_dma_alloc(&usb3_dev->os_dep.dmactx, size, &phys_addr);
  4266. +
  4267. + dwc_dma_free(&usb3_dev->os_dep.dmactx, size, virt_addr, phys_addr);
  4268. +
  4269. +
  4270. +Same for dwc_mutex_alloc() and dwc_mutex_free(). Examples:
  4271. +
  4272. + mutex = dwc_mutex_alloc(&usb3_dev->os_dep.mtxctx);
  4273. +
  4274. + dwc_mutex_free(&usb3_dev->os_dep.mtxctx, mutex);
  4275. +
  4276. +
  4277. +Same for dwc_spinlock_alloc() and dwc_spinlock_free(). Examples:
  4278. +
  4279. + lock = dwc_spinlock_alloc(&usb3_dev->osdep.splctx);
  4280. +
  4281. + dwc_spinlock_free(&usb3_dev->osdep.splctx, lock);
  4282. +
  4283. +
  4284. +Same for dwc_timer_alloc(). Example:
  4285. +
  4286. + timer = dwc_timer_alloc(&usb3_dev->os_dep.tmrctx, "dwc_usb3_tmr1",
  4287. + cb_func, cb_data);
  4288. +
  4289. +
  4290. +Same for dwc_waitq_alloc(). Example:
  4291. +
  4292. + waitq = dwc_waitq_alloc(&usb3_dev->os_dep.wtqctx);
  4293. +
  4294. +
  4295. +Same for dwc_thread_run(). Example:
  4296. +
  4297. + thread = dwc_thread_run(&usb3_dev->os_dep.thdctx, func,
  4298. + "dwc_usb3_thd1", data);
  4299. +
  4300. +
  4301. +Same for dwc_workq_alloc(). Example:
  4302. +
  4303. + workq = dwc_workq_alloc(&usb3_dev->osdep.wkqctx, "dwc_usb3_wkq1");
  4304. +
  4305. +
  4306. +Same for dwc_task_alloc(). Example:
  4307. +
  4308. + task = dwc_task_alloc(&usb3_dev->os_dep.tskctx, "dwc_usb3_tsk1",
  4309. + cb_func, cb_data);
  4310. +
  4311. +
  4312. +In addition to the context pointer additions, a few core functions have had
  4313. +other changes made to their parameters:
  4314. +
  4315. +The 'flags' parameter to dwc_spinlock_irqsave() and dwc_spinunlock_irqrestore()
  4316. +has been changed from a uint64_t to a dwc_irqflags_t.
  4317. +
  4318. +dwc_thread_should_stop() now takes a 'dwc_thread_t *' parameter, because the
  4319. +FreeBSD equivalent of that function requires it.
  4320. +
  4321. +And, in addition to the context pointer, dwc_task_alloc() also adds a
  4322. +'char *name' parameter, to be consistent with dwc_thread_run() and
  4323. +dwc_workq_alloc(), and because the FreeBSD equivalent of that function
  4324. +requires a unique name.
  4325. +
  4326. +
  4327. +Here is a complete list of the core functions that now take a pointer to a
  4328. +context as their first parameter:
  4329. +
  4330. + dwc_read_reg32
  4331. + dwc_read_reg64
  4332. + dwc_write_reg32
  4333. + dwc_write_reg64
  4334. + dwc_modify_reg32
  4335. + dwc_modify_reg64
  4336. + dwc_alloc
  4337. + dwc_alloc_atomic
  4338. + dwc_strdup
  4339. + dwc_free
  4340. + dwc_dma_alloc
  4341. + dwc_dma_free
  4342. + dwc_mutex_alloc
  4343. + dwc_mutex_free
  4344. + dwc_spinlock_alloc
  4345. + dwc_spinlock_free
  4346. + dwc_timer_alloc
  4347. + dwc_waitq_alloc
  4348. + dwc_thread_run
  4349. + dwc_workq_alloc
  4350. + dwc_task_alloc Also adds a 'char *name' as its 2nd parameter
  4351. +
  4352. +And here are the core functions that have other changes to their parameters:
  4353. +
  4354. + dwc_spinlock_irqsave 'flags' param is now a 'dwc_irqflags_t *'
  4355. + dwc_spinunlock_irqrestore 'flags' param is now a 'dwc_irqflags_t'
  4356. + dwc_thread_should_stop Adds a 'dwc_thread_t *' parameter
  4357. +
  4358. +
  4359. +
  4360. +The changes to the core functions also require some of the other library
  4361. +functions to change:
  4362. +
  4363. + dwc_cc_if_alloc() and dwc_cc_if_free() now take a 'void *memctx'
  4364. + (for memory allocation) as the 1st param and a 'void *mtxctx'
  4365. + (for mutex allocation) as the 2nd param.
  4366. +
  4367. + dwc_cc_clear(), dwc_cc_add(), dwc_cc_change(), dwc_cc_remove(),
  4368. + dwc_cc_data_for_save(), and dwc_cc_restore_from_data() now take a
  4369. + 'void *memctx' as the 1st param.
  4370. +
  4371. + dwc_dh_modpow(), dwc_dh_pk(), and dwc_dh_derive_keys() now take a
  4372. + 'void *memctx' as the 1st param.
  4373. +
  4374. + dwc_modpow() now takes a 'void *memctx' as the 1st param.
  4375. +
  4376. + dwc_alloc_notification_manager() now takes a 'void *memctx' as the
  4377. + 1st param and a 'void *wkqctx' (for work queue allocation) as the 2nd
  4378. + param, and also now returns an integer value that is non-zero if
  4379. + allocation of its data structures or work queue fails.
  4380. +
  4381. + dwc_register_notifier() now takes a 'void *memctx' as the 1st param.
  4382. +
  4383. + dwc_memory_debug_start() now takes a 'void *mem_ctx' as the first
  4384. + param, and also now returns an integer value that is non-zero if
  4385. + allocation of its data structures fails.
  4386. +
  4387. +
  4388. +
  4389. +Other miscellaneous changes:
  4390. +
  4391. +The DEBUG_MEMORY and DEBUG_REGS #define's have been renamed to
  4392. +DWC_DEBUG_MEMORY and DWC_DEBUG_REGS.
  4393. +
  4394. +The following #define's have been added to allow selectively compiling library
  4395. +features:
  4396. +
  4397. + DWC_CCLIB
  4398. + DWC_CRYPTOLIB
  4399. + DWC_NOTIFYLIB
  4400. + DWC_UTFLIB
  4401. +
  4402. +A DWC_LIBMODULE #define has also been added. If this is not defined, then the
  4403. +module code in dwc_common_linux.c is not compiled in. This allows linking the
  4404. +library code directly into a driver module, instead of as a standalone module.
  4405. --- /dev/null
  4406. +++ b/drivers/usb/host/dwc_common_port/doc/doxygen.cfg
  4407. @@ -0,0 +1,270 @@
  4408. +# Doxyfile 1.4.5
  4409. +
  4410. +#---------------------------------------------------------------------------
  4411. +# Project related configuration options
  4412. +#---------------------------------------------------------------------------
  4413. +PROJECT_NAME = "Synopsys DWC Portability and Common Library for UWB"
  4414. +PROJECT_NUMBER =
  4415. +OUTPUT_DIRECTORY = doc
  4416. +CREATE_SUBDIRS = NO
  4417. +OUTPUT_LANGUAGE = English
  4418. +BRIEF_MEMBER_DESC = YES
  4419. +REPEAT_BRIEF = YES
  4420. +ABBREVIATE_BRIEF = "The $name class" \
  4421. + "The $name widget" \
  4422. + "The $name file" \
  4423. + is \
  4424. + provides \
  4425. + specifies \
  4426. + contains \
  4427. + represents \
  4428. + a \
  4429. + an \
  4430. + the
  4431. +ALWAYS_DETAILED_SEC = YES
  4432. +INLINE_INHERITED_MEMB = NO
  4433. +FULL_PATH_NAMES = NO
  4434. +STRIP_FROM_PATH = ..
  4435. +STRIP_FROM_INC_PATH =
  4436. +SHORT_NAMES = NO
  4437. +JAVADOC_AUTOBRIEF = YES
  4438. +MULTILINE_CPP_IS_BRIEF = NO
  4439. +DETAILS_AT_TOP = YES
  4440. +INHERIT_DOCS = YES
  4441. +SEPARATE_MEMBER_PAGES = NO
  4442. +TAB_SIZE = 8
  4443. +ALIASES =
  4444. +OPTIMIZE_OUTPUT_FOR_C = YES
  4445. +OPTIMIZE_OUTPUT_JAVA = NO
  4446. +BUILTIN_STL_SUPPORT = NO
  4447. +DISTRIBUTE_GROUP_DOC = NO
  4448. +SUBGROUPING = NO
  4449. +#---------------------------------------------------------------------------
  4450. +# Build related configuration options
  4451. +#---------------------------------------------------------------------------
  4452. +EXTRACT_ALL = NO
  4453. +EXTRACT_PRIVATE = NO
  4454. +EXTRACT_STATIC = YES
  4455. +EXTRACT_LOCAL_CLASSES = NO
  4456. +EXTRACT_LOCAL_METHODS = NO
  4457. +HIDE_UNDOC_MEMBERS = NO
  4458. +HIDE_UNDOC_CLASSES = NO
  4459. +HIDE_FRIEND_COMPOUNDS = NO
  4460. +HIDE_IN_BODY_DOCS = NO
  4461. +INTERNAL_DOCS = NO
  4462. +CASE_SENSE_NAMES = YES
  4463. +HIDE_SCOPE_NAMES = NO
  4464. +SHOW_INCLUDE_FILES = NO
  4465. +INLINE_INFO = YES
  4466. +SORT_MEMBER_DOCS = NO
  4467. +SORT_BRIEF_DOCS = NO
  4468. +SORT_BY_SCOPE_NAME = NO
  4469. +GENERATE_TODOLIST = YES
  4470. +GENERATE_TESTLIST = YES
  4471. +GENERATE_BUGLIST = YES
  4472. +GENERATE_DEPRECATEDLIST= YES
  4473. +ENABLED_SECTIONS =
  4474. +MAX_INITIALIZER_LINES = 30
  4475. +SHOW_USED_FILES = YES
  4476. +SHOW_DIRECTORIES = YES
  4477. +FILE_VERSION_FILTER =
  4478. +#---------------------------------------------------------------------------
  4479. +# configuration options related to warning and progress messages
  4480. +#---------------------------------------------------------------------------
  4481. +QUIET = YES
  4482. +WARNINGS = YES
  4483. +WARN_IF_UNDOCUMENTED = NO
  4484. +WARN_IF_DOC_ERROR = YES
  4485. +WARN_NO_PARAMDOC = YES
  4486. +WARN_FORMAT = "$file:$line: $text"
  4487. +WARN_LOGFILE =
  4488. +#---------------------------------------------------------------------------
  4489. +# configuration options related to the input files
  4490. +#---------------------------------------------------------------------------
  4491. +INPUT = .
  4492. +FILE_PATTERNS = *.c \
  4493. + *.cc \
  4494. + *.cxx \
  4495. + *.cpp \
  4496. + *.c++ \
  4497. + *.d \
  4498. + *.java \
  4499. + *.ii \
  4500. + *.ixx \
  4501. + *.ipp \
  4502. + *.i++ \
  4503. + *.inl \
  4504. + *.h \
  4505. + *.hh \
  4506. + *.hxx \
  4507. + *.hpp \
  4508. + *.h++ \
  4509. + *.idl \
  4510. + *.odl \
  4511. + *.cs \
  4512. + *.php \
  4513. + *.php3 \
  4514. + *.inc \
  4515. + *.m \
  4516. + *.mm \
  4517. + *.dox \
  4518. + *.py \
  4519. + *.C \
  4520. + *.CC \
  4521. + *.C++ \
  4522. + *.II \
  4523. + *.I++ \
  4524. + *.H \
  4525. + *.HH \
  4526. + *.H++ \
  4527. + *.CS \
  4528. + *.PHP \
  4529. + *.PHP3 \
  4530. + *.M \
  4531. + *.MM \
  4532. + *.PY
  4533. +RECURSIVE = NO
  4534. +EXCLUDE =
  4535. +EXCLUDE_SYMLINKS = NO
  4536. +EXCLUDE_PATTERNS =
  4537. +EXAMPLE_PATH =
  4538. +EXAMPLE_PATTERNS = *
  4539. +EXAMPLE_RECURSIVE = NO
  4540. +IMAGE_PATH =
  4541. +INPUT_FILTER =
  4542. +FILTER_PATTERNS =
  4543. +FILTER_SOURCE_FILES = NO
  4544. +#---------------------------------------------------------------------------
  4545. +# configuration options related to source browsing
  4546. +#---------------------------------------------------------------------------
  4547. +SOURCE_BROWSER = NO
  4548. +INLINE_SOURCES = NO
  4549. +STRIP_CODE_COMMENTS = YES
  4550. +REFERENCED_BY_RELATION = YES
  4551. +REFERENCES_RELATION = YES
  4552. +USE_HTAGS = NO
  4553. +VERBATIM_HEADERS = NO
  4554. +#---------------------------------------------------------------------------
  4555. +# configuration options related to the alphabetical class index
  4556. +#---------------------------------------------------------------------------
  4557. +ALPHABETICAL_INDEX = NO
  4558. +COLS_IN_ALPHA_INDEX = 5
  4559. +IGNORE_PREFIX =
  4560. +#---------------------------------------------------------------------------
  4561. +# configuration options related to the HTML output
  4562. +#---------------------------------------------------------------------------
  4563. +GENERATE_HTML = YES
  4564. +HTML_OUTPUT = html
  4565. +HTML_FILE_EXTENSION = .html
  4566. +HTML_HEADER =
  4567. +HTML_FOOTER =
  4568. +HTML_STYLESHEET =
  4569. +HTML_ALIGN_MEMBERS = YES
  4570. +GENERATE_HTMLHELP = NO
  4571. +CHM_FILE =
  4572. +HHC_LOCATION =
  4573. +GENERATE_CHI = NO
  4574. +BINARY_TOC = NO
  4575. +TOC_EXPAND = NO
  4576. +DISABLE_INDEX = NO
  4577. +ENUM_VALUES_PER_LINE = 4
  4578. +GENERATE_TREEVIEW = YES
  4579. +TREEVIEW_WIDTH = 250
  4580. +#---------------------------------------------------------------------------
  4581. +# configuration options related to the LaTeX output
  4582. +#---------------------------------------------------------------------------
  4583. +GENERATE_LATEX = NO
  4584. +LATEX_OUTPUT = latex
  4585. +LATEX_CMD_NAME = latex
  4586. +MAKEINDEX_CMD_NAME = makeindex
  4587. +COMPACT_LATEX = NO
  4588. +PAPER_TYPE = a4wide
  4589. +EXTRA_PACKAGES =
  4590. +LATEX_HEADER =
  4591. +PDF_HYPERLINKS = NO
  4592. +USE_PDFLATEX = NO
  4593. +LATEX_BATCHMODE = NO
  4594. +LATEX_HIDE_INDICES = NO
  4595. +#---------------------------------------------------------------------------
  4596. +# configuration options related to the RTF output
  4597. +#---------------------------------------------------------------------------
  4598. +GENERATE_RTF = NO
  4599. +RTF_OUTPUT = rtf
  4600. +COMPACT_RTF = NO
  4601. +RTF_HYPERLINKS = NO
  4602. +RTF_STYLESHEET_FILE =
  4603. +RTF_EXTENSIONS_FILE =
  4604. +#---------------------------------------------------------------------------
  4605. +# configuration options related to the man page output
  4606. +#---------------------------------------------------------------------------
  4607. +GENERATE_MAN = NO
  4608. +MAN_OUTPUT = man
  4609. +MAN_EXTENSION = .3
  4610. +MAN_LINKS = NO
  4611. +#---------------------------------------------------------------------------
  4612. +# configuration options related to the XML output
  4613. +#---------------------------------------------------------------------------
  4614. +GENERATE_XML = NO
  4615. +XML_OUTPUT = xml
  4616. +XML_SCHEMA =
  4617. +XML_DTD =
  4618. +XML_PROGRAMLISTING = YES
  4619. +#---------------------------------------------------------------------------
  4620. +# configuration options for the AutoGen Definitions output
  4621. +#---------------------------------------------------------------------------
  4622. +GENERATE_AUTOGEN_DEF = NO
  4623. +#---------------------------------------------------------------------------
  4624. +# configuration options related to the Perl module output
  4625. +#---------------------------------------------------------------------------
  4626. +GENERATE_PERLMOD = NO
  4627. +PERLMOD_LATEX = NO
  4628. +PERLMOD_PRETTY = YES
  4629. +PERLMOD_MAKEVAR_PREFIX =
  4630. +#---------------------------------------------------------------------------
  4631. +# Configuration options related to the preprocessor
  4632. +#---------------------------------------------------------------------------
  4633. +ENABLE_PREPROCESSING = YES
  4634. +MACRO_EXPANSION = NO
  4635. +EXPAND_ONLY_PREDEF = NO
  4636. +SEARCH_INCLUDES = YES
  4637. +INCLUDE_PATH =
  4638. +INCLUDE_FILE_PATTERNS =
  4639. +PREDEFINED = DEBUG DEBUG_MEMORY
  4640. +EXPAND_AS_DEFINED =
  4641. +SKIP_FUNCTION_MACROS = YES
  4642. +#---------------------------------------------------------------------------
  4643. +# Configuration::additions related to external references
  4644. +#---------------------------------------------------------------------------
  4645. +TAGFILES =
  4646. +GENERATE_TAGFILE =
  4647. +ALLEXTERNALS = NO
  4648. +EXTERNAL_GROUPS = YES
  4649. +PERL_PATH = /usr/bin/perl
  4650. +#---------------------------------------------------------------------------
  4651. +# Configuration options related to the dot tool
  4652. +#---------------------------------------------------------------------------
  4653. +CLASS_DIAGRAMS = YES
  4654. +HIDE_UNDOC_RELATIONS = YES
  4655. +HAVE_DOT = NO
  4656. +CLASS_GRAPH = YES
  4657. +COLLABORATION_GRAPH = YES
  4658. +GROUP_GRAPHS = YES
  4659. +UML_LOOK = NO
  4660. +TEMPLATE_RELATIONS = NO
  4661. +INCLUDE_GRAPH = NO
  4662. +INCLUDED_BY_GRAPH = YES
  4663. +CALL_GRAPH = NO
  4664. +GRAPHICAL_HIERARCHY = YES
  4665. +DIRECTORY_GRAPH = YES
  4666. +DOT_IMAGE_FORMAT = png
  4667. +DOT_PATH =
  4668. +DOTFILE_DIRS =
  4669. +MAX_DOT_GRAPH_DEPTH = 1000
  4670. +DOT_TRANSPARENT = NO
  4671. +DOT_MULTI_TARGETS = NO
  4672. +GENERATE_LEGEND = YES
  4673. +DOT_CLEANUP = YES
  4674. +#---------------------------------------------------------------------------
  4675. +# Configuration::additions related to the search engine
  4676. +#---------------------------------------------------------------------------
  4677. +SEARCHENGINE = NO
  4678. --- /dev/null
  4679. +++ b/drivers/usb/host/dwc_common_port/dwc_cc.c
  4680. @@ -0,0 +1,532 @@
  4681. +/* =========================================================================
  4682. + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.c $
  4683. + * $Revision: #4 $
  4684. + * $Date: 2010/11/04 $
  4685. + * $Change: 1621692 $
  4686. + *
  4687. + * Synopsys Portability Library Software and documentation
  4688. + * (hereinafter, "Software") is an Unsupported proprietary work of
  4689. + * Synopsys, Inc. unless otherwise expressly agreed to in writing
  4690. + * between Synopsys and you.
  4691. + *
  4692. + * The Software IS NOT an item of Licensed Software or Licensed Product
  4693. + * under any End User Software License Agreement or Agreement for
  4694. + * Licensed Product with Synopsys or any supplement thereto. You are
  4695. + * permitted to use and redistribute this Software in source and binary
  4696. + * forms, with or without modification, provided that redistributions
  4697. + * of source code must retain this notice. You may not view, use,
  4698. + * disclose, copy or distribute this file or any information contained
  4699. + * herein except pursuant to this license grant from Synopsys. If you
  4700. + * do not agree with this notice, including the disclaimer below, then
  4701. + * you are not authorized to use the Software.
  4702. + *
  4703. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
  4704. + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  4705. + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  4706. + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
  4707. + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  4708. + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  4709. + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  4710. + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  4711. + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  4712. + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  4713. + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  4714. + * DAMAGE.
  4715. + * ========================================================================= */
  4716. +#ifdef DWC_CCLIB
  4717. +
  4718. +#include "dwc_cc.h"
  4719. +
  4720. +typedef struct dwc_cc
  4721. +{
  4722. + uint32_t uid;
  4723. + uint8_t chid[16];
  4724. + uint8_t cdid[16];
  4725. + uint8_t ck[16];
  4726. + uint8_t *name;
  4727. + uint8_t length;
  4728. + DWC_CIRCLEQ_ENTRY(dwc_cc) list_entry;
  4729. +} dwc_cc_t;
  4730. +
  4731. +DWC_CIRCLEQ_HEAD(context_list, dwc_cc);
  4732. +
  4733. +/** The main structure for CC management. */
  4734. +struct dwc_cc_if
  4735. +{
  4736. + dwc_mutex_t *mutex;
  4737. + char *filename;
  4738. +
  4739. + unsigned is_host:1;
  4740. +
  4741. + dwc_notifier_t *notifier;
  4742. +
  4743. + struct context_list list;
  4744. +};
  4745. +
  4746. +#ifdef DEBUG
  4747. +static inline void dump_bytes(char *name, uint8_t *bytes, int len)
  4748. +{
  4749. + int i;
  4750. + DWC_PRINTF("%s: ", name);
  4751. + for (i=0; i<len; i++) {
  4752. + DWC_PRINTF("%02x ", bytes[i]);
  4753. + }
  4754. + DWC_PRINTF("\n");
  4755. +}
  4756. +#else
  4757. +#define dump_bytes(x...)
  4758. +#endif
  4759. +
  4760. +static dwc_cc_t *alloc_cc(void *mem_ctx, uint8_t *name, uint32_t length)
  4761. +{
  4762. + dwc_cc_t *cc = dwc_alloc(mem_ctx, sizeof(dwc_cc_t));
  4763. + if (!cc) {
  4764. + return NULL;
  4765. + }
  4766. + DWC_MEMSET(cc, 0, sizeof(dwc_cc_t));
  4767. +
  4768. + if (name) {
  4769. + cc->length = length;
  4770. + cc->name = dwc_alloc(mem_ctx, length);
  4771. + if (!cc->name) {
  4772. + dwc_free(mem_ctx, cc);
  4773. + return NULL;
  4774. + }
  4775. +
  4776. + DWC_MEMCPY(cc->name, name, length);
  4777. + }
  4778. +
  4779. + return cc;
  4780. +}
  4781. +
  4782. +static void free_cc(void *mem_ctx, dwc_cc_t *cc)
  4783. +{
  4784. + if (cc->name) {
  4785. + dwc_free(mem_ctx, cc->name);
  4786. + }
  4787. + dwc_free(mem_ctx, cc);
  4788. +}
  4789. +
  4790. +static uint32_t next_uid(dwc_cc_if_t *cc_if)
  4791. +{
  4792. + uint32_t uid = 0;
  4793. + dwc_cc_t *cc;
  4794. + DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
  4795. + if (cc->uid > uid) {
  4796. + uid = cc->uid;
  4797. + }
  4798. + }
  4799. +
  4800. + if (uid == 0) {
  4801. + uid = 255;
  4802. + }
  4803. +
  4804. + return uid + 1;
  4805. +}
  4806. +
  4807. +static dwc_cc_t *cc_find(dwc_cc_if_t *cc_if, uint32_t uid)
  4808. +{
  4809. + dwc_cc_t *cc;
  4810. + DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
  4811. + if (cc->uid == uid) {
  4812. + return cc;
  4813. + }
  4814. + }
  4815. + return NULL;
  4816. +}
  4817. +
  4818. +static unsigned int cc_data_size(dwc_cc_if_t *cc_if)
  4819. +{
  4820. + unsigned int size = 0;
  4821. + dwc_cc_t *cc;
  4822. + DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
  4823. + size += (48 + 1);
  4824. + if (cc->name) {
  4825. + size += cc->length;
  4826. + }
  4827. + }
  4828. + return size;
  4829. +}
  4830. +
  4831. +static uint32_t cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
  4832. +{
  4833. + uint32_t uid = 0;
  4834. + dwc_cc_t *cc;
  4835. +
  4836. + DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
  4837. + if (DWC_MEMCMP(cc->chid, chid, 16) == 0) {
  4838. + uid = cc->uid;
  4839. + break;
  4840. + }
  4841. + }
  4842. + return uid;
  4843. +}
  4844. +static uint32_t cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
  4845. +{
  4846. + uint32_t uid = 0;
  4847. + dwc_cc_t *cc;
  4848. +
  4849. + DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
  4850. + if (DWC_MEMCMP(cc->cdid, cdid, 16) == 0) {
  4851. + uid = cc->uid;
  4852. + break;
  4853. + }
  4854. + }
  4855. + return uid;
  4856. +}
  4857. +
  4858. +/* Internal cc_add */
  4859. +static int32_t cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
  4860. + uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
  4861. +{
  4862. + dwc_cc_t *cc;
  4863. + uint32_t uid;
  4864. +
  4865. + if (cc_if->is_host) {
  4866. + uid = cc_match_cdid(cc_if, cdid);
  4867. + }
  4868. + else {
  4869. + uid = cc_match_chid(cc_if, chid);
  4870. + }
  4871. +
  4872. + if (uid) {
  4873. + DWC_DEBUGC("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length);
  4874. + cc = cc_find(cc_if, uid);
  4875. + }
  4876. + else {
  4877. + cc = alloc_cc(mem_ctx, name, length);
  4878. + cc->uid = next_uid(cc_if);
  4879. + DWC_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry);
  4880. + }
  4881. +
  4882. + DWC_MEMCPY(&(cc->chid[0]), chid, 16);
  4883. + DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
  4884. + DWC_MEMCPY(&(cc->ck[0]), ck, 16);
  4885. +
  4886. + DWC_DEBUGC("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length);
  4887. + dump_bytes("CHID", cc->chid, 16);
  4888. + dump_bytes("CDID", cc->cdid, 16);
  4889. + dump_bytes("CK", cc->ck, 16);
  4890. + return cc->uid;
  4891. +}
  4892. +
  4893. +/* Internal cc_clear */
  4894. +static void cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)
  4895. +{
  4896. + while (!DWC_CIRCLEQ_EMPTY(&cc_if->list)) {
  4897. + dwc_cc_t *cc = DWC_CIRCLEQ_FIRST(&cc_if->list);
  4898. + DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
  4899. + free_cc(mem_ctx, cc);
  4900. + }
  4901. +}
  4902. +
  4903. +dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx,
  4904. + dwc_notifier_t *notifier, unsigned is_host)
  4905. +{
  4906. + dwc_cc_if_t *cc_if = NULL;
  4907. +
  4908. + /* Allocate a common_cc_if structure */
  4909. + cc_if = dwc_alloc(mem_ctx, sizeof(dwc_cc_if_t));
  4910. +
  4911. + if (!cc_if)
  4912. + return NULL;
  4913. +
  4914. +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
  4915. + DWC_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex);
  4916. +#else
  4917. + cc_if->mutex = dwc_mutex_alloc(mtx_ctx);
  4918. +#endif
  4919. + if (!cc_if->mutex) {
  4920. + dwc_free(mem_ctx, cc_if);
  4921. + return NULL;
  4922. + }
  4923. +
  4924. + DWC_CIRCLEQ_INIT(&cc_if->list);
  4925. + cc_if->is_host = is_host;
  4926. + cc_if->notifier = notifier;
  4927. + return cc_if;
  4928. +}
  4929. +
  4930. +void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if)
  4931. +{
  4932. +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
  4933. + DWC_MUTEX_FREE(cc_if->mutex);
  4934. +#else
  4935. + dwc_mutex_free(mtx_ctx, cc_if->mutex);
  4936. +#endif
  4937. + cc_clear(mem_ctx, cc_if);
  4938. + dwc_free(mem_ctx, cc_if);
  4939. +}
  4940. +
  4941. +static void cc_changed(dwc_cc_if_t *cc_if)
  4942. +{
  4943. + if (cc_if->notifier) {
  4944. + dwc_notify(cc_if->notifier, DWC_CC_LIST_CHANGED_NOTIFICATION, cc_if);
  4945. + }
  4946. +}
  4947. +
  4948. +void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if)
  4949. +{
  4950. + DWC_MUTEX_LOCK(cc_if->mutex);
  4951. + cc_clear(mem_ctx, cc_if);
  4952. + DWC_MUTEX_UNLOCK(cc_if->mutex);
  4953. + cc_changed(cc_if);
  4954. +}
  4955. +
  4956. +int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
  4957. + uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
  4958. +{
  4959. + uint32_t uid;
  4960. +
  4961. + DWC_MUTEX_LOCK(cc_if->mutex);
  4962. + uid = cc_add(mem_ctx, cc_if, chid, cdid, ck, name, length);
  4963. + DWC_MUTEX_UNLOCK(cc_if->mutex);
  4964. + cc_changed(cc_if);
  4965. +
  4966. + return uid;
  4967. +}
  4968. +
  4969. +void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid,
  4970. + uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length)
  4971. +{
  4972. + dwc_cc_t* cc;
  4973. +
  4974. + DWC_DEBUGC("Change connection context %d", id);
  4975. +
  4976. + DWC_MUTEX_LOCK(cc_if->mutex);
  4977. + cc = cc_find(cc_if, id);
  4978. + if (!cc) {
  4979. + DWC_ERROR("Uid %d not found in cc list\n", id);
  4980. + DWC_MUTEX_UNLOCK(cc_if->mutex);
  4981. + return;
  4982. + }
  4983. +
  4984. + if (chid) {
  4985. + DWC_MEMCPY(&(cc->chid[0]), chid, 16);
  4986. + }
  4987. + if (cdid) {
  4988. + DWC_MEMCPY(&(cc->cdid[0]), cdid, 16);
  4989. + }
  4990. + if (ck) {
  4991. + DWC_MEMCPY(&(cc->ck[0]), ck, 16);
  4992. + }
  4993. +
  4994. + if (name) {
  4995. + if (cc->name) {
  4996. + dwc_free(mem_ctx, cc->name);
  4997. + }
  4998. + cc->name = dwc_alloc(mem_ctx, length);
  4999. + if (!cc->name) {
  5000. + DWC_ERROR("Out of memory in dwc_cc_change()\n");
  5001. + DWC_MUTEX_UNLOCK(cc_if->mutex);
  5002. + return;
  5003. + }
  5004. + cc->length = length;
  5005. + DWC_MEMCPY(cc->name, name, length);
  5006. + }
  5007. +
  5008. + DWC_MUTEX_UNLOCK(cc_if->mutex);
  5009. +
  5010. + cc_changed(cc_if);
  5011. +
  5012. + DWC_DEBUGC("Changed connection context id=%d\n", id);
  5013. + dump_bytes("New CHID", cc->chid, 16);
  5014. + dump_bytes("New CDID", cc->cdid, 16);
  5015. + dump_bytes("New CK", cc->ck, 16);
  5016. +}
  5017. +
  5018. +void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id)
  5019. +{
  5020. + dwc_cc_t *cc;
  5021. +
  5022. + DWC_DEBUGC("Removing connection context %d", id);
  5023. +
  5024. + DWC_MUTEX_LOCK(cc_if->mutex);
  5025. + cc = cc_find(cc_if, id);
  5026. + if (!cc) {
  5027. + DWC_ERROR("Uid %d not found in cc list\n", id);
  5028. + DWC_MUTEX_UNLOCK(cc_if->mutex);
  5029. + return;
  5030. + }
  5031. +
  5032. + DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry);
  5033. + DWC_MUTEX_UNLOCK(cc_if->mutex);
  5034. + free_cc(mem_ctx, cc);
  5035. +
  5036. + cc_changed(cc_if);
  5037. +}
  5038. +
  5039. +uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, unsigned int *length)
  5040. +{
  5041. + uint8_t *buf, *x;
  5042. + uint8_t zero = 0;
  5043. + dwc_cc_t *cc;
  5044. +
  5045. + DWC_MUTEX_LOCK(cc_if->mutex);
  5046. + *length = cc_data_size(cc_if);
  5047. + if (!(*length)) {
  5048. + DWC_MUTEX_UNLOCK(cc_if->mutex);
  5049. + return NULL;
  5050. + }
  5051. +
  5052. + DWC_DEBUGC("Creating data for saving (length=%d)", *length);
  5053. +
  5054. + buf = dwc_alloc(mem_ctx, *length);
  5055. + if (!buf) {
  5056. + *length = 0;
  5057. + DWC_MUTEX_UNLOCK(cc_if->mutex);
  5058. + return NULL;
  5059. + }
  5060. +
  5061. + x = buf;
  5062. + DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) {
  5063. + DWC_MEMCPY(x, cc->chid, 16);
  5064. + x += 16;
  5065. + DWC_MEMCPY(x, cc->cdid, 16);
  5066. + x += 16;
  5067. + DWC_MEMCPY(x, cc->ck, 16);
  5068. + x += 16;
  5069. + if (cc->name) {
  5070. + DWC_MEMCPY(x, &cc->length, 1);
  5071. + x += 1;
  5072. + DWC_MEMCPY(x, cc->name, cc->length);
  5073. + x += cc->length;
  5074. + }
  5075. + else {
  5076. + DWC_MEMCPY(x, &zero, 1);
  5077. + x += 1;
  5078. + }
  5079. + }
  5080. + DWC_MUTEX_UNLOCK(cc_if->mutex);
  5081. +
  5082. + return buf;
  5083. +}
  5084. +
  5085. +void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length)
  5086. +{
  5087. + uint8_t name_length;
  5088. + uint8_t *name;
  5089. + uint8_t *chid;
  5090. + uint8_t *cdid;
  5091. + uint8_t *ck;
  5092. + uint32_t i = 0;
  5093. +
  5094. + DWC_MUTEX_LOCK(cc_if->mutex);
  5095. + cc_clear(mem_ctx, cc_if);
  5096. +
  5097. + while (i < length) {
  5098. + chid = &data[i];
  5099. + i += 16;
  5100. + cdid = &data[i];
  5101. + i += 16;
  5102. + ck = &data[i];
  5103. + i += 16;
  5104. +
  5105. + name_length = data[i];
  5106. + i ++;
  5107. +
  5108. + if (name_length) {
  5109. + name = &data[i];
  5110. + i += name_length;
  5111. + }
  5112. + else {
  5113. + name = NULL;
  5114. + }
  5115. +
  5116. + /* check to see if we haven't overflown the buffer */
  5117. + if (i > length) {
  5118. + DWC_ERROR("Data format error while attempting to load CCs "
  5119. + "(nlen=%d, iter=%d, buflen=%d).\n", name_length, i, length);
  5120. + break;
  5121. + }
  5122. +
  5123. + cc_add(mem_ctx, cc_if, chid, cdid, ck, name, name_length);
  5124. + }
  5125. + DWC_MUTEX_UNLOCK(cc_if->mutex);
  5126. +
  5127. + cc_changed(cc_if);
  5128. +}
  5129. +
  5130. +uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid)
  5131. +{
  5132. + uint32_t uid = 0;
  5133. +
  5134. + DWC_MUTEX_LOCK(cc_if->mutex);
  5135. + uid = cc_match_chid(cc_if, chid);
  5136. + DWC_MUTEX_UNLOCK(cc_if->mutex);
  5137. + return uid;
  5138. +}
  5139. +uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid)
  5140. +{
  5141. + uint32_t uid = 0;
  5142. +
  5143. + DWC_MUTEX_LOCK(cc_if->mutex);
  5144. + uid = cc_match_cdid(cc_if, cdid);
  5145. + DWC_MUTEX_UNLOCK(cc_if->mutex);
  5146. + return uid;
  5147. +}
  5148. +
  5149. +uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id)
  5150. +{
  5151. + uint8_t *ck = NULL;
  5152. + dwc_cc_t *cc;
  5153. +
  5154. + DWC_MUTEX_LOCK(cc_if->mutex);
  5155. + cc = cc_find(cc_if, id);
  5156. + if (cc) {
  5157. + ck = cc->ck;
  5158. + }
  5159. + DWC_MUTEX_UNLOCK(cc_if->mutex);
  5160. +
  5161. + return ck;
  5162. +
  5163. +}
  5164. +
  5165. +uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id)
  5166. +{
  5167. + uint8_t *retval = NULL;
  5168. + dwc_cc_t *cc;
  5169. +
  5170. + DWC_MUTEX_LOCK(cc_if->mutex);
  5171. + cc = cc_find(cc_if, id);
  5172. + if (cc) {
  5173. + retval = cc->chid;
  5174. + }
  5175. + DWC_MUTEX_UNLOCK(cc_if->mutex);
  5176. +
  5177. + return retval;
  5178. +}
  5179. +
  5180. +uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id)
  5181. +{
  5182. + uint8_t *retval = NULL;
  5183. + dwc_cc_t *cc;
  5184. +
  5185. + DWC_MUTEX_LOCK(cc_if->mutex);
  5186. + cc = cc_find(cc_if, id);
  5187. + if (cc) {
  5188. + retval = cc->cdid;
  5189. + }
  5190. + DWC_MUTEX_UNLOCK(cc_if->mutex);
  5191. +
  5192. + return retval;
  5193. +}
  5194. +
  5195. +uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length)
  5196. +{
  5197. + uint8_t *retval = NULL;
  5198. + dwc_cc_t *cc;
  5199. +
  5200. + DWC_MUTEX_LOCK(cc_if->mutex);
  5201. + *length = 0;
  5202. + cc = cc_find(cc_if, id);
  5203. + if (cc) {
  5204. + *length = cc->length;
  5205. + retval = cc->name;
  5206. + }
  5207. + DWC_MUTEX_UNLOCK(cc_if->mutex);
  5208. +
  5209. + return retval;
  5210. +}
  5211. +
  5212. +#endif /* DWC_CCLIB */
  5213. --- /dev/null
  5214. +++ b/drivers/usb/host/dwc_common_port/dwc_cc.h
  5215. @@ -0,0 +1,224 @@
  5216. +/* =========================================================================
  5217. + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.h $
  5218. + * $Revision: #4 $
  5219. + * $Date: 2010/09/28 $
  5220. + * $Change: 1596182 $
  5221. + *
  5222. + * Synopsys Portability Library Software and documentation
  5223. + * (hereinafter, "Software") is an Unsupported proprietary work of
  5224. + * Synopsys, Inc. unless otherwise expressly agreed to in writing
  5225. + * between Synopsys and you.
  5226. + *
  5227. + * The Software IS NOT an item of Licensed Software or Licensed Product
  5228. + * under any End User Software License Agreement or Agreement for
  5229. + * Licensed Product with Synopsys or any supplement thereto. You are
  5230. + * permitted to use and redistribute this Software in source and binary
  5231. + * forms, with or without modification, provided that redistributions
  5232. + * of source code must retain this notice. You may not view, use,
  5233. + * disclose, copy or distribute this file or any information contained
  5234. + * herein except pursuant to this license grant from Synopsys. If you
  5235. + * do not agree with this notice, including the disclaimer below, then
  5236. + * you are not authorized to use the Software.
  5237. + *
  5238. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
  5239. + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  5240. + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  5241. + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
  5242. + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  5243. + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  5244. + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  5245. + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  5246. + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  5247. + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  5248. + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  5249. + * DAMAGE.
  5250. + * ========================================================================= */
  5251. +#ifndef _DWC_CC_H_
  5252. +#define _DWC_CC_H_
  5253. +
  5254. +#ifdef __cplusplus
  5255. +extern "C" {
  5256. +#endif
  5257. +
  5258. +/** @file
  5259. + *
  5260. + * This file defines the Context Context library.
  5261. + *
  5262. + * The main data structure is dwc_cc_if_t which is returned by either the
  5263. + * dwc_cc_if_alloc function or returned by the module to the user via a provided
  5264. + * function. The data structure is opaque and should only be manipulated via the
  5265. + * functions provied in this API.
  5266. + *
  5267. + * It manages a list of connection contexts and operations can be performed to
  5268. + * add, remove, query, search, and change, those contexts. Additionally,
  5269. + * a dwc_notifier_t object can be requested from the manager so that
  5270. + * the user can be notified whenever the context list has changed.
  5271. + */
  5272. +
  5273. +#include "dwc_os.h"
  5274. +#include "dwc_list.h"
  5275. +#include "dwc_notifier.h"
  5276. +
  5277. +
  5278. +/* Notifications */
  5279. +#define DWC_CC_LIST_CHANGED_NOTIFICATION "DWC_CC_LIST_CHANGED_NOTIFICATION"
  5280. +
  5281. +struct dwc_cc_if;
  5282. +typedef struct dwc_cc_if dwc_cc_if_t;
  5283. +
  5284. +
  5285. +/** @name Connection Context Operations */
  5286. +/** @{ */
  5287. +
  5288. +/** This function allocates memory for a dwc_cc_if_t structure, initializes
  5289. + * fields to default values, and returns a pointer to the structure or NULL on
  5290. + * error. */
  5291. +extern dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx,
  5292. + dwc_notifier_t *notifier, unsigned is_host);
  5293. +
  5294. +/** Frees the memory for the specified CC structure allocated from
  5295. + * dwc_cc_if_alloc(). */
  5296. +extern void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if);
  5297. +
  5298. +/** Removes all contexts from the connection context list */
  5299. +extern void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if);
  5300. +
  5301. +/** Adds a connection context (CHID, CK, CDID, Name) to the connection context list.
  5302. + * If a CHID already exists, the CK and name are overwritten. Statistics are
  5303. + * not overwritten.
  5304. + *
  5305. + * @param cc_if The cc_if structure.
  5306. + * @param chid A pointer to the 16-byte CHID. This value will be copied.
  5307. + * @param ck A pointer to the 16-byte CK. This value will be copied.
  5308. + * @param cdid A pointer to the 16-byte CDID. This value will be copied.
  5309. + * @param name An optional host friendly name as defined in the association model
  5310. + * spec. Must be a UTF16-LE unicode string. Can be NULL to indicated no name.
  5311. + * @param length The length othe unicode string.
  5312. + * @return A unique identifier used to refer to this context that is valid for
  5313. + * as long as this context is still in the list. */
  5314. +extern int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid,
  5315. + uint8_t *cdid, uint8_t *ck, uint8_t *name,
  5316. + uint8_t length);
  5317. +
  5318. +/** Changes the CHID, CK, CDID, or Name values of a connection context in the
  5319. + * list, preserving any accumulated statistics. This would typically be called
  5320. + * if the host decideds to change the context with a SET_CONNECTION request.
  5321. + *
  5322. + * @param cc_if The cc_if structure.
  5323. + * @param id The identifier of the connection context.
  5324. + * @param chid A pointer to the 16-byte CHID. This value will be copied. NULL
  5325. + * indicates no change.
  5326. + * @param cdid A pointer to the 16-byte CDID. This value will be copied. NULL
  5327. + * indicates no change.
  5328. + * @param ck A pointer to the 16-byte CK. This value will be copied. NULL
  5329. + * indicates no change.
  5330. + * @param name Host friendly name UTF16-LE. NULL indicates no change.
  5331. + * @param length Length of name. */
  5332. +extern void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id,
  5333. + uint8_t *chid, uint8_t *cdid, uint8_t *ck,
  5334. + uint8_t *name, uint8_t length);
  5335. +
  5336. +/** Remove the specified connection context.
  5337. + * @param cc_if The cc_if structure.
  5338. + * @param id The identifier of the connection context to remove. */
  5339. +extern void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id);
  5340. +
  5341. +/** Get a binary block of data for the connection context list and attributes.
  5342. + * This data can be used by the OS specific driver to save the connection
  5343. + * context list into non-volatile memory.
  5344. + *
  5345. + * @param cc_if The cc_if structure.
  5346. + * @param length Return the length of the data buffer.
  5347. + * @return A pointer to the data buffer. The memory for this buffer should be
  5348. + * freed with DWC_FREE() after use. */
  5349. +extern uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if,
  5350. + unsigned int *length);
  5351. +
  5352. +/** Restore the connection context list from the binary data that was previously
  5353. + * returned from a call to dwc_cc_data_for_save. This can be used by the OS specific
  5354. + * driver to load a connection context list from non-volatile memory.
  5355. + *
  5356. + * @param cc_if The cc_if structure.
  5357. + * @param data The data bytes as returned from dwc_cc_data_for_save.
  5358. + * @param length The length of the data. */
  5359. +extern void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if,
  5360. + uint8_t *data, unsigned int length);
  5361. +
  5362. +/** Find the connection context from the specified CHID.
  5363. + *
  5364. + * @param cc_if The cc_if structure.
  5365. + * @param chid A pointer to the CHID data.
  5366. + * @return A non-zero identifier of the connection context if the CHID matches.
  5367. + * Otherwise returns 0. */
  5368. +extern uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid);
  5369. +
  5370. +/** Find the connection context from the specified CDID.
  5371. + *
  5372. + * @param cc_if The cc_if structure.
  5373. + * @param cdid A pointer to the CDID data.
  5374. + * @return A non-zero identifier of the connection context if the CHID matches.
  5375. + * Otherwise returns 0. */
  5376. +extern uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid);
  5377. +
  5378. +/** Retrieve the CK from the specified connection context.
  5379. + *
  5380. + * @param cc_if The cc_if structure.
  5381. + * @param id The identifier of the connection context.
  5382. + * @return A pointer to the CK data. The memory does not need to be freed. */
  5383. +extern uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id);
  5384. +
  5385. +/** Retrieve the CHID from the specified connection context.
  5386. + *
  5387. + * @param cc_if The cc_if structure.
  5388. + * @param id The identifier of the connection context.
  5389. + * @return A pointer to the CHID data. The memory does not need to be freed. */
  5390. +extern uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id);
  5391. +
  5392. +/** Retrieve the CDID from the specified connection context.
  5393. + *
  5394. + * @param cc_if The cc_if structure.
  5395. + * @param id The identifier of the connection context.
  5396. + * @return A pointer to the CDID data. The memory does not need to be freed. */
  5397. +extern uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id);
  5398. +
  5399. +extern uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length);
  5400. +
  5401. +/** Checks a buffer for non-zero.
  5402. + * @param id A pointer to a 16 byte buffer.
  5403. + * @return true if the 16 byte value is non-zero. */
  5404. +static inline unsigned dwc_assoc_is_not_zero_id(uint8_t *id) {
  5405. + int i;
  5406. + for (i=0; i<16; i++) {
  5407. + if (id[i]) return 1;
  5408. + }
  5409. + return 0;
  5410. +}
  5411. +
  5412. +/** Checks a buffer for zero.
  5413. + * @param id A pointer to a 16 byte buffer.
  5414. + * @return true if the 16 byte value is zero. */
  5415. +static inline unsigned dwc_assoc_is_zero_id(uint8_t *id) {
  5416. + return !dwc_assoc_is_not_zero_id(id);
  5417. +}
  5418. +
  5419. +/** Prints an ASCII representation for the 16-byte chid, cdid, or ck, into
  5420. + * buffer. */
  5421. +static inline int dwc_print_id_string(char *buffer, uint8_t *id) {
  5422. + char *ptr = buffer;
  5423. + int i;
  5424. + for (i=0; i<16; i++) {
  5425. + ptr += DWC_SPRINTF(ptr, "%02x", id[i]);
  5426. + if (i < 15) {
  5427. + ptr += DWC_SPRINTF(ptr, " ");
  5428. + }
  5429. + }
  5430. + return ptr - buffer;
  5431. +}
  5432. +
  5433. +/** @} */
  5434. +
  5435. +#ifdef __cplusplus
  5436. +}
  5437. +#endif
  5438. +
  5439. +#endif /* _DWC_CC_H_ */
  5440. --- /dev/null
  5441. +++ b/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c
  5442. @@ -0,0 +1,1308 @@
  5443. +#include "dwc_os.h"
  5444. +#include "dwc_list.h"
  5445. +
  5446. +#ifdef DWC_CCLIB
  5447. +# include "dwc_cc.h"
  5448. +#endif
  5449. +
  5450. +#ifdef DWC_CRYPTOLIB
  5451. +# include "dwc_modpow.h"
  5452. +# include "dwc_dh.h"
  5453. +# include "dwc_crypto.h"
  5454. +#endif
  5455. +
  5456. +#ifdef DWC_NOTIFYLIB
  5457. +# include "dwc_notifier.h"
  5458. +#endif
  5459. +
  5460. +/* OS-Level Implementations */
  5461. +
  5462. +/* This is the FreeBSD 7.0 kernel implementation of the DWC platform library. */
  5463. +
  5464. +
  5465. +/* MISC */
  5466. +
  5467. +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
  5468. +{
  5469. + return memset(dest, byte, size);
  5470. +}
  5471. +
  5472. +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
  5473. +{
  5474. + return memcpy(dest, src, size);
  5475. +}
  5476. +
  5477. +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
  5478. +{
  5479. + bcopy(src, dest, size);
  5480. + return dest;
  5481. +}
  5482. +
  5483. +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
  5484. +{
  5485. + return memcmp(m1, m2, size);
  5486. +}
  5487. +
  5488. +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
  5489. +{
  5490. + return strncmp(s1, s2, size);
  5491. +}
  5492. +
  5493. +int DWC_STRCMP(void *s1, void *s2)
  5494. +{
  5495. + return strcmp(s1, s2);
  5496. +}
  5497. +
  5498. +int DWC_STRLEN(char const *str)
  5499. +{
  5500. + return strlen(str);
  5501. +}
  5502. +
  5503. +char *DWC_STRCPY(char *to, char const *from)
  5504. +{
  5505. + return strcpy(to, from);
  5506. +}
  5507. +
  5508. +char *DWC_STRDUP(char const *str)
  5509. +{
  5510. + int len = DWC_STRLEN(str) + 1;
  5511. + char *new = DWC_ALLOC_ATOMIC(len);
  5512. +
  5513. + if (!new) {
  5514. + return NULL;
  5515. + }
  5516. +
  5517. + DWC_MEMCPY(new, str, len);
  5518. + return new;
  5519. +}
  5520. +
  5521. +int DWC_ATOI(char *str, int32_t *value)
  5522. +{
  5523. + char *end = NULL;
  5524. +
  5525. + *value = strtol(str, &end, 0);
  5526. + if (*end == '\0') {
  5527. + return 0;
  5528. + }
  5529. +
  5530. + return -1;
  5531. +}
  5532. +
  5533. +int DWC_ATOUI(char *str, uint32_t *value)
  5534. +{
  5535. + char *end = NULL;
  5536. +
  5537. + *value = strtoul(str, &end, 0);
  5538. + if (*end == '\0') {
  5539. + return 0;
  5540. + }
  5541. +
  5542. + return -1;
  5543. +}
  5544. +
  5545. +
  5546. +#ifdef DWC_UTFLIB
  5547. +/* From usbstring.c */
  5548. +
  5549. +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
  5550. +{
  5551. + int count = 0;
  5552. + u8 c;
  5553. + u16 uchar;
  5554. +
  5555. + /* this insists on correct encodings, though not minimal ones.
  5556. + * BUT it currently rejects legit 4-byte UTF-8 code points,
  5557. + * which need surrogate pairs. (Unicode 3.1 can use them.)
  5558. + */
  5559. + while (len != 0 && (c = (u8) *s++) != 0) {
  5560. + if (unlikely(c & 0x80)) {
  5561. + // 2-byte sequence:
  5562. + // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
  5563. + if ((c & 0xe0) == 0xc0) {
  5564. + uchar = (c & 0x1f) << 6;
  5565. +
  5566. + c = (u8) *s++;
  5567. + if ((c & 0xc0) != 0xc0)
  5568. + goto fail;
  5569. + c &= 0x3f;
  5570. + uchar |= c;
  5571. +
  5572. + // 3-byte sequence (most CJKV characters):
  5573. + // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
  5574. + } else if ((c & 0xf0) == 0xe0) {
  5575. + uchar = (c & 0x0f) << 12;
  5576. +
  5577. + c = (u8) *s++;
  5578. + if ((c & 0xc0) != 0xc0)
  5579. + goto fail;
  5580. + c &= 0x3f;
  5581. + uchar |= c << 6;
  5582. +
  5583. + c = (u8) *s++;
  5584. + if ((c & 0xc0) != 0xc0)
  5585. + goto fail;
  5586. + c &= 0x3f;
  5587. + uchar |= c;
  5588. +
  5589. + /* no bogus surrogates */
  5590. + if (0xd800 <= uchar && uchar <= 0xdfff)
  5591. + goto fail;
  5592. +
  5593. + // 4-byte sequence (surrogate pairs, currently rare):
  5594. + // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
  5595. + // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
  5596. + // (uuuuu = wwww + 1)
  5597. + // FIXME accept the surrogate code points (only)
  5598. + } else
  5599. + goto fail;
  5600. + } else
  5601. + uchar = c;
  5602. + put_unaligned (cpu_to_le16 (uchar), cp++);
  5603. + count++;
  5604. + len--;
  5605. + }
  5606. + return count;
  5607. +fail:
  5608. + return -1;
  5609. +}
  5610. +
  5611. +#endif /* DWC_UTFLIB */
  5612. +
  5613. +
  5614. +/* dwc_debug.h */
  5615. +
  5616. +dwc_bool_t DWC_IN_IRQ(void)
  5617. +{
  5618. +// return in_irq();
  5619. + return 0;
  5620. +}
  5621. +
  5622. +dwc_bool_t DWC_IN_BH(void)
  5623. +{
  5624. +// return in_softirq();
  5625. + return 0;
  5626. +}
  5627. +
  5628. +void DWC_VPRINTF(char *format, va_list args)
  5629. +{
  5630. + vprintf(format, args);
  5631. +}
  5632. +
  5633. +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
  5634. +{
  5635. + return vsnprintf(str, size, format, args);
  5636. +}
  5637. +
  5638. +void DWC_PRINTF(char *format, ...)
  5639. +{
  5640. + va_list args;
  5641. +
  5642. + va_start(args, format);
  5643. + DWC_VPRINTF(format, args);
  5644. + va_end(args);
  5645. +}
  5646. +
  5647. +int DWC_SPRINTF(char *buffer, char *format, ...)
  5648. +{
  5649. + int retval;
  5650. + va_list args;
  5651. +
  5652. + va_start(args, format);
  5653. + retval = vsprintf(buffer, format, args);
  5654. + va_end(args);
  5655. + return retval;
  5656. +}
  5657. +
  5658. +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
  5659. +{
  5660. + int retval;
  5661. + va_list args;
  5662. +
  5663. + va_start(args, format);
  5664. + retval = vsnprintf(buffer, size, format, args);
  5665. + va_end(args);
  5666. + return retval;
  5667. +}
  5668. +
  5669. +void __DWC_WARN(char *format, ...)
  5670. +{
  5671. + va_list args;
  5672. +
  5673. + va_start(args, format);
  5674. + DWC_VPRINTF(format, args);
  5675. + va_end(args);
  5676. +}
  5677. +
  5678. +void __DWC_ERROR(char *format, ...)
  5679. +{
  5680. + va_list args;
  5681. +
  5682. + va_start(args, format);
  5683. + DWC_VPRINTF(format, args);
  5684. + va_end(args);
  5685. +}
  5686. +
  5687. +void DWC_EXCEPTION(char *format, ...)
  5688. +{
  5689. + va_list args;
  5690. +
  5691. + va_start(args, format);
  5692. + DWC_VPRINTF(format, args);
  5693. + va_end(args);
  5694. +// BUG_ON(1); ???
  5695. +}
  5696. +
  5697. +#ifdef DEBUG
  5698. +void __DWC_DEBUG(char *format, ...)
  5699. +{
  5700. + va_list args;
  5701. +
  5702. + va_start(args, format);
  5703. + DWC_VPRINTF(format, args);
  5704. + va_end(args);
  5705. +}
  5706. +#endif
  5707. +
  5708. +
  5709. +/* dwc_mem.h */
  5710. +
  5711. +#if 0
  5712. +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
  5713. + uint32_t align,
  5714. + uint32_t alloc)
  5715. +{
  5716. + struct dma_pool *pool = dma_pool_create("Pool", NULL,
  5717. + size, align, alloc);
  5718. + return (dwc_pool_t *)pool;
  5719. +}
  5720. +
  5721. +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
  5722. +{
  5723. + dma_pool_destroy((struct dma_pool *)pool);
  5724. +}
  5725. +
  5726. +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
  5727. +{
  5728. +// return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
  5729. + return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr);
  5730. +}
  5731. +
  5732. +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
  5733. +{
  5734. + void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
  5735. + memset(..);
  5736. +}
  5737. +
  5738. +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
  5739. +{
  5740. + dma_pool_free(pool, vaddr, daddr);
  5741. +}
  5742. +#endif
  5743. +
  5744. +static void dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
  5745. +{
  5746. + if (error)
  5747. + return;
  5748. + *(bus_addr_t *)arg = segs[0].ds_addr;
  5749. +}
  5750. +
  5751. +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
  5752. +{
  5753. + dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
  5754. + int error;
  5755. +
  5756. + error = bus_dma_tag_create(
  5757. +#if __FreeBSD_version >= 700000
  5758. + bus_get_dma_tag(dma->dev), /* parent */
  5759. +#else
  5760. + NULL, /* parent */
  5761. +#endif
  5762. + 4, 0, /* alignment, bounds */
  5763. + BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
  5764. + BUS_SPACE_MAXADDR, /* highaddr */
  5765. + NULL, NULL, /* filter, filterarg */
  5766. + size, /* maxsize */
  5767. + 1, /* nsegments */
  5768. + size, /* maxsegsize */
  5769. + 0, /* flags */
  5770. + NULL, /* lockfunc */
  5771. + NULL, /* lockarg */
  5772. + &dma->dma_tag);
  5773. + if (error) {
  5774. + device_printf(dma->dev, "%s: bus_dma_tag_create failed: %d\n",
  5775. + __func__, error);
  5776. + goto fail_0;
  5777. + }
  5778. +
  5779. + error = bus_dmamem_alloc(dma->dma_tag, &dma->dma_vaddr,
  5780. + BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map);
  5781. + if (error) {
  5782. + device_printf(dma->dev, "%s: bus_dmamem_alloc(%ju) failed: %d\n",
  5783. + __func__, (uintmax_t)size, error);
  5784. + goto fail_1;
  5785. + }
  5786. +
  5787. + dma->dma_paddr = 0;
  5788. + error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, size,
  5789. + dmamap_cb, &dma->dma_paddr, BUS_DMA_NOWAIT);
  5790. + if (error || dma->dma_paddr == 0) {
  5791. + device_printf(dma->dev, "%s: bus_dmamap_load failed: %d\n",
  5792. + __func__, error);
  5793. + goto fail_2;
  5794. + }
  5795. +
  5796. + *dma_addr = dma->dma_paddr;
  5797. + return dma->dma_vaddr;
  5798. +
  5799. +fail_2:
  5800. + bus_dmamap_unload(dma->dma_tag, dma->dma_map);
  5801. +fail_1:
  5802. + bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
  5803. + bus_dma_tag_destroy(dma->dma_tag);
  5804. +fail_0:
  5805. + dma->dma_map = NULL;
  5806. + dma->dma_tag = NULL;
  5807. +
  5808. + return NULL;
  5809. +}
  5810. +
  5811. +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
  5812. +{
  5813. + dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
  5814. +
  5815. + if (dma->dma_tag == NULL)
  5816. + return;
  5817. + if (dma->dma_map != NULL) {
  5818. + bus_dmamap_sync(dma->dma_tag, dma->dma_map,
  5819. + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
  5820. + bus_dmamap_unload(dma->dma_tag, dma->dma_map);
  5821. + bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map);
  5822. + dma->dma_map = NULL;
  5823. + }
  5824. +
  5825. + bus_dma_tag_destroy(dma->dma_tag);
  5826. + dma->dma_tag = NULL;
  5827. +}
  5828. +
  5829. +void *__DWC_ALLOC(void *mem_ctx, uint32_t size)
  5830. +{
  5831. + return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
  5832. +}
  5833. +
  5834. +void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)
  5835. +{
  5836. + return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
  5837. +}
  5838. +
  5839. +void __DWC_FREE(void *mem_ctx, void *addr)
  5840. +{
  5841. + free(addr, M_DEVBUF);
  5842. +}
  5843. +
  5844. +
  5845. +#ifdef DWC_CRYPTOLIB
  5846. +/* dwc_crypto.h */
  5847. +
  5848. +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
  5849. +{
  5850. + get_random_bytes(buffer, length);
  5851. +}
  5852. +
  5853. +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
  5854. +{
  5855. + struct crypto_blkcipher *tfm;
  5856. + struct blkcipher_desc desc;
  5857. + struct scatterlist sgd;
  5858. + struct scatterlist sgs;
  5859. +
  5860. + tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
  5861. + if (tfm == NULL) {
  5862. + printk("failed to load transform for aes CBC\n");
  5863. + return -1;
  5864. + }
  5865. +
  5866. + crypto_blkcipher_setkey(tfm, key, keylen);
  5867. + crypto_blkcipher_set_iv(tfm, iv, 16);
  5868. +
  5869. + sg_init_one(&sgd, out, messagelen);
  5870. + sg_init_one(&sgs, message, messagelen);
  5871. +
  5872. + desc.tfm = tfm;
  5873. + desc.flags = 0;
  5874. +
  5875. + if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
  5876. + crypto_free_blkcipher(tfm);
  5877. + DWC_ERROR("AES CBC encryption failed");
  5878. + return -1;
  5879. + }
  5880. +
  5881. + crypto_free_blkcipher(tfm);
  5882. + return 0;
  5883. +}
  5884. +
  5885. +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
  5886. +{
  5887. + struct crypto_hash *tfm;
  5888. + struct hash_desc desc;
  5889. + struct scatterlist sg;
  5890. +
  5891. + tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
  5892. + if (IS_ERR(tfm)) {
  5893. + DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm));
  5894. + return 0;
  5895. + }
  5896. + desc.tfm = tfm;
  5897. + desc.flags = 0;
  5898. +
  5899. + sg_init_one(&sg, message, len);
  5900. + crypto_hash_digest(&desc, &sg, len, out);
  5901. + crypto_free_hash(tfm);
  5902. +
  5903. + return 1;
  5904. +}
  5905. +
  5906. +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
  5907. + uint8_t *key, uint32_t keylen, uint8_t *out)
  5908. +{
  5909. + struct crypto_hash *tfm;
  5910. + struct hash_desc desc;
  5911. + struct scatterlist sg;
  5912. +
  5913. + tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
  5914. + if (IS_ERR(tfm)) {
  5915. + DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm));
  5916. + return 0;
  5917. + }
  5918. + desc.tfm = tfm;
  5919. + desc.flags = 0;
  5920. +
  5921. + sg_init_one(&sg, message, messagelen);
  5922. + crypto_hash_setkey(tfm, key, keylen);
  5923. + crypto_hash_digest(&desc, &sg, messagelen, out);
  5924. + crypto_free_hash(tfm);
  5925. +
  5926. + return 1;
  5927. +}
  5928. +
  5929. +#endif /* DWC_CRYPTOLIB */
  5930. +
  5931. +
  5932. +/* Byte Ordering Conversions */
  5933. +
  5934. +uint32_t DWC_CPU_TO_LE32(uint32_t *p)
  5935. +{
  5936. +#ifdef __LITTLE_ENDIAN
  5937. + return *p;
  5938. +#else
  5939. + uint8_t *u_p = (uint8_t *)p;
  5940. +
  5941. + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
  5942. +#endif
  5943. +}
  5944. +
  5945. +uint32_t DWC_CPU_TO_BE32(uint32_t *p)
  5946. +{
  5947. +#ifdef __BIG_ENDIAN
  5948. + return *p;
  5949. +#else
  5950. + uint8_t *u_p = (uint8_t *)p;
  5951. +
  5952. + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
  5953. +#endif
  5954. +}
  5955. +
  5956. +uint32_t DWC_LE32_TO_CPU(uint32_t *p)
  5957. +{
  5958. +#ifdef __LITTLE_ENDIAN
  5959. + return *p;
  5960. +#else
  5961. + uint8_t *u_p = (uint8_t *)p;
  5962. +
  5963. + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
  5964. +#endif
  5965. +}
  5966. +
  5967. +uint32_t DWC_BE32_TO_CPU(uint32_t *p)
  5968. +{
  5969. +#ifdef __BIG_ENDIAN
  5970. + return *p;
  5971. +#else
  5972. + uint8_t *u_p = (uint8_t *)p;
  5973. +
  5974. + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
  5975. +#endif
  5976. +}
  5977. +
  5978. +uint16_t DWC_CPU_TO_LE16(uint16_t *p)
  5979. +{
  5980. +#ifdef __LITTLE_ENDIAN
  5981. + return *p;
  5982. +#else
  5983. + uint8_t *u_p = (uint8_t *)p;
  5984. + return (u_p[1] | (u_p[0] << 8));
  5985. +#endif
  5986. +}
  5987. +
  5988. +uint16_t DWC_CPU_TO_BE16(uint16_t *p)
  5989. +{
  5990. +#ifdef __BIG_ENDIAN
  5991. + return *p;
  5992. +#else
  5993. + uint8_t *u_p = (uint8_t *)p;
  5994. + return (u_p[1] | (u_p[0] << 8));
  5995. +#endif
  5996. +}
  5997. +
  5998. +uint16_t DWC_LE16_TO_CPU(uint16_t *p)
  5999. +{
  6000. +#ifdef __LITTLE_ENDIAN
  6001. + return *p;
  6002. +#else
  6003. + uint8_t *u_p = (uint8_t *)p;
  6004. + return (u_p[1] | (u_p[0] << 8));
  6005. +#endif
  6006. +}
  6007. +
  6008. +uint16_t DWC_BE16_TO_CPU(uint16_t *p)
  6009. +{
  6010. +#ifdef __BIG_ENDIAN
  6011. + return *p;
  6012. +#else
  6013. + uint8_t *u_p = (uint8_t *)p;
  6014. + return (u_p[1] | (u_p[0] << 8));
  6015. +#endif
  6016. +}
  6017. +
  6018. +
  6019. +/* Registers */
  6020. +
  6021. +uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg)
  6022. +{
  6023. + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
  6024. + bus_size_t ior = (bus_size_t)reg;
  6025. +
  6026. + return bus_space_read_4(io->iot, io->ioh, ior);
  6027. +}
  6028. +
  6029. +#if 0
  6030. +uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg)
  6031. +{
  6032. + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
  6033. + bus_size_t ior = (bus_size_t)reg;
  6034. +
  6035. + return bus_space_read_8(io->iot, io->ioh, ior);
  6036. +}
  6037. +#endif
  6038. +
  6039. +void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value)
  6040. +{
  6041. + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
  6042. + bus_size_t ior = (bus_size_t)reg;
  6043. +
  6044. + bus_space_write_4(io->iot, io->ioh, ior, value);
  6045. +}
  6046. +
  6047. +#if 0
  6048. +void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value)
  6049. +{
  6050. + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
  6051. + bus_size_t ior = (bus_size_t)reg;
  6052. +
  6053. + bus_space_write_8(io->iot, io->ioh, ior, value);
  6054. +}
  6055. +#endif
  6056. +
  6057. +void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask,
  6058. + uint32_t set_mask)
  6059. +{
  6060. + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
  6061. + bus_size_t ior = (bus_size_t)reg;
  6062. +
  6063. + bus_space_write_4(io->iot, io->ioh, ior,
  6064. + (bus_space_read_4(io->iot, io->ioh, ior) &
  6065. + ~clear_mask) | set_mask);
  6066. +}
  6067. +
  6068. +#if 0
  6069. +void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask,
  6070. + uint64_t set_mask)
  6071. +{
  6072. + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
  6073. + bus_size_t ior = (bus_size_t)reg;
  6074. +
  6075. + bus_space_write_8(io->iot, io->ioh, ior,
  6076. + (bus_space_read_8(io->iot, io->ioh, ior) &
  6077. + ~clear_mask) | set_mask);
  6078. +}
  6079. +#endif
  6080. +
  6081. +
  6082. +/* Locking */
  6083. +
  6084. +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
  6085. +{
  6086. + struct mtx *sl = DWC_ALLOC(sizeof(*sl));
  6087. +
  6088. + if (!sl) {
  6089. + DWC_ERROR("Cannot allocate memory for spinlock");
  6090. + return NULL;
  6091. + }
  6092. +
  6093. + mtx_init(sl, "dw3spn", NULL, MTX_SPIN);
  6094. + return (dwc_spinlock_t *)sl;
  6095. +}
  6096. +
  6097. +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
  6098. +{
  6099. + struct mtx *sl = (struct mtx *)lock;
  6100. +
  6101. + mtx_destroy(sl);
  6102. + DWC_FREE(sl);
  6103. +}
  6104. +
  6105. +void DWC_SPINLOCK(dwc_spinlock_t *lock)
  6106. +{
  6107. + mtx_lock_spin((struct mtx *)lock); // ???
  6108. +}
  6109. +
  6110. +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
  6111. +{
  6112. + mtx_unlock_spin((struct mtx *)lock); // ???
  6113. +}
  6114. +
  6115. +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)
  6116. +{
  6117. + mtx_lock_spin((struct mtx *)lock);
  6118. +}
  6119. +
  6120. +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)
  6121. +{
  6122. + mtx_unlock_spin((struct mtx *)lock);
  6123. +}
  6124. +
  6125. +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
  6126. +{
  6127. + struct mtx *m;
  6128. + dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mtx));
  6129. +
  6130. + if (!mutex) {
  6131. + DWC_ERROR("Cannot allocate memory for mutex");
  6132. + return NULL;
  6133. + }
  6134. +
  6135. + m = (struct mtx *)mutex;
  6136. + mtx_init(m, "dw3mtx", NULL, MTX_DEF);
  6137. + return mutex;
  6138. +}
  6139. +
  6140. +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
  6141. +#else
  6142. +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
  6143. +{
  6144. + mtx_destroy((struct mtx *)mutex);
  6145. + DWC_FREE(mutex);
  6146. +}
  6147. +#endif
  6148. +
  6149. +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
  6150. +{
  6151. + struct mtx *m = (struct mtx *)mutex;
  6152. +
  6153. + mtx_lock(m);
  6154. +}
  6155. +
  6156. +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
  6157. +{
  6158. + struct mtx *m = (struct mtx *)mutex;
  6159. +
  6160. + return mtx_trylock(m);
  6161. +}
  6162. +
  6163. +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
  6164. +{
  6165. + struct mtx *m = (struct mtx *)mutex;
  6166. +
  6167. + mtx_unlock(m);
  6168. +}
  6169. +
  6170. +
  6171. +/* Timing */
  6172. +
  6173. +void DWC_UDELAY(uint32_t usecs)
  6174. +{
  6175. + DELAY(usecs);
  6176. +}
  6177. +
  6178. +void DWC_MDELAY(uint32_t msecs)
  6179. +{
  6180. + do {
  6181. + DELAY(1000);
  6182. + } while (--msecs);
  6183. +}
  6184. +
  6185. +void DWC_MSLEEP(uint32_t msecs)
  6186. +{
  6187. + struct timeval tv;
  6188. +
  6189. + tv.tv_sec = msecs / 1000;
  6190. + tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
  6191. + pause("dw3slp", tvtohz(&tv));
  6192. +}
  6193. +
  6194. +uint32_t DWC_TIME(void)
  6195. +{
  6196. + struct timeval tv;
  6197. +
  6198. + microuptime(&tv); // or getmicrouptime? (less precise, but faster)
  6199. + return tv.tv_sec * 1000 + tv.tv_usec / 1000;
  6200. +}
  6201. +
  6202. +
  6203. +/* Timers */
  6204. +
  6205. +struct dwc_timer {
  6206. + struct callout t;
  6207. + char *name;
  6208. + dwc_spinlock_t *lock;
  6209. + dwc_timer_callback_t cb;
  6210. + void *data;
  6211. +};
  6212. +
  6213. +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
  6214. +{
  6215. + dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
  6216. +
  6217. + if (!t) {
  6218. + DWC_ERROR("Cannot allocate memory for timer");
  6219. + return NULL;
  6220. + }
  6221. +
  6222. + callout_init(&t->t, 1);
  6223. +
  6224. + t->name = DWC_STRDUP(name);
  6225. + if (!t->name) {
  6226. + DWC_ERROR("Cannot allocate memory for timer->name");
  6227. + goto no_name;
  6228. + }
  6229. +
  6230. + t->lock = DWC_SPINLOCK_ALLOC();
  6231. + if (!t->lock) {
  6232. + DWC_ERROR("Cannot allocate memory for lock");
  6233. + goto no_lock;
  6234. + }
  6235. +
  6236. + t->cb = cb;
  6237. + t->data = data;
  6238. +
  6239. + return t;
  6240. +
  6241. + no_lock:
  6242. + DWC_FREE(t->name);
  6243. + no_name:
  6244. + DWC_FREE(t);
  6245. +
  6246. + return NULL;
  6247. +}
  6248. +
  6249. +void DWC_TIMER_FREE(dwc_timer_t *timer)
  6250. +{
  6251. + callout_stop(&timer->t);
  6252. + DWC_SPINLOCK_FREE(timer->lock);
  6253. + DWC_FREE(timer->name);
  6254. + DWC_FREE(timer);
  6255. +}
  6256. +
  6257. +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
  6258. +{
  6259. + struct timeval tv;
  6260. +
  6261. + tv.tv_sec = time / 1000;
  6262. + tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
  6263. + callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data);
  6264. +}
  6265. +
  6266. +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
  6267. +{
  6268. + callout_stop(&timer->t);
  6269. +}
  6270. +
  6271. +
  6272. +/* Wait Queues */
  6273. +
  6274. +struct dwc_waitq {
  6275. + struct mtx lock;
  6276. + int abort;
  6277. +};
  6278. +
  6279. +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
  6280. +{
  6281. + dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
  6282. +
  6283. + if (!wq) {
  6284. + DWC_ERROR("Cannot allocate memory for waitqueue");
  6285. + return NULL;
  6286. + }
  6287. +
  6288. + mtx_init(&wq->lock, "dw3wtq", NULL, MTX_DEF);
  6289. + wq->abort = 0;
  6290. +
  6291. + return wq;
  6292. +}
  6293. +
  6294. +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
  6295. +{
  6296. + mtx_destroy(&wq->lock);
  6297. + DWC_FREE(wq);
  6298. +}
  6299. +
  6300. +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)
  6301. +{
  6302. +// intrmask_t ipl;
  6303. + int result = 0;
  6304. +
  6305. + mtx_lock(&wq->lock);
  6306. +// ipl = splbio();
  6307. +
  6308. + /* Skip the sleep if already aborted or triggered */
  6309. + if (!wq->abort && !cond(data)) {
  6310. +// splx(ipl);
  6311. + result = msleep(wq, &wq->lock, PCATCH, "dw3wat", 0); // infinite timeout
  6312. +// ipl = splbio();
  6313. + }
  6314. +
  6315. + if (result == ERESTART) { // signaled - restart
  6316. + result = -DWC_E_RESTART;
  6317. +
  6318. + } else if (result == EINTR) { // signaled - interrupt
  6319. + result = -DWC_E_ABORT;
  6320. +
  6321. + } else if (wq->abort) {
  6322. + result = -DWC_E_ABORT;
  6323. +
  6324. + } else {
  6325. + result = 0;
  6326. + }
  6327. +
  6328. + wq->abort = 0;
  6329. +// splx(ipl);
  6330. + mtx_unlock(&wq->lock);
  6331. + return result;
  6332. +}
  6333. +
  6334. +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
  6335. + void *data, int32_t msecs)
  6336. +{
  6337. + struct timeval tv, tv1, tv2;
  6338. +// intrmask_t ipl;
  6339. + int result = 0;
  6340. +
  6341. + tv.tv_sec = msecs / 1000;
  6342. + tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
  6343. +
  6344. + mtx_lock(&wq->lock);
  6345. +// ipl = splbio();
  6346. +
  6347. + /* Skip the sleep if already aborted or triggered */
  6348. + if (!wq->abort && !cond(data)) {
  6349. +// splx(ipl);
  6350. + getmicrouptime(&tv1);
  6351. + result = msleep(wq, &wq->lock, PCATCH, "dw3wto", tvtohz(&tv));
  6352. + getmicrouptime(&tv2);
  6353. +// ipl = splbio();
  6354. + }
  6355. +
  6356. + if (result == 0) { // awoken
  6357. + if (wq->abort) {
  6358. + result = -DWC_E_ABORT;
  6359. + } else {
  6360. + tv2.tv_usec -= tv1.tv_usec;
  6361. + if (tv2.tv_usec < 0) {
  6362. + tv2.tv_usec += 1000000;
  6363. + tv2.tv_sec--;
  6364. + }
  6365. +
  6366. + tv2.tv_sec -= tv1.tv_sec;
  6367. + result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;
  6368. + result = msecs - result;
  6369. + if (result <= 0)
  6370. + result = 1;
  6371. + }
  6372. + } else if (result == ERESTART) { // signaled - restart
  6373. + result = -DWC_E_RESTART;
  6374. +
  6375. + } else if (result == EINTR) { // signaled - interrupt
  6376. + result = -DWC_E_ABORT;
  6377. +
  6378. + } else { // timed out
  6379. + result = -DWC_E_TIMEOUT;
  6380. + }
  6381. +
  6382. + wq->abort = 0;
  6383. +// splx(ipl);
  6384. + mtx_unlock(&wq->lock);
  6385. + return result;
  6386. +}
  6387. +
  6388. +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
  6389. +{
  6390. + wakeup(wq);
  6391. +}
  6392. +
  6393. +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
  6394. +{
  6395. +// intrmask_t ipl;
  6396. +
  6397. + mtx_lock(&wq->lock);
  6398. +// ipl = splbio();
  6399. + wq->abort = 1;
  6400. + wakeup(wq);
  6401. +// splx(ipl);
  6402. + mtx_unlock(&wq->lock);
  6403. +}
  6404. +
  6405. +
  6406. +/* Threading */
  6407. +
  6408. +struct dwc_thread {
  6409. + struct proc *proc;
  6410. + int abort;
  6411. +};
  6412. +
  6413. +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)
  6414. +{
  6415. + int retval;
  6416. + dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread));
  6417. +
  6418. + if (!thread) {
  6419. + return NULL;
  6420. + }
  6421. +
  6422. + thread->abort = 0;
  6423. + retval = kthread_create((void (*)(void *))func, data, &thread->proc,
  6424. + RFPROC | RFNOWAIT, 0, "%s", name);
  6425. + if (retval) {
  6426. + DWC_FREE(thread);
  6427. + return NULL;
  6428. + }
  6429. +
  6430. + return thread;
  6431. +}
  6432. +
  6433. +int DWC_THREAD_STOP(dwc_thread_t *thread)
  6434. +{
  6435. + int retval;
  6436. +
  6437. + thread->abort = 1;
  6438. + retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz);
  6439. +
  6440. + if (retval == 0) {
  6441. + /* DWC_THREAD_EXIT() will free the thread struct */
  6442. + return 0;
  6443. + }
  6444. +
  6445. + /* NOTE: We leak the thread struct if thread doesn't die */
  6446. +
  6447. + if (retval == EWOULDBLOCK) {
  6448. + return -DWC_E_TIMEOUT;
  6449. + }
  6450. +
  6451. + return -DWC_E_UNKNOWN;
  6452. +}
  6453. +
  6454. +dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread)
  6455. +{
  6456. + return thread->abort;
  6457. +}
  6458. +
  6459. +void DWC_THREAD_EXIT(dwc_thread_t *thread)
  6460. +{
  6461. + wakeup(&thread->abort);
  6462. + DWC_FREE(thread);
  6463. + kthread_exit(0);
  6464. +}
  6465. +
  6466. +
  6467. +/* tasklets
  6468. + - Runs in interrupt context (cannot sleep)
  6469. + - Each tasklet runs on a single CPU [ How can we ensure this on FreeBSD? Does it matter? ]
  6470. + - Different tasklets can be running simultaneously on different CPUs [ shouldn't matter ]
  6471. + */
  6472. +struct dwc_tasklet {
  6473. + struct task t;
  6474. + dwc_tasklet_callback_t cb;
  6475. + void *data;
  6476. +};
  6477. +
  6478. +static void tasklet_callback(void *data, int pending) // what to do with pending ???
  6479. +{
  6480. + dwc_tasklet_t *task = (dwc_tasklet_t *)data;
  6481. +
  6482. + task->cb(task->data);
  6483. +}
  6484. +
  6485. +dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)
  6486. +{
  6487. + dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task));
  6488. +
  6489. + if (task) {
  6490. + task->cb = cb;
  6491. + task->data = data;
  6492. + TASK_INIT(&task->t, 0, tasklet_callback, task);
  6493. + } else {
  6494. + DWC_ERROR("Cannot allocate memory for tasklet");
  6495. + }
  6496. +
  6497. + return task;
  6498. +}
  6499. +
  6500. +void DWC_TASK_FREE(dwc_tasklet_t *task)
  6501. +{
  6502. + taskqueue_drain(taskqueue_fast, &task->t); // ???
  6503. + DWC_FREE(task);
  6504. +}
  6505. +
  6506. +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
  6507. +{
  6508. + /* Uses predefined system queue */
  6509. + taskqueue_enqueue_fast(taskqueue_fast, &task->t);
  6510. +}
  6511. +
  6512. +
  6513. +/* workqueues
  6514. + - Runs in process context (can sleep)
  6515. + */
  6516. +typedef struct work_container {
  6517. + dwc_work_callback_t cb;
  6518. + void *data;
  6519. + dwc_workq_t *wq;
  6520. + char *name;
  6521. + int hz;
  6522. +
  6523. +#ifdef DEBUG
  6524. + DWC_CIRCLEQ_ENTRY(work_container) entry;
  6525. +#endif
  6526. + struct task task;
  6527. +} work_container_t;
  6528. +
  6529. +#ifdef DEBUG
  6530. +DWC_CIRCLEQ_HEAD(work_container_queue, work_container);
  6531. +#endif
  6532. +
  6533. +struct dwc_workq {
  6534. + struct taskqueue *taskq;
  6535. + dwc_spinlock_t *lock;
  6536. + dwc_waitq_t *waitq;
  6537. + int pending;
  6538. +
  6539. +#ifdef DEBUG
  6540. + struct work_container_queue entries;
  6541. +#endif
  6542. +};
  6543. +
  6544. +static void do_work(void *data, int pending) // what to do with pending ???
  6545. +{
  6546. + work_container_t *container = (work_container_t *)data;
  6547. + dwc_workq_t *wq = container->wq;
  6548. + dwc_irqflags_t flags;
  6549. +
  6550. + if (container->hz) {
  6551. + pause("dw3wrk", container->hz);
  6552. + }
  6553. +
  6554. + container->cb(container->data);
  6555. + DWC_DEBUG("Work done: %s, container=%p", container->name, container);
  6556. +
  6557. + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
  6558. +
  6559. +#ifdef DEBUG
  6560. + DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry);
  6561. +#endif
  6562. + if (container->name)
  6563. + DWC_FREE(container->name);
  6564. + DWC_FREE(container);
  6565. + wq->pending--;
  6566. + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
  6567. + DWC_WAITQ_TRIGGER(wq->waitq);
  6568. +}
  6569. +
  6570. +static int work_done(void *data)
  6571. +{
  6572. + dwc_workq_t *workq = (dwc_workq_t *)data;
  6573. +
  6574. + return workq->pending == 0;
  6575. +}
  6576. +
  6577. +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
  6578. +{
  6579. + return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
  6580. +}
  6581. +
  6582. +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
  6583. +{
  6584. + dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
  6585. +
  6586. + if (!wq) {
  6587. + DWC_ERROR("Cannot allocate memory for workqueue");
  6588. + return NULL;
  6589. + }
  6590. +
  6591. + wq->taskq = taskqueue_create(name, M_NOWAIT, taskqueue_thread_enqueue, &wq->taskq);
  6592. + if (!wq->taskq) {
  6593. + DWC_ERROR("Cannot allocate memory for taskqueue");
  6594. + goto no_taskq;
  6595. + }
  6596. +
  6597. + wq->pending = 0;
  6598. +
  6599. + wq->lock = DWC_SPINLOCK_ALLOC();
  6600. + if (!wq->lock) {
  6601. + DWC_ERROR("Cannot allocate memory for spinlock");
  6602. + goto no_lock;
  6603. + }
  6604. +
  6605. + wq->waitq = DWC_WAITQ_ALLOC();
  6606. + if (!wq->waitq) {
  6607. + DWC_ERROR("Cannot allocate memory for waitqueue");
  6608. + goto no_waitq;
  6609. + }
  6610. +
  6611. + taskqueue_start_threads(&wq->taskq, 1, PWAIT, "%s taskq", "dw3tsk");
  6612. +
  6613. +#ifdef DEBUG
  6614. + DWC_CIRCLEQ_INIT(&wq->entries);
  6615. +#endif
  6616. + return wq;
  6617. +
  6618. + no_waitq:
  6619. + DWC_SPINLOCK_FREE(wq->lock);
  6620. + no_lock:
  6621. + taskqueue_free(wq->taskq);
  6622. + no_taskq:
  6623. + DWC_FREE(wq);
  6624. +
  6625. + return NULL;
  6626. +}
  6627. +
  6628. +void DWC_WORKQ_FREE(dwc_workq_t *wq)
  6629. +{
  6630. +#ifdef DEBUG
  6631. + dwc_irqflags_t flags;
  6632. +
  6633. + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
  6634. +
  6635. + if (wq->pending != 0) {
  6636. + struct work_container *container;
  6637. +
  6638. + DWC_ERROR("Destroying work queue with pending work");
  6639. +
  6640. + DWC_CIRCLEQ_FOREACH(container, &wq->entries, entry) {
  6641. + DWC_ERROR("Work %s still pending", container->name);
  6642. + }
  6643. + }
  6644. +
  6645. + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
  6646. +#endif
  6647. + DWC_WAITQ_FREE(wq->waitq);
  6648. + DWC_SPINLOCK_FREE(wq->lock);
  6649. + taskqueue_free(wq->taskq);
  6650. + DWC_FREE(wq);
  6651. +}
  6652. +
  6653. +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,
  6654. + char *format, ...)
  6655. +{
  6656. + dwc_irqflags_t flags;
  6657. + work_container_t *container;
  6658. + static char name[128];
  6659. + va_list args;
  6660. +
  6661. + va_start(args, format);
  6662. + DWC_VSNPRINTF(name, 128, format, args);
  6663. + va_end(args);
  6664. +
  6665. + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
  6666. + wq->pending++;
  6667. + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
  6668. + DWC_WAITQ_TRIGGER(wq->waitq);
  6669. +
  6670. + container = DWC_ALLOC_ATOMIC(sizeof(*container));
  6671. + if (!container) {
  6672. + DWC_ERROR("Cannot allocate memory for container");
  6673. + return;
  6674. + }
  6675. +
  6676. + container->name = DWC_STRDUP(name);
  6677. + if (!container->name) {
  6678. + DWC_ERROR("Cannot allocate memory for container->name");
  6679. + DWC_FREE(container);
  6680. + return;
  6681. + }
  6682. +
  6683. + container->cb = cb;
  6684. + container->data = data;
  6685. + container->wq = wq;
  6686. + container->hz = 0;
  6687. +
  6688. + DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
  6689. +
  6690. + TASK_INIT(&container->task, 0, do_work, container);
  6691. +
  6692. +#ifdef DEBUG
  6693. + DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
  6694. +#endif
  6695. + taskqueue_enqueue_fast(wq->taskq, &container->task);
  6696. +}
  6697. +
  6698. +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,
  6699. + void *data, uint32_t time, char *format, ...)
  6700. +{
  6701. + dwc_irqflags_t flags;
  6702. + work_container_t *container;
  6703. + static char name[128];
  6704. + struct timeval tv;
  6705. + va_list args;
  6706. +
  6707. + va_start(args, format);
  6708. + DWC_VSNPRINTF(name, 128, format, args);
  6709. + va_end(args);
  6710. +
  6711. + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
  6712. + wq->pending++;
  6713. + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
  6714. + DWC_WAITQ_TRIGGER(wq->waitq);
  6715. +
  6716. + container = DWC_ALLOC_ATOMIC(sizeof(*container));
  6717. + if (!container) {
  6718. + DWC_ERROR("Cannot allocate memory for container");
  6719. + return;
  6720. + }
  6721. +
  6722. + container->name = DWC_STRDUP(name);
  6723. + if (!container->name) {
  6724. + DWC_ERROR("Cannot allocate memory for container->name");
  6725. + DWC_FREE(container);
  6726. + return;
  6727. + }
  6728. +
  6729. + container->cb = cb;
  6730. + container->data = data;
  6731. + container->wq = wq;
  6732. +
  6733. + tv.tv_sec = time / 1000;
  6734. + tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
  6735. + container->hz = tvtohz(&tv);
  6736. +
  6737. + DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
  6738. +
  6739. + TASK_INIT(&container->task, 0, do_work, container);
  6740. +
  6741. +#ifdef DEBUG
  6742. + DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
  6743. +#endif
  6744. + taskqueue_enqueue_fast(wq->taskq, &container->task);
  6745. +}
  6746. +
  6747. +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
  6748. +{
  6749. + return wq->pending;
  6750. +}
  6751. --- /dev/null
  6752. +++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c
  6753. @@ -0,0 +1,1429 @@
  6754. +#include <linux/kernel.h>
  6755. +#include <linux/init.h>
  6756. +#include <linux/module.h>
  6757. +#include <linux/kthread.h>
  6758. +
  6759. +#ifdef DWC_CCLIB
  6760. +# include "dwc_cc.h"
  6761. +#endif
  6762. +
  6763. +#ifdef DWC_CRYPTOLIB
  6764. +# include "dwc_modpow.h"
  6765. +# include "dwc_dh.h"
  6766. +# include "dwc_crypto.h"
  6767. +#endif
  6768. +
  6769. +#ifdef DWC_NOTIFYLIB
  6770. +# include "dwc_notifier.h"
  6771. +#endif
  6772. +
  6773. +/* OS-Level Implementations */
  6774. +
  6775. +/* This is the Linux kernel implementation of the DWC platform library. */
  6776. +#include <linux/moduleparam.h>
  6777. +#include <linux/ctype.h>
  6778. +#include <linux/crypto.h>
  6779. +#include <linux/delay.h>
  6780. +#include <linux/device.h>
  6781. +#include <linux/dma-mapping.h>
  6782. +#include <linux/cdev.h>
  6783. +#include <linux/errno.h>
  6784. +#include <linux/interrupt.h>
  6785. +#include <linux/jiffies.h>
  6786. +#include <linux/list.h>
  6787. +#include <linux/pci.h>
  6788. +#include <linux/random.h>
  6789. +#include <linux/scatterlist.h>
  6790. +#include <linux/slab.h>
  6791. +#include <linux/stat.h>
  6792. +#include <linux/string.h>
  6793. +#include <linux/timer.h>
  6794. +#include <linux/usb.h>
  6795. +
  6796. +#include <linux/version.h>
  6797. +
  6798. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
  6799. +# include <linux/usb/gadget.h>
  6800. +#else
  6801. +# include <linux/usb_gadget.h>
  6802. +#endif
  6803. +
  6804. +#include <asm/io.h>
  6805. +#include <asm/page.h>
  6806. +#include <asm/uaccess.h>
  6807. +#include <asm/unaligned.h>
  6808. +
  6809. +#include "dwc_os.h"
  6810. +#include "dwc_list.h"
  6811. +
  6812. +
  6813. +/* MISC */
  6814. +
  6815. +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
  6816. +{
  6817. + return memset(dest, byte, size);
  6818. +}
  6819. +
  6820. +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
  6821. +{
  6822. + return memcpy(dest, src, size);
  6823. +}
  6824. +
  6825. +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
  6826. +{
  6827. + return memmove(dest, src, size);
  6828. +}
  6829. +
  6830. +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
  6831. +{
  6832. + return memcmp(m1, m2, size);
  6833. +}
  6834. +
  6835. +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
  6836. +{
  6837. + return strncmp(s1, s2, size);
  6838. +}
  6839. +
  6840. +int DWC_STRCMP(void *s1, void *s2)
  6841. +{
  6842. + return strcmp(s1, s2);
  6843. +}
  6844. +
  6845. +int DWC_STRLEN(char const *str)
  6846. +{
  6847. + return strlen(str);
  6848. +}
  6849. +
  6850. +char *DWC_STRCPY(char *to, char const *from)
  6851. +{
  6852. + return strcpy(to, from);
  6853. +}
  6854. +
  6855. +char *DWC_STRDUP(char const *str)
  6856. +{
  6857. + int len = DWC_STRLEN(str) + 1;
  6858. + char *new = DWC_ALLOC_ATOMIC(len);
  6859. +
  6860. + if (!new) {
  6861. + return NULL;
  6862. + }
  6863. +
  6864. + DWC_MEMCPY(new, str, len);
  6865. + return new;
  6866. +}
  6867. +
  6868. +int DWC_ATOI(const char *str, int32_t *value)
  6869. +{
  6870. + char *end = NULL;
  6871. +
  6872. + *value = simple_strtol(str, &end, 0);
  6873. + if (*end == '\0') {
  6874. + return 0;
  6875. + }
  6876. +
  6877. + return -1;
  6878. +}
  6879. +
  6880. +int DWC_ATOUI(const char *str, uint32_t *value)
  6881. +{
  6882. + char *end = NULL;
  6883. +
  6884. + *value = simple_strtoul(str, &end, 0);
  6885. + if (*end == '\0') {
  6886. + return 0;
  6887. + }
  6888. +
  6889. + return -1;
  6890. +}
  6891. +
  6892. +
  6893. +#ifdef DWC_UTFLIB
  6894. +/* From usbstring.c */
  6895. +
  6896. +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
  6897. +{
  6898. + int count = 0;
  6899. + u8 c;
  6900. + u16 uchar;
  6901. +
  6902. + /* this insists on correct encodings, though not minimal ones.
  6903. + * BUT it currently rejects legit 4-byte UTF-8 code points,
  6904. + * which need surrogate pairs. (Unicode 3.1 can use them.)
  6905. + */
  6906. + while (len != 0 && (c = (u8) *s++) != 0) {
  6907. + if (unlikely(c & 0x80)) {
  6908. + // 2-byte sequence:
  6909. + // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
  6910. + if ((c & 0xe0) == 0xc0) {
  6911. + uchar = (c & 0x1f) << 6;
  6912. +
  6913. + c = (u8) *s++;
  6914. + if ((c & 0xc0) != 0xc0)
  6915. + goto fail;
  6916. + c &= 0x3f;
  6917. + uchar |= c;
  6918. +
  6919. + // 3-byte sequence (most CJKV characters):
  6920. + // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
  6921. + } else if ((c & 0xf0) == 0xe0) {
  6922. + uchar = (c & 0x0f) << 12;
  6923. +
  6924. + c = (u8) *s++;
  6925. + if ((c & 0xc0) != 0xc0)
  6926. + goto fail;
  6927. + c &= 0x3f;
  6928. + uchar |= c << 6;
  6929. +
  6930. + c = (u8) *s++;
  6931. + if ((c & 0xc0) != 0xc0)
  6932. + goto fail;
  6933. + c &= 0x3f;
  6934. + uchar |= c;
  6935. +
  6936. + /* no bogus surrogates */
  6937. + if (0xd800 <= uchar && uchar <= 0xdfff)
  6938. + goto fail;
  6939. +
  6940. + // 4-byte sequence (surrogate pairs, currently rare):
  6941. + // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
  6942. + // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
  6943. + // (uuuuu = wwww + 1)
  6944. + // FIXME accept the surrogate code points (only)
  6945. + } else
  6946. + goto fail;
  6947. + } else
  6948. + uchar = c;
  6949. + put_unaligned (cpu_to_le16 (uchar), cp++);
  6950. + count++;
  6951. + len--;
  6952. + }
  6953. + return count;
  6954. +fail:
  6955. + return -1;
  6956. +}
  6957. +#endif /* DWC_UTFLIB */
  6958. +
  6959. +
  6960. +/* dwc_debug.h */
  6961. +
  6962. +dwc_bool_t DWC_IN_IRQ(void)
  6963. +{
  6964. + return in_irq();
  6965. +}
  6966. +
  6967. +dwc_bool_t DWC_IN_BH(void)
  6968. +{
  6969. + return in_softirq();
  6970. +}
  6971. +
  6972. +void DWC_VPRINTF(char *format, va_list args)
  6973. +{
  6974. + vprintk(format, args);
  6975. +}
  6976. +
  6977. +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
  6978. +{
  6979. + return vsnprintf(str, size, format, args);
  6980. +}
  6981. +
  6982. +void DWC_PRINTF(char *format, ...)
  6983. +{
  6984. + va_list args;
  6985. +
  6986. + va_start(args, format);
  6987. + DWC_VPRINTF(format, args);
  6988. + va_end(args);
  6989. +}
  6990. +
  6991. +int DWC_SPRINTF(char *buffer, char *format, ...)
  6992. +{
  6993. + int retval;
  6994. + va_list args;
  6995. +
  6996. + va_start(args, format);
  6997. + retval = vsprintf(buffer, format, args);
  6998. + va_end(args);
  6999. + return retval;
  7000. +}
  7001. +
  7002. +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
  7003. +{
  7004. + int retval;
  7005. + va_list args;
  7006. +
  7007. + va_start(args, format);
  7008. + retval = vsnprintf(buffer, size, format, args);
  7009. + va_end(args);
  7010. + return retval;
  7011. +}
  7012. +
  7013. +void __DWC_WARN(char *format, ...)
  7014. +{
  7015. + va_list args;
  7016. +
  7017. + va_start(args, format);
  7018. + DWC_PRINTF(KERN_WARNING);
  7019. + DWC_VPRINTF(format, args);
  7020. + va_end(args);
  7021. +}
  7022. +
  7023. +void __DWC_ERROR(char *format, ...)
  7024. +{
  7025. + va_list args;
  7026. +
  7027. + va_start(args, format);
  7028. + DWC_PRINTF(KERN_ERR);
  7029. + DWC_VPRINTF(format, args);
  7030. + va_end(args);
  7031. +}
  7032. +
  7033. +void DWC_EXCEPTION(char *format, ...)
  7034. +{
  7035. + va_list args;
  7036. +
  7037. + va_start(args, format);
  7038. + DWC_PRINTF(KERN_ERR);
  7039. + DWC_VPRINTF(format, args);
  7040. + va_end(args);
  7041. + BUG_ON(1);
  7042. +}
  7043. +
  7044. +#ifdef DEBUG
  7045. +void __DWC_DEBUG(char *format, ...)
  7046. +{
  7047. + va_list args;
  7048. +
  7049. + va_start(args, format);
  7050. + DWC_PRINTF(KERN_DEBUG);
  7051. + DWC_VPRINTF(format, args);
  7052. + va_end(args);
  7053. +}
  7054. +#endif
  7055. +
  7056. +
  7057. +/* dwc_mem.h */
  7058. +
  7059. +#if 0
  7060. +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
  7061. + uint32_t align,
  7062. + uint32_t alloc)
  7063. +{
  7064. + struct dma_pool *pool = dma_pool_create("Pool", NULL,
  7065. + size, align, alloc);
  7066. + return (dwc_pool_t *)pool;
  7067. +}
  7068. +
  7069. +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
  7070. +{
  7071. + dma_pool_destroy((struct dma_pool *)pool);
  7072. +}
  7073. +
  7074. +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
  7075. +{
  7076. + return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
  7077. +}
  7078. +
  7079. +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
  7080. +{
  7081. + void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
  7082. + memset(..);
  7083. +}
  7084. +
  7085. +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
  7086. +{
  7087. + dma_pool_free(pool, vaddr, daddr);
  7088. +}
  7089. +#endif
  7090. +
  7091. +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
  7092. +{
  7093. +#ifdef xxCOSIM /* Only works for 32-bit cosim */
  7094. + void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL);
  7095. +#else
  7096. + void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL | GFP_DMA32);
  7097. +#endif
  7098. + if (!buf) {
  7099. + return NULL;
  7100. + }
  7101. +
  7102. + memset(buf, 0, (size_t)size);
  7103. + return buf;
  7104. +}
  7105. +
  7106. +void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
  7107. +{
  7108. + void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC);
  7109. + if (!buf) {
  7110. + return NULL;
  7111. + }
  7112. + memset(buf, 0, (size_t)size);
  7113. + return buf;
  7114. +}
  7115. +
  7116. +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
  7117. +{
  7118. + dma_free_coherent(dma_ctx, size, virt_addr, dma_addr);
  7119. +}
  7120. +
  7121. +void *__DWC_ALLOC(void *mem_ctx, uint32_t size)
  7122. +{
  7123. + return kzalloc(size, GFP_KERNEL);
  7124. +}
  7125. +
  7126. +void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)
  7127. +{
  7128. + return kzalloc(size, GFP_ATOMIC);
  7129. +}
  7130. +
  7131. +void __DWC_FREE(void *mem_ctx, void *addr)
  7132. +{
  7133. + kfree(addr);
  7134. +}
  7135. +
  7136. +
  7137. +#ifdef DWC_CRYPTOLIB
  7138. +/* dwc_crypto.h */
  7139. +
  7140. +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
  7141. +{
  7142. + get_random_bytes(buffer, length);
  7143. +}
  7144. +
  7145. +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
  7146. +{
  7147. + struct crypto_blkcipher *tfm;
  7148. + struct blkcipher_desc desc;
  7149. + struct scatterlist sgd;
  7150. + struct scatterlist sgs;
  7151. +
  7152. + tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
  7153. + if (tfm == NULL) {
  7154. + printk("failed to load transform for aes CBC\n");
  7155. + return -1;
  7156. + }
  7157. +
  7158. + crypto_blkcipher_setkey(tfm, key, keylen);
  7159. + crypto_blkcipher_set_iv(tfm, iv, 16);
  7160. +
  7161. + sg_init_one(&sgd, out, messagelen);
  7162. + sg_init_one(&sgs, message, messagelen);
  7163. +
  7164. + desc.tfm = tfm;
  7165. + desc.flags = 0;
  7166. +
  7167. + if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
  7168. + crypto_free_blkcipher(tfm);
  7169. + DWC_ERROR("AES CBC encryption failed");
  7170. + return -1;
  7171. + }
  7172. +
  7173. + crypto_free_blkcipher(tfm);
  7174. + return 0;
  7175. +}
  7176. +
  7177. +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
  7178. +{
  7179. + struct crypto_hash *tfm;
  7180. + struct hash_desc desc;
  7181. + struct scatterlist sg;
  7182. +
  7183. + tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
  7184. + if (IS_ERR(tfm)) {
  7185. + DWC_ERROR("Failed to load transform for sha256: %ld\n", PTR_ERR(tfm));
  7186. + return 0;
  7187. + }
  7188. + desc.tfm = tfm;
  7189. + desc.flags = 0;
  7190. +
  7191. + sg_init_one(&sg, message, len);
  7192. + crypto_hash_digest(&desc, &sg, len, out);
  7193. + crypto_free_hash(tfm);
  7194. +
  7195. + return 1;
  7196. +}
  7197. +
  7198. +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
  7199. + uint8_t *key, uint32_t keylen, uint8_t *out)
  7200. +{
  7201. + struct crypto_hash *tfm;
  7202. + struct hash_desc desc;
  7203. + struct scatterlist sg;
  7204. +
  7205. + tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
  7206. + if (IS_ERR(tfm)) {
  7207. + DWC_ERROR("Failed to load transform for hmac(sha256): %ld\n", PTR_ERR(tfm));
  7208. + return 0;
  7209. + }
  7210. + desc.tfm = tfm;
  7211. + desc.flags = 0;
  7212. +
  7213. + sg_init_one(&sg, message, messagelen);
  7214. + crypto_hash_setkey(tfm, key, keylen);
  7215. + crypto_hash_digest(&desc, &sg, messagelen, out);
  7216. + crypto_free_hash(tfm);
  7217. +
  7218. + return 1;
  7219. +}
  7220. +#endif /* DWC_CRYPTOLIB */
  7221. +
  7222. +
  7223. +/* Byte Ordering Conversions */
  7224. +
  7225. +uint32_t DWC_CPU_TO_LE32(uint32_t *p)
  7226. +{
  7227. +#ifdef __LITTLE_ENDIAN
  7228. + return *p;
  7229. +#else
  7230. + uint8_t *u_p = (uint8_t *)p;
  7231. +
  7232. + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
  7233. +#endif
  7234. +}
  7235. +
  7236. +uint32_t DWC_CPU_TO_BE32(uint32_t *p)
  7237. +{
  7238. +#ifdef __BIG_ENDIAN
  7239. + return *p;
  7240. +#else
  7241. + uint8_t *u_p = (uint8_t *)p;
  7242. +
  7243. + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
  7244. +#endif
  7245. +}
  7246. +
  7247. +uint32_t DWC_LE32_TO_CPU(uint32_t *p)
  7248. +{
  7249. +#ifdef __LITTLE_ENDIAN
  7250. + return *p;
  7251. +#else
  7252. + uint8_t *u_p = (uint8_t *)p;
  7253. +
  7254. + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
  7255. +#endif
  7256. +}
  7257. +
  7258. +uint32_t DWC_BE32_TO_CPU(uint32_t *p)
  7259. +{
  7260. +#ifdef __BIG_ENDIAN
  7261. + return *p;
  7262. +#else
  7263. + uint8_t *u_p = (uint8_t *)p;
  7264. +
  7265. + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
  7266. +#endif
  7267. +}
  7268. +
  7269. +uint16_t DWC_CPU_TO_LE16(uint16_t *p)
  7270. +{
  7271. +#ifdef __LITTLE_ENDIAN
  7272. + return *p;
  7273. +#else
  7274. + uint8_t *u_p = (uint8_t *)p;
  7275. + return (u_p[1] | (u_p[0] << 8));
  7276. +#endif
  7277. +}
  7278. +
  7279. +uint16_t DWC_CPU_TO_BE16(uint16_t *p)
  7280. +{
  7281. +#ifdef __BIG_ENDIAN
  7282. + return *p;
  7283. +#else
  7284. + uint8_t *u_p = (uint8_t *)p;
  7285. + return (u_p[1] | (u_p[0] << 8));
  7286. +#endif
  7287. +}
  7288. +
  7289. +uint16_t DWC_LE16_TO_CPU(uint16_t *p)
  7290. +{
  7291. +#ifdef __LITTLE_ENDIAN
  7292. + return *p;
  7293. +#else
  7294. + uint8_t *u_p = (uint8_t *)p;
  7295. + return (u_p[1] | (u_p[0] << 8));
  7296. +#endif
  7297. +}
  7298. +
  7299. +uint16_t DWC_BE16_TO_CPU(uint16_t *p)
  7300. +{
  7301. +#ifdef __BIG_ENDIAN
  7302. + return *p;
  7303. +#else
  7304. + uint8_t *u_p = (uint8_t *)p;
  7305. + return (u_p[1] | (u_p[0] << 8));
  7306. +#endif
  7307. +}
  7308. +
  7309. +
  7310. +/* Registers */
  7311. +
  7312. +uint32_t DWC_READ_REG32(uint32_t volatile *reg)
  7313. +{
  7314. + return readl(reg);
  7315. +}
  7316. +
  7317. +#if 0
  7318. +uint64_t DWC_READ_REG64(uint64_t volatile *reg)
  7319. +{
  7320. +}
  7321. +#endif
  7322. +
  7323. +void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value)
  7324. +{
  7325. + writel(value, reg);
  7326. +}
  7327. +
  7328. +#if 0
  7329. +void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value)
  7330. +{
  7331. +}
  7332. +#endif
  7333. +
  7334. +void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)
  7335. +{
  7336. + writel((readl(reg) & ~clear_mask) | set_mask, reg);
  7337. +}
  7338. +
  7339. +#if 0
  7340. +void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask)
  7341. +{
  7342. +}
  7343. +#endif
  7344. +
  7345. +
  7346. +/* Locking */
  7347. +
  7348. +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
  7349. +{
  7350. + spinlock_t *sl = (spinlock_t *)1;
  7351. +
  7352. +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
  7353. + sl = DWC_ALLOC(sizeof(*sl));
  7354. + if (!sl) {
  7355. + DWC_ERROR("Cannot allocate memory for spinlock\n");
  7356. + return NULL;
  7357. + }
  7358. +
  7359. + spin_lock_init(sl);
  7360. +#endif
  7361. + return (dwc_spinlock_t *)sl;
  7362. +}
  7363. +
  7364. +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
  7365. +{
  7366. +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
  7367. + DWC_FREE(lock);
  7368. +#endif
  7369. +}
  7370. +
  7371. +void DWC_SPINLOCK(dwc_spinlock_t *lock)
  7372. +{
  7373. +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
  7374. + spin_lock((spinlock_t *)lock);
  7375. +#endif
  7376. +}
  7377. +
  7378. +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
  7379. +{
  7380. +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
  7381. + spin_unlock((spinlock_t *)lock);
  7382. +#endif
  7383. +}
  7384. +
  7385. +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)
  7386. +{
  7387. + dwc_irqflags_t f;
  7388. +
  7389. +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
  7390. + spin_lock_irqsave((spinlock_t *)lock, f);
  7391. +#else
  7392. + local_irq_save(f);
  7393. +#endif
  7394. + *flags = f;
  7395. +}
  7396. +
  7397. +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)
  7398. +{
  7399. +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP)
  7400. + spin_unlock_irqrestore((spinlock_t *)lock, flags);
  7401. +#else
  7402. + local_irq_restore(flags);
  7403. +#endif
  7404. +}
  7405. +
  7406. +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
  7407. +{
  7408. + struct mutex *m;
  7409. + dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex));
  7410. +
  7411. + if (!mutex) {
  7412. + DWC_ERROR("Cannot allocate memory for mutex\n");
  7413. + return NULL;
  7414. + }
  7415. +
  7416. + m = (struct mutex *)mutex;
  7417. + mutex_init(m);
  7418. + return mutex;
  7419. +}
  7420. +
  7421. +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
  7422. +#else
  7423. +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
  7424. +{
  7425. + mutex_destroy((struct mutex *)mutex);
  7426. + DWC_FREE(mutex);
  7427. +}
  7428. +#endif
  7429. +
  7430. +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
  7431. +{
  7432. + struct mutex *m = (struct mutex *)mutex;
  7433. + mutex_lock(m);
  7434. +}
  7435. +
  7436. +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
  7437. +{
  7438. + struct mutex *m = (struct mutex *)mutex;
  7439. + return mutex_trylock(m);
  7440. +}
  7441. +
  7442. +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
  7443. +{
  7444. + struct mutex *m = (struct mutex *)mutex;
  7445. + mutex_unlock(m);
  7446. +}
  7447. +
  7448. +
  7449. +/* Timing */
  7450. +
  7451. +void DWC_UDELAY(uint32_t usecs)
  7452. +{
  7453. + udelay(usecs);
  7454. +}
  7455. +
  7456. +void DWC_MDELAY(uint32_t msecs)
  7457. +{
  7458. + mdelay(msecs);
  7459. +}
  7460. +
  7461. +void DWC_MSLEEP(uint32_t msecs)
  7462. +{
  7463. + msleep(msecs);
  7464. +}
  7465. +
  7466. +uint32_t DWC_TIME(void)
  7467. +{
  7468. + return jiffies_to_msecs(jiffies);
  7469. +}
  7470. +
  7471. +
  7472. +/* Timers */
  7473. +
  7474. +struct dwc_timer {
  7475. + struct timer_list *t;
  7476. + char *name;
  7477. + dwc_timer_callback_t cb;
  7478. + void *data;
  7479. + uint8_t scheduled;
  7480. + dwc_spinlock_t *lock;
  7481. +};
  7482. +
  7483. +static void timer_callback(unsigned long data)
  7484. +{
  7485. + dwc_timer_t *timer = (dwc_timer_t *)data;
  7486. + dwc_irqflags_t flags;
  7487. +
  7488. + DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);
  7489. + timer->scheduled = 0;
  7490. + DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);
  7491. + DWC_DEBUGC("Timer %s callback", timer->name);
  7492. + timer->cb(timer->data);
  7493. +}
  7494. +
  7495. +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
  7496. +{
  7497. + dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
  7498. +
  7499. + if (!t) {
  7500. + DWC_ERROR("Cannot allocate memory for timer");
  7501. + return NULL;
  7502. + }
  7503. +
  7504. + t->t = DWC_ALLOC(sizeof(*t->t));
  7505. + if (!t->t) {
  7506. + DWC_ERROR("Cannot allocate memory for timer->t");
  7507. + goto no_timer;
  7508. + }
  7509. +
  7510. + t->name = DWC_STRDUP(name);
  7511. + if (!t->name) {
  7512. + DWC_ERROR("Cannot allocate memory for timer->name");
  7513. + goto no_name;
  7514. + }
  7515. +
  7516. +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_SPINLOCK))
  7517. + DWC_SPINLOCK_ALLOC_LINUX_DEBUG(t->lock);
  7518. +#else
  7519. + t->lock = DWC_SPINLOCK_ALLOC();
  7520. +#endif
  7521. + if (!t->lock) {
  7522. + DWC_ERROR("Cannot allocate memory for lock");
  7523. + goto no_lock;
  7524. + }
  7525. +
  7526. + t->scheduled = 0;
  7527. + t->t->base = &boot_tvec_bases;
  7528. + t->t->expires = jiffies;
  7529. + setup_timer(t->t, timer_callback, (unsigned long)t);
  7530. +
  7531. + t->cb = cb;
  7532. + t->data = data;
  7533. +
  7534. + return t;
  7535. +
  7536. + no_lock:
  7537. + DWC_FREE(t->name);
  7538. + no_name:
  7539. + DWC_FREE(t->t);
  7540. + no_timer:
  7541. + DWC_FREE(t);
  7542. + return NULL;
  7543. +}
  7544. +
  7545. +void DWC_TIMER_FREE(dwc_timer_t *timer)
  7546. +{
  7547. + dwc_irqflags_t flags;
  7548. +
  7549. + DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);
  7550. +
  7551. + if (timer->scheduled) {
  7552. + del_timer(timer->t);
  7553. + timer->scheduled = 0;
  7554. + }
  7555. +
  7556. + DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);
  7557. + DWC_SPINLOCK_FREE(timer->lock);
  7558. + DWC_FREE(timer->t);
  7559. + DWC_FREE(timer->name);
  7560. + DWC_FREE(timer);
  7561. +}
  7562. +
  7563. +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
  7564. +{
  7565. + dwc_irqflags_t flags;
  7566. +
  7567. + DWC_SPINLOCK_IRQSAVE(timer->lock, &flags);
  7568. +
  7569. + if (!timer->scheduled) {
  7570. + timer->scheduled = 1;
  7571. + DWC_DEBUGC("Scheduling timer %s to expire in +%d msec", timer->name, time);
  7572. + timer->t->expires = jiffies + msecs_to_jiffies(time);
  7573. + add_timer(timer->t);
  7574. + } else {
  7575. + DWC_DEBUGC("Modifying timer %s to expire in +%d msec", timer->name, time);
  7576. + mod_timer(timer->t, jiffies + msecs_to_jiffies(time));
  7577. + }
  7578. +
  7579. + DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags);
  7580. +}
  7581. +
  7582. +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
  7583. +{
  7584. + del_timer(timer->t);
  7585. +}
  7586. +
  7587. +
  7588. +/* Wait Queues */
  7589. +
  7590. +struct dwc_waitq {
  7591. + wait_queue_head_t queue;
  7592. + int abort;
  7593. +};
  7594. +
  7595. +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
  7596. +{
  7597. + dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
  7598. +
  7599. + if (!wq) {
  7600. + DWC_ERROR("Cannot allocate memory for waitqueue\n");
  7601. + return NULL;
  7602. + }
  7603. +
  7604. + init_waitqueue_head(&wq->queue);
  7605. + wq->abort = 0;
  7606. + return wq;
  7607. +}
  7608. +
  7609. +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
  7610. +{
  7611. + DWC_FREE(wq);
  7612. +}
  7613. +
  7614. +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)
  7615. +{
  7616. + int result = wait_event_interruptible(wq->queue,
  7617. + cond(data) || wq->abort);
  7618. + if (result == -ERESTARTSYS) {
  7619. + wq->abort = 0;
  7620. + return -DWC_E_RESTART;
  7621. + }
  7622. +
  7623. + if (wq->abort == 1) {
  7624. + wq->abort = 0;
  7625. + return -DWC_E_ABORT;
  7626. + }
  7627. +
  7628. + wq->abort = 0;
  7629. +
  7630. + if (result == 0) {
  7631. + return 0;
  7632. + }
  7633. +
  7634. + return -DWC_E_UNKNOWN;
  7635. +}
  7636. +
  7637. +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
  7638. + void *data, int32_t msecs)
  7639. +{
  7640. + int32_t tmsecs;
  7641. + int result = wait_event_interruptible_timeout(wq->queue,
  7642. + cond(data) || wq->abort,
  7643. + msecs_to_jiffies(msecs));
  7644. + if (result == -ERESTARTSYS) {
  7645. + wq->abort = 0;
  7646. + return -DWC_E_RESTART;
  7647. + }
  7648. +
  7649. + if (wq->abort == 1) {
  7650. + wq->abort = 0;
  7651. + return -DWC_E_ABORT;
  7652. + }
  7653. +
  7654. + wq->abort = 0;
  7655. +
  7656. + if (result > 0) {
  7657. + tmsecs = jiffies_to_msecs(result);
  7658. + if (!tmsecs) {
  7659. + return 1;
  7660. + }
  7661. +
  7662. + return tmsecs;
  7663. + }
  7664. +
  7665. + if (result == 0) {
  7666. + return -DWC_E_TIMEOUT;
  7667. + }
  7668. +
  7669. + return -DWC_E_UNKNOWN;
  7670. +}
  7671. +
  7672. +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
  7673. +{
  7674. + wq->abort = 0;
  7675. + wake_up_interruptible(&wq->queue);
  7676. +}
  7677. +
  7678. +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
  7679. +{
  7680. + wq->abort = 1;
  7681. + wake_up_interruptible(&wq->queue);
  7682. +}
  7683. +
  7684. +
  7685. +/* Threading */
  7686. +
  7687. +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)
  7688. +{
  7689. + struct task_struct *thread = kthread_run(func, data, name);
  7690. +
  7691. + if (thread == ERR_PTR(-ENOMEM)) {
  7692. + return NULL;
  7693. + }
  7694. +
  7695. + return (dwc_thread_t *)thread;
  7696. +}
  7697. +
  7698. +int DWC_THREAD_STOP(dwc_thread_t *thread)
  7699. +{
  7700. + return kthread_stop((struct task_struct *)thread);
  7701. +}
  7702. +
  7703. +dwc_bool_t DWC_THREAD_SHOULD_STOP(void)
  7704. +{
  7705. + return kthread_should_stop();
  7706. +}
  7707. +
  7708. +
  7709. +/* tasklets
  7710. + - run in interrupt context (cannot sleep)
  7711. + - each tasklet runs on a single CPU
  7712. + - different tasklets can be running simultaneously on different CPUs
  7713. + */
  7714. +struct dwc_tasklet {
  7715. + struct tasklet_struct t;
  7716. + dwc_tasklet_callback_t cb;
  7717. + void *data;
  7718. +};
  7719. +
  7720. +static void tasklet_callback(unsigned long data)
  7721. +{
  7722. + dwc_tasklet_t *t = (dwc_tasklet_t *)data;
  7723. + t->cb(t->data);
  7724. +}
  7725. +
  7726. +dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)
  7727. +{
  7728. + dwc_tasklet_t *t = DWC_ALLOC(sizeof(*t));
  7729. +
  7730. + if (t) {
  7731. + t->cb = cb;
  7732. + t->data = data;
  7733. + tasklet_init(&t->t, tasklet_callback, (unsigned long)t);
  7734. + } else {
  7735. + DWC_ERROR("Cannot allocate memory for tasklet\n");
  7736. + }
  7737. +
  7738. + return t;
  7739. +}
  7740. +
  7741. +void DWC_TASK_FREE(dwc_tasklet_t *task)
  7742. +{
  7743. + DWC_FREE(task);
  7744. +}
  7745. +
  7746. +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
  7747. +{
  7748. + tasklet_schedule(&task->t);
  7749. +}
  7750. +
  7751. +
  7752. +/* workqueues
  7753. + - run in process context (can sleep)
  7754. + */
  7755. +typedef struct work_container {
  7756. + dwc_work_callback_t cb;
  7757. + void *data;
  7758. + dwc_workq_t *wq;
  7759. + char *name;
  7760. +
  7761. +#ifdef DEBUG
  7762. + DWC_CIRCLEQ_ENTRY(work_container) entry;
  7763. +#endif
  7764. + struct delayed_work work;
  7765. +} work_container_t;
  7766. +
  7767. +#ifdef DEBUG
  7768. +DWC_CIRCLEQ_HEAD(work_container_queue, work_container);
  7769. +#endif
  7770. +
  7771. +struct dwc_workq {
  7772. + struct workqueue_struct *wq;
  7773. + dwc_spinlock_t *lock;
  7774. + dwc_waitq_t *waitq;
  7775. + int pending;
  7776. +
  7777. +#ifdef DEBUG
  7778. + struct work_container_queue entries;
  7779. +#endif
  7780. +};
  7781. +
  7782. +static void do_work(struct work_struct *work)
  7783. +{
  7784. + dwc_irqflags_t flags;
  7785. + struct delayed_work *dw = container_of(work, struct delayed_work, work);
  7786. + work_container_t *container = container_of(dw, struct work_container, work);
  7787. + dwc_workq_t *wq = container->wq;
  7788. +
  7789. + container->cb(container->data);
  7790. +
  7791. +#ifdef DEBUG
  7792. + DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry);
  7793. +#endif
  7794. + DWC_DEBUGC("Work done: %s, container=%p", container->name, container);
  7795. + if (container->name) {
  7796. + DWC_FREE(container->name);
  7797. + }
  7798. + DWC_FREE(container);
  7799. +
  7800. + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
  7801. + wq->pending--;
  7802. + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
  7803. + DWC_WAITQ_TRIGGER(wq->waitq);
  7804. +}
  7805. +
  7806. +static int work_done(void *data)
  7807. +{
  7808. + dwc_workq_t *workq = (dwc_workq_t *)data;
  7809. + return workq->pending == 0;
  7810. +}
  7811. +
  7812. +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
  7813. +{
  7814. + return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
  7815. +}
  7816. +
  7817. +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
  7818. +{
  7819. + dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
  7820. +
  7821. + if (!wq) {
  7822. + return NULL;
  7823. + }
  7824. +
  7825. + wq->wq = create_singlethread_workqueue(name);
  7826. + if (!wq->wq) {
  7827. + goto no_wq;
  7828. + }
  7829. +
  7830. + wq->pending = 0;
  7831. +
  7832. +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_SPINLOCK))
  7833. + DWC_SPINLOCK_ALLOC_LINUX_DEBUG(wq->lock);
  7834. +#else
  7835. + wq->lock = DWC_SPINLOCK_ALLOC();
  7836. +#endif
  7837. + if (!wq->lock) {
  7838. + goto no_lock;
  7839. + }
  7840. +
  7841. + wq->waitq = DWC_WAITQ_ALLOC();
  7842. + if (!wq->waitq) {
  7843. + goto no_waitq;
  7844. + }
  7845. +
  7846. +#ifdef DEBUG
  7847. + DWC_CIRCLEQ_INIT(&wq->entries);
  7848. +#endif
  7849. + return wq;
  7850. +
  7851. + no_waitq:
  7852. + DWC_SPINLOCK_FREE(wq->lock);
  7853. + no_lock:
  7854. + destroy_workqueue(wq->wq);
  7855. + no_wq:
  7856. + DWC_FREE(wq);
  7857. +
  7858. + return NULL;
  7859. +}
  7860. +
  7861. +void DWC_WORKQ_FREE(dwc_workq_t *wq)
  7862. +{
  7863. +#ifdef DEBUG
  7864. + if (wq->pending != 0) {
  7865. + struct work_container *wc;
  7866. + DWC_ERROR("Destroying work queue with pending work");
  7867. + DWC_CIRCLEQ_FOREACH(wc, &wq->entries, entry) {
  7868. + DWC_ERROR("Work %s still pending", wc->name);
  7869. + }
  7870. + }
  7871. +#endif
  7872. + destroy_workqueue(wq->wq);
  7873. + DWC_SPINLOCK_FREE(wq->lock);
  7874. + DWC_WAITQ_FREE(wq->waitq);
  7875. + DWC_FREE(wq);
  7876. +}
  7877. +
  7878. +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,
  7879. + char *format, ...)
  7880. +{
  7881. + dwc_irqflags_t flags;
  7882. + work_container_t *container;
  7883. + static char name[128];
  7884. + va_list args;
  7885. +
  7886. + va_start(args, format);
  7887. + DWC_VSNPRINTF(name, 128, format, args);
  7888. + va_end(args);
  7889. +
  7890. + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
  7891. + wq->pending++;
  7892. + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
  7893. + DWC_WAITQ_TRIGGER(wq->waitq);
  7894. +
  7895. + container = DWC_ALLOC_ATOMIC(sizeof(*container));
  7896. + if (!container) {
  7897. + DWC_ERROR("Cannot allocate memory for container\n");
  7898. + return;
  7899. + }
  7900. +
  7901. + container->name = DWC_STRDUP(name);
  7902. + if (!container->name) {
  7903. + DWC_ERROR("Cannot allocate memory for container->name\n");
  7904. + DWC_FREE(container);
  7905. + return;
  7906. + }
  7907. +
  7908. + container->cb = cb;
  7909. + container->data = data;
  7910. + container->wq = wq;
  7911. + DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container);
  7912. + INIT_WORK(&container->work.work, do_work);
  7913. +
  7914. +#ifdef DEBUG
  7915. + DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
  7916. +#endif
  7917. + queue_work(wq->wq, &container->work.work);
  7918. +}
  7919. +
  7920. +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,
  7921. + void *data, uint32_t time, char *format, ...)
  7922. +{
  7923. + dwc_irqflags_t flags;
  7924. + work_container_t *container;
  7925. + static char name[128];
  7926. + va_list args;
  7927. +
  7928. + va_start(args, format);
  7929. + DWC_VSNPRINTF(name, 128, format, args);
  7930. + va_end(args);
  7931. +
  7932. + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
  7933. + wq->pending++;
  7934. + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
  7935. + DWC_WAITQ_TRIGGER(wq->waitq);
  7936. +
  7937. + container = DWC_ALLOC_ATOMIC(sizeof(*container));
  7938. + if (!container) {
  7939. + DWC_ERROR("Cannot allocate memory for container\n");
  7940. + return;
  7941. + }
  7942. +
  7943. + container->name = DWC_STRDUP(name);
  7944. + if (!container->name) {
  7945. + DWC_ERROR("Cannot allocate memory for container->name\n");
  7946. + DWC_FREE(container);
  7947. + return;
  7948. + }
  7949. +
  7950. + container->cb = cb;
  7951. + container->data = data;
  7952. + container->wq = wq;
  7953. + DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container);
  7954. + INIT_DELAYED_WORK(&container->work, do_work);
  7955. +
  7956. +#ifdef DEBUG
  7957. + DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry);
  7958. +#endif
  7959. + queue_delayed_work(wq->wq, &container->work, msecs_to_jiffies(time));
  7960. +}
  7961. +
  7962. +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
  7963. +{
  7964. + return wq->pending;
  7965. +}
  7966. +
  7967. +
  7968. +#ifdef DWC_LIBMODULE
  7969. +
  7970. +#ifdef DWC_CCLIB
  7971. +/* CC */
  7972. +EXPORT_SYMBOL(dwc_cc_if_alloc);
  7973. +EXPORT_SYMBOL(dwc_cc_if_free);
  7974. +EXPORT_SYMBOL(dwc_cc_clear);
  7975. +EXPORT_SYMBOL(dwc_cc_add);
  7976. +EXPORT_SYMBOL(dwc_cc_remove);
  7977. +EXPORT_SYMBOL(dwc_cc_change);
  7978. +EXPORT_SYMBOL(dwc_cc_data_for_save);
  7979. +EXPORT_SYMBOL(dwc_cc_restore_from_data);
  7980. +EXPORT_SYMBOL(dwc_cc_match_chid);
  7981. +EXPORT_SYMBOL(dwc_cc_match_cdid);
  7982. +EXPORT_SYMBOL(dwc_cc_ck);
  7983. +EXPORT_SYMBOL(dwc_cc_chid);
  7984. +EXPORT_SYMBOL(dwc_cc_cdid);
  7985. +EXPORT_SYMBOL(dwc_cc_name);
  7986. +#endif /* DWC_CCLIB */
  7987. +
  7988. +#ifdef DWC_CRYPTOLIB
  7989. +# ifndef CONFIG_MACH_IPMATE
  7990. +/* Modpow */
  7991. +EXPORT_SYMBOL(dwc_modpow);
  7992. +
  7993. +/* DH */
  7994. +EXPORT_SYMBOL(dwc_dh_modpow);
  7995. +EXPORT_SYMBOL(dwc_dh_derive_keys);
  7996. +EXPORT_SYMBOL(dwc_dh_pk);
  7997. +# endif /* CONFIG_MACH_IPMATE */
  7998. +
  7999. +/* Crypto */
  8000. +EXPORT_SYMBOL(dwc_wusb_aes_encrypt);
  8001. +EXPORT_SYMBOL(dwc_wusb_cmf);
  8002. +EXPORT_SYMBOL(dwc_wusb_prf);
  8003. +EXPORT_SYMBOL(dwc_wusb_fill_ccm_nonce);
  8004. +EXPORT_SYMBOL(dwc_wusb_gen_nonce);
  8005. +EXPORT_SYMBOL(dwc_wusb_gen_key);
  8006. +EXPORT_SYMBOL(dwc_wusb_gen_mic);
  8007. +#endif /* DWC_CRYPTOLIB */
  8008. +
  8009. +/* Notification */
  8010. +#ifdef DWC_NOTIFYLIB
  8011. +EXPORT_SYMBOL(dwc_alloc_notification_manager);
  8012. +EXPORT_SYMBOL(dwc_free_notification_manager);
  8013. +EXPORT_SYMBOL(dwc_register_notifier);
  8014. +EXPORT_SYMBOL(dwc_unregister_notifier);
  8015. +EXPORT_SYMBOL(dwc_add_observer);
  8016. +EXPORT_SYMBOL(dwc_remove_observer);
  8017. +EXPORT_SYMBOL(dwc_notify);
  8018. +#endif
  8019. +
  8020. +/* Memory Debugging Routines */
  8021. +#ifdef DWC_DEBUG_MEMORY
  8022. +EXPORT_SYMBOL(dwc_alloc_debug);
  8023. +EXPORT_SYMBOL(dwc_alloc_atomic_debug);
  8024. +EXPORT_SYMBOL(dwc_free_debug);
  8025. +EXPORT_SYMBOL(dwc_dma_alloc_debug);
  8026. +EXPORT_SYMBOL(dwc_dma_free_debug);
  8027. +#endif
  8028. +
  8029. +EXPORT_SYMBOL(DWC_MEMSET);
  8030. +EXPORT_SYMBOL(DWC_MEMCPY);
  8031. +EXPORT_SYMBOL(DWC_MEMMOVE);
  8032. +EXPORT_SYMBOL(DWC_MEMCMP);
  8033. +EXPORT_SYMBOL(DWC_STRNCMP);
  8034. +EXPORT_SYMBOL(DWC_STRCMP);
  8035. +EXPORT_SYMBOL(DWC_STRLEN);
  8036. +EXPORT_SYMBOL(DWC_STRCPY);
  8037. +EXPORT_SYMBOL(DWC_STRDUP);
  8038. +EXPORT_SYMBOL(DWC_ATOI);
  8039. +EXPORT_SYMBOL(DWC_ATOUI);
  8040. +
  8041. +#ifdef DWC_UTFLIB
  8042. +EXPORT_SYMBOL(DWC_UTF8_TO_UTF16LE);
  8043. +#endif /* DWC_UTFLIB */
  8044. +
  8045. +EXPORT_SYMBOL(DWC_IN_IRQ);
  8046. +EXPORT_SYMBOL(DWC_IN_BH);
  8047. +EXPORT_SYMBOL(DWC_VPRINTF);
  8048. +EXPORT_SYMBOL(DWC_VSNPRINTF);
  8049. +EXPORT_SYMBOL(DWC_PRINTF);
  8050. +EXPORT_SYMBOL(DWC_SPRINTF);
  8051. +EXPORT_SYMBOL(DWC_SNPRINTF);
  8052. +EXPORT_SYMBOL(__DWC_WARN);
  8053. +EXPORT_SYMBOL(__DWC_ERROR);
  8054. +EXPORT_SYMBOL(DWC_EXCEPTION);
  8055. +
  8056. +#ifdef DEBUG
  8057. +EXPORT_SYMBOL(__DWC_DEBUG);
  8058. +#endif
  8059. +
  8060. +EXPORT_SYMBOL(__DWC_DMA_ALLOC);
  8061. +EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC);
  8062. +EXPORT_SYMBOL(__DWC_DMA_FREE);
  8063. +EXPORT_SYMBOL(__DWC_ALLOC);
  8064. +EXPORT_SYMBOL(__DWC_ALLOC_ATOMIC);
  8065. +EXPORT_SYMBOL(__DWC_FREE);
  8066. +
  8067. +#ifdef DWC_CRYPTOLIB
  8068. +EXPORT_SYMBOL(DWC_RANDOM_BYTES);
  8069. +EXPORT_SYMBOL(DWC_AES_CBC);
  8070. +EXPORT_SYMBOL(DWC_SHA256);
  8071. +EXPORT_SYMBOL(DWC_HMAC_SHA256);
  8072. +#endif
  8073. +
  8074. +EXPORT_SYMBOL(DWC_CPU_TO_LE32);
  8075. +EXPORT_SYMBOL(DWC_CPU_TO_BE32);
  8076. +EXPORT_SYMBOL(DWC_LE32_TO_CPU);
  8077. +EXPORT_SYMBOL(DWC_BE32_TO_CPU);
  8078. +EXPORT_SYMBOL(DWC_CPU_TO_LE16);
  8079. +EXPORT_SYMBOL(DWC_CPU_TO_BE16);
  8080. +EXPORT_SYMBOL(DWC_LE16_TO_CPU);
  8081. +EXPORT_SYMBOL(DWC_BE16_TO_CPU);
  8082. +EXPORT_SYMBOL(DWC_READ_REG32);
  8083. +EXPORT_SYMBOL(DWC_WRITE_REG32);
  8084. +EXPORT_SYMBOL(DWC_MODIFY_REG32);
  8085. +
  8086. +#if 0
  8087. +EXPORT_SYMBOL(DWC_READ_REG64);
  8088. +EXPORT_SYMBOL(DWC_WRITE_REG64);
  8089. +EXPORT_SYMBOL(DWC_MODIFY_REG64);
  8090. +#endif
  8091. +
  8092. +EXPORT_SYMBOL(DWC_SPINLOCK_ALLOC);
  8093. +EXPORT_SYMBOL(DWC_SPINLOCK_FREE);
  8094. +EXPORT_SYMBOL(DWC_SPINLOCK);
  8095. +EXPORT_SYMBOL(DWC_SPINUNLOCK);
  8096. +EXPORT_SYMBOL(DWC_SPINLOCK_IRQSAVE);
  8097. +EXPORT_SYMBOL(DWC_SPINUNLOCK_IRQRESTORE);
  8098. +EXPORT_SYMBOL(DWC_MUTEX_ALLOC);
  8099. +
  8100. +#if (!defined(DWC_LINUX) || !defined(CONFIG_DEBUG_MUTEXES))
  8101. +EXPORT_SYMBOL(DWC_MUTEX_FREE);
  8102. +#endif
  8103. +
  8104. +EXPORT_SYMBOL(DWC_MUTEX_LOCK);
  8105. +EXPORT_SYMBOL(DWC_MUTEX_TRYLOCK);
  8106. +EXPORT_SYMBOL(DWC_MUTEX_UNLOCK);
  8107. +EXPORT_SYMBOL(DWC_UDELAY);
  8108. +EXPORT_SYMBOL(DWC_MDELAY);
  8109. +EXPORT_SYMBOL(DWC_MSLEEP);
  8110. +EXPORT_SYMBOL(DWC_TIME);
  8111. +EXPORT_SYMBOL(DWC_TIMER_ALLOC);
  8112. +EXPORT_SYMBOL(DWC_TIMER_FREE);
  8113. +EXPORT_SYMBOL(DWC_TIMER_SCHEDULE);
  8114. +EXPORT_SYMBOL(DWC_TIMER_CANCEL);
  8115. +EXPORT_SYMBOL(DWC_WAITQ_ALLOC);
  8116. +EXPORT_SYMBOL(DWC_WAITQ_FREE);
  8117. +EXPORT_SYMBOL(DWC_WAITQ_WAIT);
  8118. +EXPORT_SYMBOL(DWC_WAITQ_WAIT_TIMEOUT);
  8119. +EXPORT_SYMBOL(DWC_WAITQ_TRIGGER);
  8120. +EXPORT_SYMBOL(DWC_WAITQ_ABORT);
  8121. +EXPORT_SYMBOL(DWC_THREAD_RUN);
  8122. +EXPORT_SYMBOL(DWC_THREAD_STOP);
  8123. +EXPORT_SYMBOL(DWC_THREAD_SHOULD_STOP);
  8124. +EXPORT_SYMBOL(DWC_TASK_ALLOC);
  8125. +EXPORT_SYMBOL(DWC_TASK_FREE);
  8126. +EXPORT_SYMBOL(DWC_TASK_SCHEDULE);
  8127. +EXPORT_SYMBOL(DWC_WORKQ_WAIT_WORK_DONE);
  8128. +EXPORT_SYMBOL(DWC_WORKQ_ALLOC);
  8129. +EXPORT_SYMBOL(DWC_WORKQ_FREE);
  8130. +EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE);
  8131. +EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE_DELAYED);
  8132. +EXPORT_SYMBOL(DWC_WORKQ_PENDING);
  8133. +
  8134. +static int dwc_common_port_init_module(void)
  8135. +{
  8136. + int result = 0;
  8137. +
  8138. + printk(KERN_DEBUG "Module dwc_common_port init\n" );
  8139. +
  8140. +#ifdef DWC_DEBUG_MEMORY
  8141. + result = dwc_memory_debug_start(NULL);
  8142. + if (result) {
  8143. + printk(KERN_ERR
  8144. + "dwc_memory_debug_start() failed with error %d\n",
  8145. + result);
  8146. + return result;
  8147. + }
  8148. +#endif
  8149. +
  8150. +#ifdef DWC_NOTIFYLIB
  8151. + result = dwc_alloc_notification_manager(NULL, NULL);
  8152. + if (result) {
  8153. + printk(KERN_ERR
  8154. + "dwc_alloc_notification_manager() failed with error %d\n",
  8155. + result);
  8156. + return result;
  8157. + }
  8158. +#endif
  8159. + return result;
  8160. +}
  8161. +
  8162. +static void dwc_common_port_exit_module(void)
  8163. +{
  8164. + printk(KERN_DEBUG "Module dwc_common_port exit\n" );
  8165. +
  8166. +#ifdef DWC_NOTIFYLIB
  8167. + dwc_free_notification_manager();
  8168. +#endif
  8169. +
  8170. +#ifdef DWC_DEBUG_MEMORY
  8171. + dwc_memory_debug_stop();
  8172. +#endif
  8173. +}
  8174. +
  8175. +module_init(dwc_common_port_init_module);
  8176. +module_exit(dwc_common_port_exit_module);
  8177. +
  8178. +MODULE_DESCRIPTION("DWC Common Library - Portable version");
  8179. +MODULE_AUTHOR("Synopsys Inc.");
  8180. +MODULE_LICENSE ("GPL");
  8181. +
  8182. +#endif /* DWC_LIBMODULE */
  8183. --- /dev/null
  8184. +++ b/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c
  8185. @@ -0,0 +1,1275 @@
  8186. +#include "dwc_os.h"
  8187. +#include "dwc_list.h"
  8188. +
  8189. +#ifdef DWC_CCLIB
  8190. +# include "dwc_cc.h"
  8191. +#endif
  8192. +
  8193. +#ifdef DWC_CRYPTOLIB
  8194. +# include "dwc_modpow.h"
  8195. +# include "dwc_dh.h"
  8196. +# include "dwc_crypto.h"
  8197. +#endif
  8198. +
  8199. +#ifdef DWC_NOTIFYLIB
  8200. +# include "dwc_notifier.h"
  8201. +#endif
  8202. +
  8203. +/* OS-Level Implementations */
  8204. +
  8205. +/* This is the NetBSD 4.0.1 kernel implementation of the DWC platform library. */
  8206. +
  8207. +
  8208. +/* MISC */
  8209. +
  8210. +void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size)
  8211. +{
  8212. + return memset(dest, byte, size);
  8213. +}
  8214. +
  8215. +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size)
  8216. +{
  8217. + return memcpy(dest, src, size);
  8218. +}
  8219. +
  8220. +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size)
  8221. +{
  8222. + bcopy(src, dest, size);
  8223. + return dest;
  8224. +}
  8225. +
  8226. +int DWC_MEMCMP(void *m1, void *m2, uint32_t size)
  8227. +{
  8228. + return memcmp(m1, m2, size);
  8229. +}
  8230. +
  8231. +int DWC_STRNCMP(void *s1, void *s2, uint32_t size)
  8232. +{
  8233. + return strncmp(s1, s2, size);
  8234. +}
  8235. +
  8236. +int DWC_STRCMP(void *s1, void *s2)
  8237. +{
  8238. + return strcmp(s1, s2);
  8239. +}
  8240. +
  8241. +int DWC_STRLEN(char const *str)
  8242. +{
  8243. + return strlen(str);
  8244. +}
  8245. +
  8246. +char *DWC_STRCPY(char *to, char const *from)
  8247. +{
  8248. + return strcpy(to, from);
  8249. +}
  8250. +
  8251. +char *DWC_STRDUP(char const *str)
  8252. +{
  8253. + int len = DWC_STRLEN(str) + 1;
  8254. + char *new = DWC_ALLOC_ATOMIC(len);
  8255. +
  8256. + if (!new) {
  8257. + return NULL;
  8258. + }
  8259. +
  8260. + DWC_MEMCPY(new, str, len);
  8261. + return new;
  8262. +}
  8263. +
  8264. +int DWC_ATOI(char *str, int32_t *value)
  8265. +{
  8266. + char *end = NULL;
  8267. +
  8268. + /* NetBSD doesn't have 'strtol' in the kernel, but 'strtoul'
  8269. + * should be equivalent on 2's complement machines
  8270. + */
  8271. + *value = strtoul(str, &end, 0);
  8272. + if (*end == '\0') {
  8273. + return 0;
  8274. + }
  8275. +
  8276. + return -1;
  8277. +}
  8278. +
  8279. +int DWC_ATOUI(char *str, uint32_t *value)
  8280. +{
  8281. + char *end = NULL;
  8282. +
  8283. + *value = strtoul(str, &end, 0);
  8284. + if (*end == '\0') {
  8285. + return 0;
  8286. + }
  8287. +
  8288. + return -1;
  8289. +}
  8290. +
  8291. +
  8292. +#ifdef DWC_UTFLIB
  8293. +/* From usbstring.c */
  8294. +
  8295. +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len)
  8296. +{
  8297. + int count = 0;
  8298. + u8 c;
  8299. + u16 uchar;
  8300. +
  8301. + /* this insists on correct encodings, though not minimal ones.
  8302. + * BUT it currently rejects legit 4-byte UTF-8 code points,
  8303. + * which need surrogate pairs. (Unicode 3.1 can use them.)
  8304. + */
  8305. + while (len != 0 && (c = (u8) *s++) != 0) {
  8306. + if (unlikely(c & 0x80)) {
  8307. + // 2-byte sequence:
  8308. + // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
  8309. + if ((c & 0xe0) == 0xc0) {
  8310. + uchar = (c & 0x1f) << 6;
  8311. +
  8312. + c = (u8) *s++;
  8313. + if ((c & 0xc0) != 0xc0)
  8314. + goto fail;
  8315. + c &= 0x3f;
  8316. + uchar |= c;
  8317. +
  8318. + // 3-byte sequence (most CJKV characters):
  8319. + // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
  8320. + } else if ((c & 0xf0) == 0xe0) {
  8321. + uchar = (c & 0x0f) << 12;
  8322. +
  8323. + c = (u8) *s++;
  8324. + if ((c & 0xc0) != 0xc0)
  8325. + goto fail;
  8326. + c &= 0x3f;
  8327. + uchar |= c << 6;
  8328. +
  8329. + c = (u8) *s++;
  8330. + if ((c & 0xc0) != 0xc0)
  8331. + goto fail;
  8332. + c &= 0x3f;
  8333. + uchar |= c;
  8334. +
  8335. + /* no bogus surrogates */
  8336. + if (0xd800 <= uchar && uchar <= 0xdfff)
  8337. + goto fail;
  8338. +
  8339. + // 4-byte sequence (surrogate pairs, currently rare):
  8340. + // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
  8341. + // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
  8342. + // (uuuuu = wwww + 1)
  8343. + // FIXME accept the surrogate code points (only)
  8344. + } else
  8345. + goto fail;
  8346. + } else
  8347. + uchar = c;
  8348. + put_unaligned (cpu_to_le16 (uchar), cp++);
  8349. + count++;
  8350. + len--;
  8351. + }
  8352. + return count;
  8353. +fail:
  8354. + return -1;
  8355. +}
  8356. +
  8357. +#endif /* DWC_UTFLIB */
  8358. +
  8359. +
  8360. +/* dwc_debug.h */
  8361. +
  8362. +dwc_bool_t DWC_IN_IRQ(void)
  8363. +{
  8364. +// return in_irq();
  8365. + return 0;
  8366. +}
  8367. +
  8368. +dwc_bool_t DWC_IN_BH(void)
  8369. +{
  8370. +// return in_softirq();
  8371. + return 0;
  8372. +}
  8373. +
  8374. +void DWC_VPRINTF(char *format, va_list args)
  8375. +{
  8376. + vprintf(format, args);
  8377. +}
  8378. +
  8379. +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args)
  8380. +{
  8381. + return vsnprintf(str, size, format, args);
  8382. +}
  8383. +
  8384. +void DWC_PRINTF(char *format, ...)
  8385. +{
  8386. + va_list args;
  8387. +
  8388. + va_start(args, format);
  8389. + DWC_VPRINTF(format, args);
  8390. + va_end(args);
  8391. +}
  8392. +
  8393. +int DWC_SPRINTF(char *buffer, char *format, ...)
  8394. +{
  8395. + int retval;
  8396. + va_list args;
  8397. +
  8398. + va_start(args, format);
  8399. + retval = vsprintf(buffer, format, args);
  8400. + va_end(args);
  8401. + return retval;
  8402. +}
  8403. +
  8404. +int DWC_SNPRINTF(char *buffer, int size, char *format, ...)
  8405. +{
  8406. + int retval;
  8407. + va_list args;
  8408. +
  8409. + va_start(args, format);
  8410. + retval = vsnprintf(buffer, size, format, args);
  8411. + va_end(args);
  8412. + return retval;
  8413. +}
  8414. +
  8415. +void __DWC_WARN(char *format, ...)
  8416. +{
  8417. + va_list args;
  8418. +
  8419. + va_start(args, format);
  8420. + DWC_VPRINTF(format, args);
  8421. + va_end(args);
  8422. +}
  8423. +
  8424. +void __DWC_ERROR(char *format, ...)
  8425. +{
  8426. + va_list args;
  8427. +
  8428. + va_start(args, format);
  8429. + DWC_VPRINTF(format, args);
  8430. + va_end(args);
  8431. +}
  8432. +
  8433. +void DWC_EXCEPTION(char *format, ...)
  8434. +{
  8435. + va_list args;
  8436. +
  8437. + va_start(args, format);
  8438. + DWC_VPRINTF(format, args);
  8439. + va_end(args);
  8440. +// BUG_ON(1); ???
  8441. +}
  8442. +
  8443. +#ifdef DEBUG
  8444. +void __DWC_DEBUG(char *format, ...)
  8445. +{
  8446. + va_list args;
  8447. +
  8448. + va_start(args, format);
  8449. + DWC_VPRINTF(format, args);
  8450. + va_end(args);
  8451. +}
  8452. +#endif
  8453. +
  8454. +
  8455. +/* dwc_mem.h */
  8456. +
  8457. +#if 0
  8458. +dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size,
  8459. + uint32_t align,
  8460. + uint32_t alloc)
  8461. +{
  8462. + struct dma_pool *pool = dma_pool_create("Pool", NULL,
  8463. + size, align, alloc);
  8464. + return (dwc_pool_t *)pool;
  8465. +}
  8466. +
  8467. +void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool)
  8468. +{
  8469. + dma_pool_destroy((struct dma_pool *)pool);
  8470. +}
  8471. +
  8472. +void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
  8473. +{
  8474. +// return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr);
  8475. + return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr);
  8476. +}
  8477. +
  8478. +void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr)
  8479. +{
  8480. + void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr);
  8481. + memset(..);
  8482. +}
  8483. +
  8484. +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr)
  8485. +{
  8486. + dma_pool_free(pool, vaddr, daddr);
  8487. +}
  8488. +#endif
  8489. +
  8490. +void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr)
  8491. +{
  8492. + dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
  8493. + int error;
  8494. +
  8495. + error = bus_dmamem_alloc(dma->dma_tag, size, 1, size, dma->segs,
  8496. + sizeof(dma->segs) / sizeof(dma->segs[0]),
  8497. + &dma->nsegs, BUS_DMA_NOWAIT);
  8498. + if (error) {
  8499. + printf("%s: bus_dmamem_alloc(%ju) failed: %d\n", __func__,
  8500. + (uintmax_t)size, error);
  8501. + goto fail_0;
  8502. + }
  8503. +
  8504. + error = bus_dmamem_map(dma->dma_tag, dma->segs, dma->nsegs, size,
  8505. + (caddr_t *)&dma->dma_vaddr,
  8506. + BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
  8507. + if (error) {
  8508. + printf("%s: bus_dmamem_map failed: %d\n", __func__, error);
  8509. + goto fail_1;
  8510. + }
  8511. +
  8512. + error = bus_dmamap_create(dma->dma_tag, size, 1, size, 0,
  8513. + BUS_DMA_NOWAIT, &dma->dma_map);
  8514. + if (error) {
  8515. + printf("%s: bus_dmamap_create failed: %d\n", __func__, error);
  8516. + goto fail_2;
  8517. + }
  8518. +
  8519. + error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr,
  8520. + size, NULL, BUS_DMA_NOWAIT);
  8521. + if (error) {
  8522. + printf("%s: bus_dmamap_load failed: %d\n", __func__, error);
  8523. + goto fail_3;
  8524. + }
  8525. +
  8526. + dma->dma_paddr = (bus_addr_t)dma->segs[0].ds_addr;
  8527. + *dma_addr = dma->dma_paddr;
  8528. + return dma->dma_vaddr;
  8529. +
  8530. +fail_3:
  8531. + bus_dmamap_destroy(dma->dma_tag, dma->dma_map);
  8532. +fail_2:
  8533. + bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size);
  8534. +fail_1:
  8535. + bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs);
  8536. +fail_0:
  8537. + dma->dma_map = NULL;
  8538. + dma->dma_vaddr = NULL;
  8539. + dma->nsegs = 0;
  8540. +
  8541. + return NULL;
  8542. +}
  8543. +
  8544. +void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr)
  8545. +{
  8546. + dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx;
  8547. +
  8548. + if (dma->dma_map != NULL) {
  8549. + bus_dmamap_sync(dma->dma_tag, dma->dma_map, 0, size,
  8550. + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
  8551. + bus_dmamap_unload(dma->dma_tag, dma->dma_map);
  8552. + bus_dmamap_destroy(dma->dma_tag, dma->dma_map);
  8553. + bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size);
  8554. + bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs);
  8555. + dma->dma_paddr = 0;
  8556. + dma->dma_map = NULL;
  8557. + dma->dma_vaddr = NULL;
  8558. + dma->nsegs = 0;
  8559. + }
  8560. +}
  8561. +
  8562. +void *__DWC_ALLOC(void *mem_ctx, uint32_t size)
  8563. +{
  8564. + return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
  8565. +}
  8566. +
  8567. +void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size)
  8568. +{
  8569. + return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
  8570. +}
  8571. +
  8572. +void __DWC_FREE(void *mem_ctx, void *addr)
  8573. +{
  8574. + free(addr, M_DEVBUF);
  8575. +}
  8576. +
  8577. +
  8578. +#ifdef DWC_CRYPTOLIB
  8579. +/* dwc_crypto.h */
  8580. +
  8581. +void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length)
  8582. +{
  8583. + get_random_bytes(buffer, length);
  8584. +}
  8585. +
  8586. +int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out)
  8587. +{
  8588. + struct crypto_blkcipher *tfm;
  8589. + struct blkcipher_desc desc;
  8590. + struct scatterlist sgd;
  8591. + struct scatterlist sgs;
  8592. +
  8593. + tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
  8594. + if (tfm == NULL) {
  8595. + printk("failed to load transform for aes CBC\n");
  8596. + return -1;
  8597. + }
  8598. +
  8599. + crypto_blkcipher_setkey(tfm, key, keylen);
  8600. + crypto_blkcipher_set_iv(tfm, iv, 16);
  8601. +
  8602. + sg_init_one(&sgd, out, messagelen);
  8603. + sg_init_one(&sgs, message, messagelen);
  8604. +
  8605. + desc.tfm = tfm;
  8606. + desc.flags = 0;
  8607. +
  8608. + if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) {
  8609. + crypto_free_blkcipher(tfm);
  8610. + DWC_ERROR("AES CBC encryption failed");
  8611. + return -1;
  8612. + }
  8613. +
  8614. + crypto_free_blkcipher(tfm);
  8615. + return 0;
  8616. +}
  8617. +
  8618. +int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out)
  8619. +{
  8620. + struct crypto_hash *tfm;
  8621. + struct hash_desc desc;
  8622. + struct scatterlist sg;
  8623. +
  8624. + tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC);
  8625. + if (IS_ERR(tfm)) {
  8626. + DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm));
  8627. + return 0;
  8628. + }
  8629. + desc.tfm = tfm;
  8630. + desc.flags = 0;
  8631. +
  8632. + sg_init_one(&sg, message, len);
  8633. + crypto_hash_digest(&desc, &sg, len, out);
  8634. + crypto_free_hash(tfm);
  8635. +
  8636. + return 1;
  8637. +}
  8638. +
  8639. +int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen,
  8640. + uint8_t *key, uint32_t keylen, uint8_t *out)
  8641. +{
  8642. + struct crypto_hash *tfm;
  8643. + struct hash_desc desc;
  8644. + struct scatterlist sg;
  8645. +
  8646. + tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC);
  8647. + if (IS_ERR(tfm)) {
  8648. + DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm));
  8649. + return 0;
  8650. + }
  8651. + desc.tfm = tfm;
  8652. + desc.flags = 0;
  8653. +
  8654. + sg_init_one(&sg, message, messagelen);
  8655. + crypto_hash_setkey(tfm, key, keylen);
  8656. + crypto_hash_digest(&desc, &sg, messagelen, out);
  8657. + crypto_free_hash(tfm);
  8658. +
  8659. + return 1;
  8660. +}
  8661. +
  8662. +#endif /* DWC_CRYPTOLIB */
  8663. +
  8664. +
  8665. +/* Byte Ordering Conversions */
  8666. +
  8667. +uint32_t DWC_CPU_TO_LE32(uint32_t *p)
  8668. +{
  8669. +#ifdef __LITTLE_ENDIAN
  8670. + return *p;
  8671. +#else
  8672. + uint8_t *u_p = (uint8_t *)p;
  8673. +
  8674. + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
  8675. +#endif
  8676. +}
  8677. +
  8678. +uint32_t DWC_CPU_TO_BE32(uint32_t *p)
  8679. +{
  8680. +#ifdef __BIG_ENDIAN
  8681. + return *p;
  8682. +#else
  8683. + uint8_t *u_p = (uint8_t *)p;
  8684. +
  8685. + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
  8686. +#endif
  8687. +}
  8688. +
  8689. +uint32_t DWC_LE32_TO_CPU(uint32_t *p)
  8690. +{
  8691. +#ifdef __LITTLE_ENDIAN
  8692. + return *p;
  8693. +#else
  8694. + uint8_t *u_p = (uint8_t *)p;
  8695. +
  8696. + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
  8697. +#endif
  8698. +}
  8699. +
  8700. +uint32_t DWC_BE32_TO_CPU(uint32_t *p)
  8701. +{
  8702. +#ifdef __BIG_ENDIAN
  8703. + return *p;
  8704. +#else
  8705. + uint8_t *u_p = (uint8_t *)p;
  8706. +
  8707. + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24));
  8708. +#endif
  8709. +}
  8710. +
  8711. +uint16_t DWC_CPU_TO_LE16(uint16_t *p)
  8712. +{
  8713. +#ifdef __LITTLE_ENDIAN
  8714. + return *p;
  8715. +#else
  8716. + uint8_t *u_p = (uint8_t *)p;
  8717. + return (u_p[1] | (u_p[0] << 8));
  8718. +#endif
  8719. +}
  8720. +
  8721. +uint16_t DWC_CPU_TO_BE16(uint16_t *p)
  8722. +{
  8723. +#ifdef __BIG_ENDIAN
  8724. + return *p;
  8725. +#else
  8726. + uint8_t *u_p = (uint8_t *)p;
  8727. + return (u_p[1] | (u_p[0] << 8));
  8728. +#endif
  8729. +}
  8730. +
  8731. +uint16_t DWC_LE16_TO_CPU(uint16_t *p)
  8732. +{
  8733. +#ifdef __LITTLE_ENDIAN
  8734. + return *p;
  8735. +#else
  8736. + uint8_t *u_p = (uint8_t *)p;
  8737. + return (u_p[1] | (u_p[0] << 8));
  8738. +#endif
  8739. +}
  8740. +
  8741. +uint16_t DWC_BE16_TO_CPU(uint16_t *p)
  8742. +{
  8743. +#ifdef __BIG_ENDIAN
  8744. + return *p;
  8745. +#else
  8746. + uint8_t *u_p = (uint8_t *)p;
  8747. + return (u_p[1] | (u_p[0] << 8));
  8748. +#endif
  8749. +}
  8750. +
  8751. +
  8752. +/* Registers */
  8753. +
  8754. +uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg)
  8755. +{
  8756. + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
  8757. + bus_size_t ior = (bus_size_t)reg;
  8758. +
  8759. + return bus_space_read_4(io->iot, io->ioh, ior);
  8760. +}
  8761. +
  8762. +#if 0
  8763. +uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg)
  8764. +{
  8765. + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
  8766. + bus_size_t ior = (bus_size_t)reg;
  8767. +
  8768. + return bus_space_read_8(io->iot, io->ioh, ior);
  8769. +}
  8770. +#endif
  8771. +
  8772. +void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value)
  8773. +{
  8774. + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
  8775. + bus_size_t ior = (bus_size_t)reg;
  8776. +
  8777. + bus_space_write_4(io->iot, io->ioh, ior, value);
  8778. +}
  8779. +
  8780. +#if 0
  8781. +void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value)
  8782. +{
  8783. + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
  8784. + bus_size_t ior = (bus_size_t)reg;
  8785. +
  8786. + bus_space_write_8(io->iot, io->ioh, ior, value);
  8787. +}
  8788. +#endif
  8789. +
  8790. +void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask,
  8791. + uint32_t set_mask)
  8792. +{
  8793. + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
  8794. + bus_size_t ior = (bus_size_t)reg;
  8795. +
  8796. + bus_space_write_4(io->iot, io->ioh, ior,
  8797. + (bus_space_read_4(io->iot, io->ioh, ior) &
  8798. + ~clear_mask) | set_mask);
  8799. +}
  8800. +
  8801. +#if 0
  8802. +void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask,
  8803. + uint64_t set_mask)
  8804. +{
  8805. + dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx;
  8806. + bus_size_t ior = (bus_size_t)reg;
  8807. +
  8808. + bus_space_write_8(io->iot, io->ioh, ior,
  8809. + (bus_space_read_8(io->iot, io->ioh, ior) &
  8810. + ~clear_mask) | set_mask);
  8811. +}
  8812. +#endif
  8813. +
  8814. +
  8815. +/* Locking */
  8816. +
  8817. +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void)
  8818. +{
  8819. + struct simplelock *sl = DWC_ALLOC(sizeof(*sl));
  8820. +
  8821. + if (!sl) {
  8822. + DWC_ERROR("Cannot allocate memory for spinlock");
  8823. + return NULL;
  8824. + }
  8825. +
  8826. + simple_lock_init(sl);
  8827. + return (dwc_spinlock_t *)sl;
  8828. +}
  8829. +
  8830. +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock)
  8831. +{
  8832. + struct simplelock *sl = (struct simplelock *)lock;
  8833. +
  8834. + DWC_FREE(sl);
  8835. +}
  8836. +
  8837. +void DWC_SPINLOCK(dwc_spinlock_t *lock)
  8838. +{
  8839. + simple_lock((struct simplelock *)lock);
  8840. +}
  8841. +
  8842. +void DWC_SPINUNLOCK(dwc_spinlock_t *lock)
  8843. +{
  8844. + simple_unlock((struct simplelock *)lock);
  8845. +}
  8846. +
  8847. +void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags)
  8848. +{
  8849. + simple_lock((struct simplelock *)lock);
  8850. + *flags = splbio();
  8851. +}
  8852. +
  8853. +void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags)
  8854. +{
  8855. + splx(flags);
  8856. + simple_unlock((struct simplelock *)lock);
  8857. +}
  8858. +
  8859. +dwc_mutex_t *DWC_MUTEX_ALLOC(void)
  8860. +{
  8861. + dwc_mutex_t *mutex = DWC_ALLOC(sizeof(struct lock));
  8862. +
  8863. + if (!mutex) {
  8864. + DWC_ERROR("Cannot allocate memory for mutex");
  8865. + return NULL;
  8866. + }
  8867. +
  8868. + lockinit((struct lock *)mutex, 0, "dw3mtx", 0, 0);
  8869. + return mutex;
  8870. +}
  8871. +
  8872. +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES))
  8873. +#else
  8874. +void DWC_MUTEX_FREE(dwc_mutex_t *mutex)
  8875. +{
  8876. + DWC_FREE(mutex);
  8877. +}
  8878. +#endif
  8879. +
  8880. +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex)
  8881. +{
  8882. + lockmgr((struct lock *)mutex, LK_EXCLUSIVE, NULL);
  8883. +}
  8884. +
  8885. +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex)
  8886. +{
  8887. + int status;
  8888. +
  8889. + status = lockmgr((struct lock *)mutex, LK_EXCLUSIVE | LK_NOWAIT, NULL);
  8890. + return status == 0;
  8891. +}
  8892. +
  8893. +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex)
  8894. +{
  8895. + lockmgr((struct lock *)mutex, LK_RELEASE, NULL);
  8896. +}
  8897. +
  8898. +
  8899. +/* Timing */
  8900. +
  8901. +void DWC_UDELAY(uint32_t usecs)
  8902. +{
  8903. + DELAY(usecs);
  8904. +}
  8905. +
  8906. +void DWC_MDELAY(uint32_t msecs)
  8907. +{
  8908. + do {
  8909. + DELAY(1000);
  8910. + } while (--msecs);
  8911. +}
  8912. +
  8913. +void DWC_MSLEEP(uint32_t msecs)
  8914. +{
  8915. + struct timeval tv;
  8916. +
  8917. + tv.tv_sec = msecs / 1000;
  8918. + tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
  8919. + tsleep(&tv, 0, "dw3slp", tvtohz(&tv));
  8920. +}
  8921. +
  8922. +uint32_t DWC_TIME(void)
  8923. +{
  8924. + struct timeval tv;
  8925. +
  8926. + microuptime(&tv); // or getmicrouptime? (less precise, but faster)
  8927. + return tv.tv_sec * 1000 + tv.tv_usec / 1000;
  8928. +}
  8929. +
  8930. +
  8931. +/* Timers */
  8932. +
  8933. +struct dwc_timer {
  8934. + struct callout t;
  8935. + char *name;
  8936. + dwc_spinlock_t *lock;
  8937. + dwc_timer_callback_t cb;
  8938. + void *data;
  8939. +};
  8940. +
  8941. +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data)
  8942. +{
  8943. + dwc_timer_t *t = DWC_ALLOC(sizeof(*t));
  8944. +
  8945. + if (!t) {
  8946. + DWC_ERROR("Cannot allocate memory for timer");
  8947. + return NULL;
  8948. + }
  8949. +
  8950. + callout_init(&t->t);
  8951. +
  8952. + t->name = DWC_STRDUP(name);
  8953. + if (!t->name) {
  8954. + DWC_ERROR("Cannot allocate memory for timer->name");
  8955. + goto no_name;
  8956. + }
  8957. +
  8958. + t->lock = DWC_SPINLOCK_ALLOC();
  8959. + if (!t->lock) {
  8960. + DWC_ERROR("Cannot allocate memory for timer->lock");
  8961. + goto no_lock;
  8962. + }
  8963. +
  8964. + t->cb = cb;
  8965. + t->data = data;
  8966. +
  8967. + return t;
  8968. +
  8969. + no_lock:
  8970. + DWC_FREE(t->name);
  8971. + no_name:
  8972. + DWC_FREE(t);
  8973. +
  8974. + return NULL;
  8975. +}
  8976. +
  8977. +void DWC_TIMER_FREE(dwc_timer_t *timer)
  8978. +{
  8979. + callout_stop(&timer->t);
  8980. + DWC_SPINLOCK_FREE(timer->lock);
  8981. + DWC_FREE(timer->name);
  8982. + DWC_FREE(timer);
  8983. +}
  8984. +
  8985. +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time)
  8986. +{
  8987. + struct timeval tv;
  8988. +
  8989. + tv.tv_sec = time / 1000;
  8990. + tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
  8991. + callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data);
  8992. +}
  8993. +
  8994. +void DWC_TIMER_CANCEL(dwc_timer_t *timer)
  8995. +{
  8996. + callout_stop(&timer->t);
  8997. +}
  8998. +
  8999. +
  9000. +/* Wait Queues */
  9001. +
  9002. +struct dwc_waitq {
  9003. + struct simplelock lock;
  9004. + int abort;
  9005. +};
  9006. +
  9007. +dwc_waitq_t *DWC_WAITQ_ALLOC(void)
  9008. +{
  9009. + dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq));
  9010. +
  9011. + if (!wq) {
  9012. + DWC_ERROR("Cannot allocate memory for waitqueue");
  9013. + return NULL;
  9014. + }
  9015. +
  9016. + simple_lock_init(&wq->lock);
  9017. + wq->abort = 0;
  9018. +
  9019. + return wq;
  9020. +}
  9021. +
  9022. +void DWC_WAITQ_FREE(dwc_waitq_t *wq)
  9023. +{
  9024. + DWC_FREE(wq);
  9025. +}
  9026. +
  9027. +int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data)
  9028. +{
  9029. + int ipl;
  9030. + int result = 0;
  9031. +
  9032. + simple_lock(&wq->lock);
  9033. + ipl = splbio();
  9034. +
  9035. + /* Skip the sleep if already aborted or triggered */
  9036. + if (!wq->abort && !cond(data)) {
  9037. + splx(ipl);
  9038. + result = ltsleep(wq, PCATCH, "dw3wat", 0, &wq->lock); // infinite timeout
  9039. + ipl = splbio();
  9040. + }
  9041. +
  9042. + if (result == 0) { // awoken
  9043. + if (wq->abort) {
  9044. + wq->abort = 0;
  9045. + result = -DWC_E_ABORT;
  9046. + } else {
  9047. + result = 0;
  9048. + }
  9049. +
  9050. + splx(ipl);
  9051. + simple_unlock(&wq->lock);
  9052. + } else {
  9053. + wq->abort = 0;
  9054. + splx(ipl);
  9055. + simple_unlock(&wq->lock);
  9056. +
  9057. + if (result == ERESTART) { // signaled - restart
  9058. + result = -DWC_E_RESTART;
  9059. + } else { // signaled - must be EINTR
  9060. + result = -DWC_E_ABORT;
  9061. + }
  9062. + }
  9063. +
  9064. + return result;
  9065. +}
  9066. +
  9067. +int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
  9068. + void *data, int32_t msecs)
  9069. +{
  9070. + struct timeval tv, tv1, tv2;
  9071. + int ipl;
  9072. + int result = 0;
  9073. +
  9074. + tv.tv_sec = msecs / 1000;
  9075. + tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000;
  9076. +
  9077. + simple_lock(&wq->lock);
  9078. + ipl = splbio();
  9079. +
  9080. + /* Skip the sleep if already aborted or triggered */
  9081. + if (!wq->abort && !cond(data)) {
  9082. + splx(ipl);
  9083. + getmicrouptime(&tv1);
  9084. + result = ltsleep(wq, PCATCH, "dw3wto", tvtohz(&tv), &wq->lock);
  9085. + getmicrouptime(&tv2);
  9086. + ipl = splbio();
  9087. + }
  9088. +
  9089. + if (result == 0) { // awoken
  9090. + if (wq->abort) {
  9091. + wq->abort = 0;
  9092. + splx(ipl);
  9093. + simple_unlock(&wq->lock);
  9094. + result = -DWC_E_ABORT;
  9095. + } else {
  9096. + splx(ipl);
  9097. + simple_unlock(&wq->lock);
  9098. +
  9099. + tv2.tv_usec -= tv1.tv_usec;
  9100. + if (tv2.tv_usec < 0) {
  9101. + tv2.tv_usec += 1000000;
  9102. + tv2.tv_sec--;
  9103. + }
  9104. +
  9105. + tv2.tv_sec -= tv1.tv_sec;
  9106. + result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;
  9107. + result = msecs - result;
  9108. + if (result <= 0)
  9109. + result = 1;
  9110. + }
  9111. + } else {
  9112. + wq->abort = 0;
  9113. + splx(ipl);
  9114. + simple_unlock(&wq->lock);
  9115. +
  9116. + if (result == ERESTART) { // signaled - restart
  9117. + result = -DWC_E_RESTART;
  9118. +
  9119. + } else if (result == EINTR) { // signaled - interrupt
  9120. + result = -DWC_E_ABORT;
  9121. +
  9122. + } else { // timed out
  9123. + result = -DWC_E_TIMEOUT;
  9124. + }
  9125. + }
  9126. +
  9127. + return result;
  9128. +}
  9129. +
  9130. +void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq)
  9131. +{
  9132. + wakeup(wq);
  9133. +}
  9134. +
  9135. +void DWC_WAITQ_ABORT(dwc_waitq_t *wq)
  9136. +{
  9137. + int ipl;
  9138. +
  9139. + simple_lock(&wq->lock);
  9140. + ipl = splbio();
  9141. + wq->abort = 1;
  9142. + wakeup(wq);
  9143. + splx(ipl);
  9144. + simple_unlock(&wq->lock);
  9145. +}
  9146. +
  9147. +
  9148. +/* Threading */
  9149. +
  9150. +struct dwc_thread {
  9151. + struct proc *proc;
  9152. + int abort;
  9153. +};
  9154. +
  9155. +dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data)
  9156. +{
  9157. + int retval;
  9158. + dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread));
  9159. +
  9160. + if (!thread) {
  9161. + return NULL;
  9162. + }
  9163. +
  9164. + thread->abort = 0;
  9165. + retval = kthread_create1((void (*)(void *))func, data, &thread->proc,
  9166. + "%s", name);
  9167. + if (retval) {
  9168. + DWC_FREE(thread);
  9169. + return NULL;
  9170. + }
  9171. +
  9172. + return thread;
  9173. +}
  9174. +
  9175. +int DWC_THREAD_STOP(dwc_thread_t *thread)
  9176. +{
  9177. + int retval;
  9178. +
  9179. + thread->abort = 1;
  9180. + retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz);
  9181. +
  9182. + if (retval == 0) {
  9183. + /* DWC_THREAD_EXIT() will free the thread struct */
  9184. + return 0;
  9185. + }
  9186. +
  9187. + /* NOTE: We leak the thread struct if thread doesn't die */
  9188. +
  9189. + if (retval == EWOULDBLOCK) {
  9190. + return -DWC_E_TIMEOUT;
  9191. + }
  9192. +
  9193. + return -DWC_E_UNKNOWN;
  9194. +}
  9195. +
  9196. +dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread)
  9197. +{
  9198. + return thread->abort;
  9199. +}
  9200. +
  9201. +void DWC_THREAD_EXIT(dwc_thread_t *thread)
  9202. +{
  9203. + wakeup(&thread->abort);
  9204. + DWC_FREE(thread);
  9205. + kthread_exit(0);
  9206. +}
  9207. +
  9208. +/* tasklets
  9209. + - Runs in interrupt context (cannot sleep)
  9210. + - Each tasklet runs on a single CPU
  9211. + - Different tasklets can be running simultaneously on different CPUs
  9212. + [ On NetBSD there is no corresponding mechanism, drivers don't have bottom-
  9213. + halves. So we just call the callback directly from DWC_TASK_SCHEDULE() ]
  9214. + */
  9215. +struct dwc_tasklet {
  9216. + dwc_tasklet_callback_t cb;
  9217. + void *data;
  9218. +};
  9219. +
  9220. +static void tasklet_callback(void *data)
  9221. +{
  9222. + dwc_tasklet_t *task = (dwc_tasklet_t *)data;
  9223. +
  9224. + task->cb(task->data);
  9225. +}
  9226. +
  9227. +dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data)
  9228. +{
  9229. + dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task));
  9230. +
  9231. + if (task) {
  9232. + task->cb = cb;
  9233. + task->data = data;
  9234. + } else {
  9235. + DWC_ERROR("Cannot allocate memory for tasklet");
  9236. + }
  9237. +
  9238. + return task;
  9239. +}
  9240. +
  9241. +void DWC_TASK_FREE(dwc_tasklet_t *task)
  9242. +{
  9243. + DWC_FREE(task);
  9244. +}
  9245. +
  9246. +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
  9247. +{
  9248. + tasklet_callback(task);
  9249. +}
  9250. +
  9251. +
  9252. +/* workqueues
  9253. + - Runs in process context (can sleep)
  9254. + */
  9255. +typedef struct work_container {
  9256. + dwc_work_callback_t cb;
  9257. + void *data;
  9258. + dwc_workq_t *wq;
  9259. + char *name;
  9260. + int hz;
  9261. + struct work task;
  9262. +} work_container_t;
  9263. +
  9264. +struct dwc_workq {
  9265. + struct workqueue *taskq;
  9266. + dwc_spinlock_t *lock;
  9267. + dwc_waitq_t *waitq;
  9268. + int pending;
  9269. + struct work_container *container;
  9270. +};
  9271. +
  9272. +static void do_work(struct work *task, void *data)
  9273. +{
  9274. + dwc_workq_t *wq = (dwc_workq_t *)data;
  9275. + work_container_t *container = wq->container;
  9276. + dwc_irqflags_t flags;
  9277. +
  9278. + if (container->hz) {
  9279. + tsleep(container, 0, "dw3wrk", container->hz);
  9280. + }
  9281. +
  9282. + container->cb(container->data);
  9283. + DWC_DEBUG("Work done: %s, container=%p", container->name, container);
  9284. +
  9285. + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
  9286. + if (container->name)
  9287. + DWC_FREE(container->name);
  9288. + DWC_FREE(container);
  9289. + wq->pending--;
  9290. + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
  9291. + DWC_WAITQ_TRIGGER(wq->waitq);
  9292. +}
  9293. +
  9294. +static int work_done(void *data)
  9295. +{
  9296. + dwc_workq_t *workq = (dwc_workq_t *)data;
  9297. +
  9298. + return workq->pending == 0;
  9299. +}
  9300. +
  9301. +int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout)
  9302. +{
  9303. + return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout);
  9304. +}
  9305. +
  9306. +dwc_workq_t *DWC_WORKQ_ALLOC(char *name)
  9307. +{
  9308. + int result;
  9309. + dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq));
  9310. +
  9311. + if (!wq) {
  9312. + DWC_ERROR("Cannot allocate memory for workqueue");
  9313. + return NULL;
  9314. + }
  9315. +
  9316. + result = workqueue_create(&wq->taskq, name, do_work, wq, 0 /*PWAIT*/,
  9317. + IPL_BIO, 0);
  9318. + if (result) {
  9319. + DWC_ERROR("Cannot create workqueue");
  9320. + goto no_taskq;
  9321. + }
  9322. +
  9323. + wq->pending = 0;
  9324. +
  9325. + wq->lock = DWC_SPINLOCK_ALLOC();
  9326. + if (!wq->lock) {
  9327. + DWC_ERROR("Cannot allocate memory for spinlock");
  9328. + goto no_lock;
  9329. + }
  9330. +
  9331. + wq->waitq = DWC_WAITQ_ALLOC();
  9332. + if (!wq->waitq) {
  9333. + DWC_ERROR("Cannot allocate memory for waitqueue");
  9334. + goto no_waitq;
  9335. + }
  9336. +
  9337. + return wq;
  9338. +
  9339. + no_waitq:
  9340. + DWC_SPINLOCK_FREE(wq->lock);
  9341. + no_lock:
  9342. + workqueue_destroy(wq->taskq);
  9343. + no_taskq:
  9344. + DWC_FREE(wq);
  9345. +
  9346. + return NULL;
  9347. +}
  9348. +
  9349. +void DWC_WORKQ_FREE(dwc_workq_t *wq)
  9350. +{
  9351. +#ifdef DEBUG
  9352. + dwc_irqflags_t flags;
  9353. +
  9354. + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
  9355. +
  9356. + if (wq->pending != 0) {
  9357. + struct work_container *container = wq->container;
  9358. +
  9359. + DWC_ERROR("Destroying work queue with pending work");
  9360. +
  9361. + if (container && container->name) {
  9362. + DWC_ERROR("Work %s still pending", container->name);
  9363. + }
  9364. + }
  9365. +
  9366. + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
  9367. +#endif
  9368. + DWC_WAITQ_FREE(wq->waitq);
  9369. + DWC_SPINLOCK_FREE(wq->lock);
  9370. + workqueue_destroy(wq->taskq);
  9371. + DWC_FREE(wq);
  9372. +}
  9373. +
  9374. +void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data,
  9375. + char *format, ...)
  9376. +{
  9377. + dwc_irqflags_t flags;
  9378. + work_container_t *container;
  9379. + static char name[128];
  9380. + va_list args;
  9381. +
  9382. + va_start(args, format);
  9383. + DWC_VSNPRINTF(name, 128, format, args);
  9384. + va_end(args);
  9385. +
  9386. + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
  9387. + wq->pending++;
  9388. + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
  9389. + DWC_WAITQ_TRIGGER(wq->waitq);
  9390. +
  9391. + container = DWC_ALLOC_ATOMIC(sizeof(*container));
  9392. + if (!container) {
  9393. + DWC_ERROR("Cannot allocate memory for container");
  9394. + return;
  9395. + }
  9396. +
  9397. + container->name = DWC_STRDUP(name);
  9398. + if (!container->name) {
  9399. + DWC_ERROR("Cannot allocate memory for container->name");
  9400. + DWC_FREE(container);
  9401. + return;
  9402. + }
  9403. +
  9404. + container->cb = cb;
  9405. + container->data = data;
  9406. + container->wq = wq;
  9407. + container->hz = 0;
  9408. + wq->container = container;
  9409. +
  9410. + DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
  9411. + workqueue_enqueue(wq->taskq, &container->task);
  9412. +}
  9413. +
  9414. +void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb,
  9415. + void *data, uint32_t time, char *format, ...)
  9416. +{
  9417. + dwc_irqflags_t flags;
  9418. + work_container_t *container;
  9419. + static char name[128];
  9420. + struct timeval tv;
  9421. + va_list args;
  9422. +
  9423. + va_start(args, format);
  9424. + DWC_VSNPRINTF(name, 128, format, args);
  9425. + va_end(args);
  9426. +
  9427. + DWC_SPINLOCK_IRQSAVE(wq->lock, &flags);
  9428. + wq->pending++;
  9429. + DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags);
  9430. + DWC_WAITQ_TRIGGER(wq->waitq);
  9431. +
  9432. + container = DWC_ALLOC_ATOMIC(sizeof(*container));
  9433. + if (!container) {
  9434. + DWC_ERROR("Cannot allocate memory for container");
  9435. + return;
  9436. + }
  9437. +
  9438. + container->name = DWC_STRDUP(name);
  9439. + if (!container->name) {
  9440. + DWC_ERROR("Cannot allocate memory for container->name");
  9441. + DWC_FREE(container);
  9442. + return;
  9443. + }
  9444. +
  9445. + container->cb = cb;
  9446. + container->data = data;
  9447. + container->wq = wq;
  9448. + tv.tv_sec = time / 1000;
  9449. + tv.tv_usec = (time - tv.tv_sec * 1000) * 1000;
  9450. + container->hz = tvtohz(&tv);
  9451. + wq->container = container;
  9452. +
  9453. + DWC_DEBUG("Queueing work: %s, container=%p", container->name, container);
  9454. + workqueue_enqueue(wq->taskq, &container->task);
  9455. +}
  9456. +
  9457. +int DWC_WORKQ_PENDING(dwc_workq_t *wq)
  9458. +{
  9459. + return wq->pending;
  9460. +}
  9461. --- /dev/null
  9462. +++ b/drivers/usb/host/dwc_common_port/dwc_crypto.c
  9463. @@ -0,0 +1,308 @@
  9464. +/* =========================================================================
  9465. + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.c $
  9466. + * $Revision: #5 $
  9467. + * $Date: 2010/09/28 $
  9468. + * $Change: 1596182 $
  9469. + *
  9470. + * Synopsys Portability Library Software and documentation
  9471. + * (hereinafter, "Software") is an Unsupported proprietary work of
  9472. + * Synopsys, Inc. unless otherwise expressly agreed to in writing
  9473. + * between Synopsys and you.
  9474. + *
  9475. + * The Software IS NOT an item of Licensed Software or Licensed Product
  9476. + * under any End User Software License Agreement or Agreement for
  9477. + * Licensed Product with Synopsys or any supplement thereto. You are
  9478. + * permitted to use and redistribute this Software in source and binary
  9479. + * forms, with or without modification, provided that redistributions
  9480. + * of source code must retain this notice. You may not view, use,
  9481. + * disclose, copy or distribute this file or any information contained
  9482. + * herein except pursuant to this license grant from Synopsys. If you
  9483. + * do not agree with this notice, including the disclaimer below, then
  9484. + * you are not authorized to use the Software.
  9485. + *
  9486. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
  9487. + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  9488. + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  9489. + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
  9490. + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  9491. + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  9492. + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  9493. + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  9494. + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  9495. + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  9496. + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  9497. + * DAMAGE.
  9498. + * ========================================================================= */
  9499. +
  9500. +/** @file
  9501. + * This file contains the WUSB cryptographic routines.
  9502. + */
  9503. +
  9504. +#ifdef DWC_CRYPTOLIB
  9505. +
  9506. +#include "dwc_crypto.h"
  9507. +#include "usb.h"
  9508. +
  9509. +#ifdef DEBUG
  9510. +static inline void dump_bytes(char *name, uint8_t *bytes, int len)
  9511. +{
  9512. + int i;
  9513. + DWC_PRINTF("%s: ", name);
  9514. + for (i=0; i<len; i++) {
  9515. + DWC_PRINTF("%02x ", bytes[i]);
  9516. + }
  9517. + DWC_PRINTF("\n");
  9518. +}
  9519. +#else
  9520. +#define dump_bytes(x...)
  9521. +#endif
  9522. +
  9523. +/* Display a block */
  9524. +void show_block(const u8 *blk, const char *prefix, const char *suffix, int a)
  9525. +{
  9526. +#ifdef DWC_DEBUG_CRYPTO
  9527. + int i, blksize = 16;
  9528. +
  9529. + DWC_DEBUG("%s", prefix);
  9530. +
  9531. + if (suffix == NULL) {
  9532. + suffix = "\n";
  9533. + blksize = a;
  9534. + }
  9535. +
  9536. + for (i = 0; i < blksize; i++)
  9537. + DWC_PRINT("%02x%s", *blk++, ((i & 3) == 3) ? " " : " ");
  9538. + DWC_PRINT(suffix);
  9539. +#endif
  9540. +}
  9541. +
  9542. +/**
  9543. + * Encrypts an array of bytes using the AES encryption engine.
  9544. + * If <code>dst</code> == <code>src</code>, then the bytes will be encrypted
  9545. + * in-place.
  9546. + *
  9547. + * @return 0 on success, negative error code on error.
  9548. + */
  9549. +int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst)
  9550. +{
  9551. + u8 block_t[16];
  9552. + DWC_MEMSET(block_t, 0, 16);
  9553. +
  9554. + return DWC_AES_CBC(src, 16, key, 16, block_t, dst);
  9555. +}
  9556. +
  9557. +/**
  9558. + * The CCM-MAC-FUNCTION described in section 6.5 of the WUSB spec.
  9559. + * This function takes a data string and returns the encrypted CBC
  9560. + * Counter-mode MIC.
  9561. + *
  9562. + * @param key The 128-bit symmetric key.
  9563. + * @param nonce The CCM nonce.
  9564. + * @param label The unique 14-byte ASCII text label.
  9565. + * @param bytes The byte array to be encrypted.
  9566. + * @param len Length of the byte array.
  9567. + * @param result Byte array to receive the 8-byte encrypted MIC.
  9568. + */
  9569. +void dwc_wusb_cmf(u8 *key, u8 *nonce,
  9570. + char *label, u8 *bytes, int len, u8 *result)
  9571. +{
  9572. + u8 block_m[16];
  9573. + u8 block_x[16];
  9574. + u8 block_t[8];
  9575. + int idx, blkNum;
  9576. + u16 la = (u16)(len + 14);
  9577. +
  9578. + /* Set the AES-128 key */
  9579. + //dwc_aes_setkey(tfm, key, 16);
  9580. +
  9581. + /* Fill block B0 from flags = 0x59, N, and l(m) = 0 */
  9582. + block_m[0] = 0x59;
  9583. + for (idx = 0; idx < 13; idx++)
  9584. + block_m[idx + 1] = nonce[idx];
  9585. + block_m[14] = 0;
  9586. + block_m[15] = 0;
  9587. +
  9588. + /* Produce the CBC IV */
  9589. + dwc_wusb_aes_encrypt(block_m, key, block_x);
  9590. + show_block(block_m, "CBC IV in: ", "\n", 0);
  9591. + show_block(block_x, "CBC IV out:", "\n", 0);
  9592. +
  9593. + /* Fill block B1 from l(a) = Blen + 14, and A */
  9594. + block_x[0] ^= (u8)(la >> 8);
  9595. + block_x[1] ^= (u8)la;
  9596. + for (idx = 0; idx < 14; idx++)
  9597. + block_x[idx + 2] ^= label[idx];
  9598. + show_block(block_x, "After xor: ", "b1\n", 16);
  9599. +
  9600. + dwc_wusb_aes_encrypt(block_x, key, block_x);
  9601. + show_block(block_x, "After AES: ", "b1\n", 16);
  9602. +
  9603. + idx = 0;
  9604. + blkNum = 0;
  9605. +
  9606. + /* Fill remaining blocks with B */
  9607. + while (len-- > 0) {
  9608. + block_x[idx] ^= *bytes++;
  9609. + if (++idx >= 16) {
  9610. + idx = 0;
  9611. + show_block(block_x, "After xor: ", "\n", blkNum);
  9612. + dwc_wusb_aes_encrypt(block_x, key, block_x);
  9613. + show_block(block_x, "After AES: ", "\n", blkNum);
  9614. + blkNum++;
  9615. + }
  9616. + }
  9617. +
  9618. + /* Handle partial last block */
  9619. + if (idx > 0) {
  9620. + show_block(block_x, "After xor: ", "\n", blkNum);
  9621. + dwc_wusb_aes_encrypt(block_x, key, block_x);
  9622. + show_block(block_x, "After AES: ", "\n", blkNum);
  9623. + }
  9624. +
  9625. + /* Save the MIC tag */
  9626. + DWC_MEMCPY(block_t, block_x, 8);
  9627. + show_block(block_t, "MIC tag : ", NULL, 8);
  9628. +
  9629. + /* Fill block A0 from flags = 0x01, N, and counter = 0 */
  9630. + block_m[0] = 0x01;
  9631. + block_m[14] = 0;
  9632. + block_m[15] = 0;
  9633. +
  9634. + /* Encrypt the counter */
  9635. + dwc_wusb_aes_encrypt(block_m, key, block_x);
  9636. + show_block(block_x, "CTR[MIC] : ", NULL, 8);
  9637. +
  9638. + /* XOR with MIC tag */
  9639. + for (idx = 0; idx < 8; idx++) {
  9640. + block_t[idx] ^= block_x[idx];
  9641. + }
  9642. +
  9643. + /* Return result to caller */
  9644. + DWC_MEMCPY(result, block_t, 8);
  9645. + show_block(result, "CCM-MIC : ", NULL, 8);
  9646. +
  9647. +}
  9648. +
  9649. +/**
  9650. + * The PRF function described in section 6.5 of the WUSB spec. This function
  9651. + * concatenates MIC values returned from dwc_cmf() to create a value of
  9652. + * the requested length.
  9653. + *
  9654. + * @param prf_len Length of the PRF function in bits (64, 128, or 256).
  9655. + * @param key, nonce, label, bytes, len Same as for dwc_cmf().
  9656. + * @param result Byte array to receive the result.
  9657. + */
  9658. +void dwc_wusb_prf(int prf_len, u8 *key,
  9659. + u8 *nonce, char *label, u8 *bytes, int len, u8 *result)
  9660. +{
  9661. + int i;
  9662. +
  9663. + nonce[0] = 0;
  9664. + for (i = 0; i < prf_len >> 6; i++, nonce[0]++) {
  9665. + dwc_wusb_cmf(key, nonce, label, bytes, len, result);
  9666. + result += 8;
  9667. + }
  9668. +}
  9669. +
  9670. +/**
  9671. + * Fills in CCM Nonce per the WUSB spec.
  9672. + *
  9673. + * @param[in] haddr Host address.
  9674. + * @param[in] daddr Device address.
  9675. + * @param[in] tkid Session Key(PTK) identifier.
  9676. + * @param[out] nonce Pointer to where the CCM Nonce output is to be written.
  9677. + */
  9678. +void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,
  9679. + uint8_t *nonce)
  9680. +{
  9681. +
  9682. + DWC_DEBUG("%s %x %x\n", __func__, daddr, haddr);
  9683. +
  9684. + DWC_MEMSET(&nonce[0], 0, 16);
  9685. +
  9686. + DWC_MEMCPY(&nonce[6], tkid, 3);
  9687. + nonce[9] = daddr & 0xFF;
  9688. + nonce[10] = (daddr >> 8) & 0xFF;
  9689. + nonce[11] = haddr & 0xFF;
  9690. + nonce[12] = (haddr >> 8) & 0xFF;
  9691. +
  9692. + dump_bytes("CCM nonce", nonce, 16);
  9693. +}
  9694. +
  9695. +/**
  9696. + * Generates a 16-byte cryptographic-grade random number for the Host/Device
  9697. + * Nonce.
  9698. + */
  9699. +void dwc_wusb_gen_nonce(uint16_t addr, uint8_t *nonce)
  9700. +{
  9701. + uint8_t inonce[16];
  9702. + uint32_t temp[4];
  9703. +
  9704. + /* Fill in the Nonce */
  9705. + DWC_MEMSET(&inonce[0], 0, sizeof(inonce));
  9706. + inonce[9] = addr & 0xFF;
  9707. + inonce[10] = (addr >> 8) & 0xFF;
  9708. + inonce[11] = inonce[9];
  9709. + inonce[12] = inonce[10];
  9710. +
  9711. + /* Collect "randomness samples" */
  9712. + DWC_RANDOM_BYTES((uint8_t *)temp, 16);
  9713. +
  9714. + dwc_wusb_prf_128((uint8_t *)temp, nonce,
  9715. + "Random Numbers", (uint8_t *)temp, sizeof(temp),
  9716. + nonce);
  9717. +}
  9718. +
  9719. +/**
  9720. + * Generates the Session Key (PTK) and Key Confirmation Key (KCK) per the
  9721. + * WUSB spec.
  9722. + *
  9723. + * @param[in] ccm_nonce Pointer to CCM Nonce.
  9724. + * @param[in] mk Master Key to derive the session from
  9725. + * @param[in] hnonce Pointer to Host Nonce.
  9726. + * @param[in] dnonce Pointer to Device Nonce.
  9727. + * @param[out] kck Pointer to where the KCK output is to be written.
  9728. + * @param[out] ptk Pointer to where the PTK output is to be written.
  9729. + */
  9730. +void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, uint8_t *hnonce,
  9731. + uint8_t *dnonce, uint8_t *kck, uint8_t *ptk)
  9732. +{
  9733. + uint8_t idata[32];
  9734. + uint8_t odata[32];
  9735. +
  9736. + dump_bytes("ck", mk, 16);
  9737. + dump_bytes("hnonce", hnonce, 16);
  9738. + dump_bytes("dnonce", dnonce, 16);
  9739. +
  9740. + /* The data is the HNonce and DNonce concatenated */
  9741. + DWC_MEMCPY(&idata[0], hnonce, 16);
  9742. + DWC_MEMCPY(&idata[16], dnonce, 16);
  9743. +
  9744. + dwc_wusb_prf_256(mk, ccm_nonce, "Pair-wise keys", idata, 32, odata);
  9745. +
  9746. + /* Low 16 bytes of the result is the KCK, high 16 is the PTK */
  9747. + DWC_MEMCPY(kck, &odata[0], 16);
  9748. + DWC_MEMCPY(ptk, &odata[16], 16);
  9749. +
  9750. + dump_bytes("kck", kck, 16);
  9751. + dump_bytes("ptk", ptk, 16);
  9752. +}
  9753. +
  9754. +/**
  9755. + * Generates the Message Integrity Code over the Handshake data per the
  9756. + * WUSB spec.
  9757. + *
  9758. + * @param ccm_nonce Pointer to CCM Nonce.
  9759. + * @param kck Pointer to Key Confirmation Key.
  9760. + * @param data Pointer to Handshake data to be checked.
  9761. + * @param mic Pointer to where the MIC output is to be written.
  9762. + */
  9763. +void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t *kck,
  9764. + uint8_t *data, uint8_t *mic)
  9765. +{
  9766. +
  9767. + dwc_wusb_prf_64(kck, ccm_nonce, "out-of-bandMIC",
  9768. + data, WUSB_HANDSHAKE_LEN_FOR_MIC, mic);
  9769. +}
  9770. +
  9771. +#endif /* DWC_CRYPTOLIB */
  9772. --- /dev/null
  9773. +++ b/drivers/usb/host/dwc_common_port/dwc_crypto.h
  9774. @@ -0,0 +1,111 @@
  9775. +/* =========================================================================
  9776. + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.h $
  9777. + * $Revision: #3 $
  9778. + * $Date: 2010/09/28 $
  9779. + * $Change: 1596182 $
  9780. + *
  9781. + * Synopsys Portability Library Software and documentation
  9782. + * (hereinafter, "Software") is an Unsupported proprietary work of
  9783. + * Synopsys, Inc. unless otherwise expressly agreed to in writing
  9784. + * between Synopsys and you.
  9785. + *
  9786. + * The Software IS NOT an item of Licensed Software or Licensed Product
  9787. + * under any End User Software License Agreement or Agreement for
  9788. + * Licensed Product with Synopsys or any supplement thereto. You are
  9789. + * permitted to use and redistribute this Software in source and binary
  9790. + * forms, with or without modification, provided that redistributions
  9791. + * of source code must retain this notice. You may not view, use,
  9792. + * disclose, copy or distribute this file or any information contained
  9793. + * herein except pursuant to this license grant from Synopsys. If you
  9794. + * do not agree with this notice, including the disclaimer below, then
  9795. + * you are not authorized to use the Software.
  9796. + *
  9797. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
  9798. + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  9799. + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  9800. + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
  9801. + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  9802. + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  9803. + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  9804. + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  9805. + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  9806. + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  9807. + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  9808. + * DAMAGE.
  9809. + * ========================================================================= */
  9810. +
  9811. +#ifndef _DWC_CRYPTO_H_
  9812. +#define _DWC_CRYPTO_H_
  9813. +
  9814. +#ifdef __cplusplus
  9815. +extern "C" {
  9816. +#endif
  9817. +
  9818. +/** @file
  9819. + *
  9820. + * This file contains declarations for the WUSB Cryptographic routines as
  9821. + * defined in the WUSB spec. They are only to be used internally by the DWC UWB
  9822. + * modules.
  9823. + */
  9824. +
  9825. +#include "dwc_os.h"
  9826. +
  9827. +int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst);
  9828. +
  9829. +void dwc_wusb_cmf(u8 *key, u8 *nonce,
  9830. + char *label, u8 *bytes, int len, u8 *result);
  9831. +void dwc_wusb_prf(int prf_len, u8 *key,
  9832. + u8 *nonce, char *label, u8 *bytes, int len, u8 *result);
  9833. +
  9834. +/**
  9835. + * The PRF-64 function described in section 6.5 of the WUSB spec.
  9836. + *
  9837. + * @param key, nonce, label, bytes, len, result Same as for dwc_prf().
  9838. + */
  9839. +static inline void dwc_wusb_prf_64(u8 *key, u8 *nonce,
  9840. + char *label, u8 *bytes, int len, u8 *result)
  9841. +{
  9842. + dwc_wusb_prf(64, key, nonce, label, bytes, len, result);
  9843. +}
  9844. +
  9845. +/**
  9846. + * The PRF-128 function described in section 6.5 of the WUSB spec.
  9847. + *
  9848. + * @param key, nonce, label, bytes, len, result Same as for dwc_prf().
  9849. + */
  9850. +static inline void dwc_wusb_prf_128(u8 *key, u8 *nonce,
  9851. + char *label, u8 *bytes, int len, u8 *result)
  9852. +{
  9853. + dwc_wusb_prf(128, key, nonce, label, bytes, len, result);
  9854. +}
  9855. +
  9856. +/**
  9857. + * The PRF-256 function described in section 6.5 of the WUSB spec.
  9858. + *
  9859. + * @param key, nonce, label, bytes, len, result Same as for dwc_prf().
  9860. + */
  9861. +static inline void dwc_wusb_prf_256(u8 *key, u8 *nonce,
  9862. + char *label, u8 *bytes, int len, u8 *result)
  9863. +{
  9864. + dwc_wusb_prf(256, key, nonce, label, bytes, len, result);
  9865. +}
  9866. +
  9867. +
  9868. +void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,
  9869. + uint8_t *nonce);
  9870. +void dwc_wusb_gen_nonce(uint16_t addr,
  9871. + uint8_t *nonce);
  9872. +
  9873. +void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk,
  9874. + uint8_t *hnonce, uint8_t *dnonce,
  9875. + uint8_t *kck, uint8_t *ptk);
  9876. +
  9877. +
  9878. +void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t
  9879. + *kck, uint8_t *data, uint8_t *mic);
  9880. +
  9881. +#ifdef __cplusplus
  9882. +}
  9883. +#endif
  9884. +
  9885. +#endif /* _DWC_CRYPTO_H_ */
  9886. --- /dev/null
  9887. +++ b/drivers/usb/host/dwc_common_port/dwc_dh.c
  9888. @@ -0,0 +1,291 @@
  9889. +/* =========================================================================
  9890. + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.c $
  9891. + * $Revision: #3 $
  9892. + * $Date: 2010/09/28 $
  9893. + * $Change: 1596182 $
  9894. + *
  9895. + * Synopsys Portability Library Software and documentation
  9896. + * (hereinafter, "Software") is an Unsupported proprietary work of
  9897. + * Synopsys, Inc. unless otherwise expressly agreed to in writing
  9898. + * between Synopsys and you.
  9899. + *
  9900. + * The Software IS NOT an item of Licensed Software or Licensed Product
  9901. + * under any End User Software License Agreement or Agreement for
  9902. + * Licensed Product with Synopsys or any supplement thereto. You are
  9903. + * permitted to use and redistribute this Software in source and binary
  9904. + * forms, with or without modification, provided that redistributions
  9905. + * of source code must retain this notice. You may not view, use,
  9906. + * disclose, copy or distribute this file or any information contained
  9907. + * herein except pursuant to this license grant from Synopsys. If you
  9908. + * do not agree with this notice, including the disclaimer below, then
  9909. + * you are not authorized to use the Software.
  9910. + *
  9911. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
  9912. + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  9913. + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  9914. + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
  9915. + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  9916. + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  9917. + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  9918. + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  9919. + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  9920. + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  9921. + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  9922. + * DAMAGE.
  9923. + * ========================================================================= */
  9924. +#ifdef DWC_CRYPTOLIB
  9925. +
  9926. +#ifndef CONFIG_MACH_IPMATE
  9927. +
  9928. +#include "dwc_dh.h"
  9929. +#include "dwc_modpow.h"
  9930. +
  9931. +#ifdef DEBUG
  9932. +/* This function prints out a buffer in the format described in the Association
  9933. + * Model specification. */
  9934. +static void dh_dump(char *str, void *_num, int len)
  9935. +{
  9936. + uint8_t *num = _num;
  9937. + int i;
  9938. + DWC_PRINTF("%s\n", str);
  9939. + for (i = 0; i < len; i ++) {
  9940. + DWC_PRINTF("%02x", num[i]);
  9941. + if (((i + 1) % 2) == 0) DWC_PRINTF(" ");
  9942. + if (((i + 1) % 26) == 0) DWC_PRINTF("\n");
  9943. + }
  9944. +
  9945. + DWC_PRINTF("\n");
  9946. +}
  9947. +#else
  9948. +#define dh_dump(_x...) do {; } while(0)
  9949. +#endif
  9950. +
  9951. +/* Constant g value */
  9952. +static __u32 dh_g[] = {
  9953. + 0x02000000,
  9954. +};
  9955. +
  9956. +/* Constant p value */
  9957. +static __u32 dh_p[] = {
  9958. + 0xFFFFFFFF, 0xFFFFFFFF, 0xA2DA0FC9, 0x34C26821, 0x8B62C6C4, 0xD11CDC80, 0x084E0229, 0x74CC678A,
  9959. + 0xA6BE0B02, 0x229B133B, 0x79084A51, 0xDD04348E, 0xB31995EF, 0x1B433ACD, 0x6D0A2B30, 0x37145FF2,
  9960. + 0x6D35E14F, 0x45C2516D, 0x76B585E4, 0xC67E5E62, 0xE9424CF4, 0x6BED37A6, 0xB65CFF0B, 0xEDB706F4,
  9961. + 0xFB6B38EE, 0xA59F895A, 0x11249FAE, 0xE61F4B7C, 0x51662849, 0x3D5BE4EC, 0xB87C00C2, 0x05BF63A1,
  9962. + 0x3648DA98, 0x9AD3551C, 0xA83F1669, 0x5FCF24FD, 0x235D6583, 0x96ADA3DC, 0x56F3621C, 0xBB528520,
  9963. + 0x0729D59E, 0x6D969670, 0x4E350C67, 0x0498BC4A, 0x086C74F1, 0x7C2118CA, 0x465E9032, 0x3BCE362E,
  9964. + 0x2C779EE3, 0x03860E18, 0xA283279B, 0x8FA207EC, 0xF05DC5B5, 0xC9524C6F, 0xF6CB2BDE, 0x18175895,
  9965. + 0x7C499539, 0xE56A95EA, 0x1826D215, 0x1005FA98, 0x5A8E7215, 0x2DC4AA8A, 0x0D1733AD, 0x337A5004,
  9966. + 0xAB2155A8, 0x64BA1CDF, 0x0485FBEC, 0x0AEFDB58, 0x5771EA8A, 0x7D0C065D, 0x850F97B3, 0xC7E4E1A6,
  9967. + 0x8CAEF5AB, 0xD73309DB, 0xE0948C1E, 0x9D61254A, 0x26D2E3CE, 0x6BEED21A, 0x06FA2FF1, 0x64088AD9,
  9968. + 0x730276D8, 0x646AC83E, 0x182B1F52, 0x0C207B17, 0x5717E1BB, 0x6C5D617A, 0xC0880977, 0xE246D9BA,
  9969. + 0xA04FE208, 0x31ABE574, 0xFC5BDB43, 0x8E10FDE0, 0x20D1824B, 0xCAD23AA9, 0xFFFFFFFF, 0xFFFFFFFF,
  9970. +};
  9971. +
  9972. +static void dh_swap_bytes(void *_in, void *_out, uint32_t len)
  9973. +{
  9974. + uint8_t *in = _in;
  9975. + uint8_t *out = _out;
  9976. + int i;
  9977. + for (i=0; i<len; i++) {
  9978. + out[i] = in[len-1-i];
  9979. + }
  9980. +}
  9981. +
  9982. +/* Computes the modular exponentiation (num^exp % mod). num, exp, and mod are
  9983. + * big endian numbers of size len, in bytes. Each len value must be a multiple
  9984. + * of 4. */
  9985. +int dwc_dh_modpow(void *mem_ctx, void *num, uint32_t num_len,
  9986. + void *exp, uint32_t exp_len,
  9987. + void *mod, uint32_t mod_len,
  9988. + void *out)
  9989. +{
  9990. + /* modpow() takes little endian numbers. AM uses big-endian. This
  9991. + * function swaps bytes of numbers before passing onto modpow. */
  9992. +
  9993. + int retval = 0;
  9994. + uint32_t *result;
  9995. +
  9996. + uint32_t *bignum_num = dwc_alloc(mem_ctx, num_len + 4);
  9997. + uint32_t *bignum_exp = dwc_alloc(mem_ctx, exp_len + 4);
  9998. + uint32_t *bignum_mod = dwc_alloc(mem_ctx, mod_len + 4);
  9999. +
  10000. + dh_swap_bytes(num, &bignum_num[1], num_len);
  10001. + bignum_num[0] = num_len / 4;
  10002. +
  10003. + dh_swap_bytes(exp, &bignum_exp[1], exp_len);
  10004. + bignum_exp[0] = exp_len / 4;
  10005. +
  10006. + dh_swap_bytes(mod, &bignum_mod[1], mod_len);
  10007. + bignum_mod[0] = mod_len / 4;
  10008. +
  10009. + result = dwc_modpow(mem_ctx, bignum_num, bignum_exp, bignum_mod);
  10010. + if (!result) {
  10011. + retval = -1;
  10012. + goto dh_modpow_nomem;
  10013. + }
  10014. +
  10015. + dh_swap_bytes(&result[1], out, result[0] * 4);
  10016. + dwc_free(mem_ctx, result);
  10017. +
  10018. + dh_modpow_nomem:
  10019. + dwc_free(mem_ctx, bignum_num);
  10020. + dwc_free(mem_ctx, bignum_exp);
  10021. + dwc_free(mem_ctx, bignum_mod);
  10022. + return retval;
  10023. +}
  10024. +
  10025. +
  10026. +int dwc_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pk, uint8_t *hash)
  10027. +{
  10028. + int retval;
  10029. + uint8_t m3[385];
  10030. +
  10031. +#ifndef DH_TEST_VECTORS
  10032. + DWC_RANDOM_BYTES(exp, 32);
  10033. +#endif
  10034. +
  10035. + /* Compute the pkd */
  10036. + if ((retval = dwc_dh_modpow(mem_ctx, dh_g, 4,
  10037. + exp, 32,
  10038. + dh_p, 384, pk))) {
  10039. + return retval;
  10040. + }
  10041. +
  10042. + m3[384] = nd;
  10043. + DWC_MEMCPY(&m3[0], pk, 384);
  10044. + DWC_SHA256(m3, 385, hash);
  10045. +
  10046. + dh_dump("PK", pk, 384);
  10047. + dh_dump("SHA-256(M3)", hash, 32);
  10048. + return 0;
  10049. +}
  10050. +
  10051. +int dwc_dh_derive_keys(void *mem_ctx, uint8_t nd, uint8_t *pkh, uint8_t *pkd,
  10052. + uint8_t *exp, int is_host,
  10053. + char *dd, uint8_t *ck, uint8_t *kdk)
  10054. +{
  10055. + int retval;
  10056. + uint8_t mv[784];
  10057. + uint8_t sha_result[32];
  10058. + uint8_t dhkey[384];
  10059. + uint8_t shared_secret[384];
  10060. + char *message;
  10061. + uint32_t vd;
  10062. +
  10063. + uint8_t *pk;
  10064. +
  10065. + if (is_host) {
  10066. + pk = pkd;
  10067. + }
  10068. + else {
  10069. + pk = pkh;
  10070. + }
  10071. +
  10072. + if ((retval = dwc_dh_modpow(mem_ctx, pk, 384,
  10073. + exp, 32,
  10074. + dh_p, 384, shared_secret))) {
  10075. + return retval;
  10076. + }
  10077. + dh_dump("Shared Secret", shared_secret, 384);
  10078. +
  10079. + DWC_SHA256(shared_secret, 384, dhkey);
  10080. + dh_dump("DHKEY", dhkey, 384);
  10081. +
  10082. + DWC_MEMCPY(&mv[0], pkd, 384);
  10083. + DWC_MEMCPY(&mv[384], pkh, 384);
  10084. + DWC_MEMCPY(&mv[768], "displayed digest", 16);
  10085. + dh_dump("MV", mv, 784);
  10086. +
  10087. + DWC_SHA256(mv, 784, sha_result);
  10088. + dh_dump("SHA-256(MV)", sha_result, 32);
  10089. + dh_dump("First 32-bits of SHA-256(MV)", sha_result, 4);
  10090. +
  10091. + dh_swap_bytes(sha_result, &vd, 4);
  10092. +#ifdef DEBUG
  10093. + DWC_PRINTF("Vd (decimal) = %d\n", vd);
  10094. +#endif
  10095. +
  10096. + switch (nd) {
  10097. + case 2:
  10098. + vd = vd % 100;
  10099. + DWC_SPRINTF(dd, "%02d", vd);
  10100. + break;
  10101. + case 3:
  10102. + vd = vd % 1000;
  10103. + DWC_SPRINTF(dd, "%03d", vd);
  10104. + break;
  10105. + case 4:
  10106. + vd = vd % 10000;
  10107. + DWC_SPRINTF(dd, "%04d", vd);
  10108. + break;
  10109. + }
  10110. +#ifdef DEBUG
  10111. + DWC_PRINTF("Display Digits: %s\n", dd);
  10112. +#endif
  10113. +
  10114. + message = "connection key";
  10115. + DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
  10116. + dh_dump("HMAC(SHA-256, DHKey, connection key)", sha_result, 32);
  10117. + DWC_MEMCPY(ck, sha_result, 16);
  10118. +
  10119. + message = "key derivation key";
  10120. + DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
  10121. + dh_dump("HMAC(SHA-256, DHKey, key derivation key)", sha_result, 32);
  10122. + DWC_MEMCPY(kdk, sha_result, 32);
  10123. +
  10124. + return 0;
  10125. +}
  10126. +
  10127. +
  10128. +#ifdef DH_TEST_VECTORS
  10129. +
  10130. +static __u8 dh_a[] = {
  10131. + 0x44, 0x00, 0x51, 0xd6,
  10132. + 0xf0, 0xb5, 0x5e, 0xa9,
  10133. + 0x67, 0xab, 0x31, 0xc6,
  10134. + 0x8a, 0x8b, 0x5e, 0x37,
  10135. + 0xd9, 0x10, 0xda, 0xe0,
  10136. + 0xe2, 0xd4, 0x59, 0xa4,
  10137. + 0x86, 0x45, 0x9c, 0xaa,
  10138. + 0xdf, 0x36, 0x75, 0x16,
  10139. +};
  10140. +
  10141. +static __u8 dh_b[] = {
  10142. + 0x5d, 0xae, 0xc7, 0x86,
  10143. + 0x79, 0x80, 0xa3, 0x24,
  10144. + 0x8c, 0xe3, 0x57, 0x8f,
  10145. + 0xc7, 0x5f, 0x1b, 0x0f,
  10146. + 0x2d, 0xf8, 0x9d, 0x30,
  10147. + 0x6f, 0xa4, 0x52, 0xcd,
  10148. + 0xe0, 0x7a, 0x04, 0x8a,
  10149. + 0xde, 0xd9, 0x26, 0x56,
  10150. +};
  10151. +
  10152. +void dwc_run_dh_test_vectors(void *mem_ctx)
  10153. +{
  10154. + uint8_t pkd[384];
  10155. + uint8_t pkh[384];
  10156. + uint8_t hashd[32];
  10157. + uint8_t hashh[32];
  10158. + uint8_t ck[16];
  10159. + uint8_t kdk[32];
  10160. + char dd[5];
  10161. +
  10162. + DWC_PRINTF("\n\n\nDH_TEST_VECTORS\n\n");
  10163. +
  10164. + /* compute the PKd and SHA-256(PKd || Nd) */
  10165. + DWC_PRINTF("Computing PKd\n");
  10166. + dwc_dh_pk(mem_ctx, 2, dh_a, pkd, hashd);
  10167. +
  10168. + /* compute the PKd and SHA-256(PKh || Nd) */
  10169. + DWC_PRINTF("Computing PKh\n");
  10170. + dwc_dh_pk(mem_ctx, 2, dh_b, pkh, hashh);
  10171. +
  10172. + /* compute the dhkey */
  10173. + dwc_dh_derive_keys(mem_ctx, 2, pkh, pkd, dh_a, 0, dd, ck, kdk);
  10174. +}
  10175. +#endif /* DH_TEST_VECTORS */
  10176. +
  10177. +#endif /* !CONFIG_MACH_IPMATE */
  10178. +
  10179. +#endif /* DWC_CRYPTOLIB */
  10180. --- /dev/null
  10181. +++ b/drivers/usb/host/dwc_common_port/dwc_dh.h
  10182. @@ -0,0 +1,106 @@
  10183. +/* =========================================================================
  10184. + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.h $
  10185. + * $Revision: #4 $
  10186. + * $Date: 2010/09/28 $
  10187. + * $Change: 1596182 $
  10188. + *
  10189. + * Synopsys Portability Library Software and documentation
  10190. + * (hereinafter, "Software") is an Unsupported proprietary work of
  10191. + * Synopsys, Inc. unless otherwise expressly agreed to in writing
  10192. + * between Synopsys and you.
  10193. + *
  10194. + * The Software IS NOT an item of Licensed Software or Licensed Product
  10195. + * under any End User Software License Agreement or Agreement for
  10196. + * Licensed Product with Synopsys or any supplement thereto. You are
  10197. + * permitted to use and redistribute this Software in source and binary
  10198. + * forms, with or without modification, provided that redistributions
  10199. + * of source code must retain this notice. You may not view, use,
  10200. + * disclose, copy or distribute this file or any information contained
  10201. + * herein except pursuant to this license grant from Synopsys. If you
  10202. + * do not agree with this notice, including the disclaimer below, then
  10203. + * you are not authorized to use the Software.
  10204. + *
  10205. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
  10206. + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  10207. + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  10208. + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
  10209. + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  10210. + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  10211. + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  10212. + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  10213. + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  10214. + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  10215. + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  10216. + * DAMAGE.
  10217. + * ========================================================================= */
  10218. +#ifndef _DWC_DH_H_
  10219. +#define _DWC_DH_H_
  10220. +
  10221. +#ifdef __cplusplus
  10222. +extern "C" {
  10223. +#endif
  10224. +
  10225. +#include "dwc_os.h"
  10226. +
  10227. +/** @file
  10228. + *
  10229. + * This file defines the common functions on device and host for performing
  10230. + * numeric association as defined in the WUSB spec. They are only to be
  10231. + * used internally by the DWC UWB modules. */
  10232. +
  10233. +extern int dwc_dh_sha256(uint8_t *message, uint32_t len, uint8_t *out);
  10234. +extern int dwc_dh_hmac_sha256(uint8_t *message, uint32_t messagelen,
  10235. + uint8_t *key, uint32_t keylen,
  10236. + uint8_t *out);
  10237. +extern int dwc_dh_modpow(void *mem_ctx, void *num, uint32_t num_len,
  10238. + void *exp, uint32_t exp_len,
  10239. + void *mod, uint32_t mod_len,
  10240. + void *out);
  10241. +
  10242. +/** Computes PKD or PKH, and SHA-256(PKd || Nd)
  10243. + *
  10244. + * PK = g^exp mod p.
  10245. + *
  10246. + * Input:
  10247. + * Nd = Number of digits on the device.
  10248. + *
  10249. + * Output:
  10250. + * exp = A 32-byte buffer to be filled with a randomly generated number.
  10251. + * used as either A or B.
  10252. + * pk = A 384-byte buffer to be filled with the PKH or PKD.
  10253. + * hash = A 32-byte buffer to be filled with SHA-256(PK || ND).
  10254. + */
  10255. +extern int dwc_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pkd, uint8_t *hash);
  10256. +
  10257. +/** Computes the DHKEY, and VD.
  10258. + *
  10259. + * If called from host, then it will comput DHKEY=PKD^exp % p.
  10260. + * If called from device, then it will comput DHKEY=PKH^exp % p.
  10261. + *
  10262. + * Input:
  10263. + * pkd = The PKD value.
  10264. + * pkh = The PKH value.
  10265. + * exp = The A value (if device) or B value (if host) generated in dwc_wudev_dh_pk.
  10266. + * is_host = Set to non zero if a WUSB host is calling this function.
  10267. + *
  10268. + * Output:
  10269. +
  10270. + * dd = A pointer to an buffer to be set to the displayed digits string to be shown
  10271. + * to the user. This buffer should be at 5 bytes long to hold 4 digits plus a
  10272. + * null termination character. This buffer can be used directly for display.
  10273. + * ck = A 16-byte buffer to be filled with the CK.
  10274. + * kdk = A 32-byte buffer to be filled with the KDK.
  10275. + */
  10276. +extern int dwc_dh_derive_keys(void *mem_ctx, uint8_t nd, uint8_t *pkh, uint8_t *pkd,
  10277. + uint8_t *exp, int is_host,
  10278. + char *dd, uint8_t *ck, uint8_t *kdk);
  10279. +
  10280. +#ifdef DH_TEST_VECTORS
  10281. +extern void dwc_run_dh_test_vectors(void);
  10282. +#endif
  10283. +
  10284. +#ifdef __cplusplus
  10285. +}
  10286. +#endif
  10287. +
  10288. +#endif /* _DWC_DH_H_ */
  10289. --- /dev/null
  10290. +++ b/drivers/usb/host/dwc_common_port/dwc_list.h
  10291. @@ -0,0 +1,594 @@
  10292. +/* $OpenBSD: queue.h,v 1.26 2004/05/04 16:59:32 grange Exp $ */
  10293. +/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
  10294. +
  10295. +/*
  10296. + * Copyright (c) 1991, 1993
  10297. + * The Regents of the University of California. All rights reserved.
  10298. + *
  10299. + * Redistribution and use in source and binary forms, with or without
  10300. + * modification, are permitted provided that the following conditions
  10301. + * are met:
  10302. + * 1. Redistributions of source code must retain the above copyright
  10303. + * notice, this list of conditions and the following disclaimer.
  10304. + * 2. Redistributions in binary form must reproduce the above copyright
  10305. + * notice, this list of conditions and the following disclaimer in the
  10306. + * documentation and/or other materials provided with the distribution.
  10307. + * 3. Neither the name of the University nor the names of its contributors
  10308. + * may be used to endorse or promote products derived from this software
  10309. + * without specific prior written permission.
  10310. + *
  10311. + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  10312. + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  10313. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  10314. + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  10315. + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  10316. + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  10317. + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  10318. + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  10319. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  10320. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  10321. + * SUCH DAMAGE.
  10322. + *
  10323. + * @(#)queue.h 8.5 (Berkeley) 8/20/94
  10324. + */
  10325. +
  10326. +#ifndef _DWC_LIST_H_
  10327. +#define _DWC_LIST_H_
  10328. +
  10329. +#ifdef __cplusplus
  10330. +extern "C" {
  10331. +#endif
  10332. +
  10333. +/** @file
  10334. + *
  10335. + * This file defines linked list operations. It is derived from BSD with
  10336. + * only the MACRO names being prefixed with DWC_. This is because a few of
  10337. + * these names conflict with those on Linux. For documentation on use, see the
  10338. + * inline comments in the source code. The original license for this source
  10339. + * code applies and is preserved in the dwc_list.h source file.
  10340. + */
  10341. +
  10342. +/*
  10343. + * This file defines five types of data structures: singly-linked lists,
  10344. + * lists, simple queues, tail queues, and circular queues.
  10345. + *
  10346. + *
  10347. + * A singly-linked list is headed by a single forward pointer. The elements
  10348. + * are singly linked for minimum space and pointer manipulation overhead at
  10349. + * the expense of O(n) removal for arbitrary elements. New elements can be
  10350. + * added to the list after an existing element or at the head of the list.
  10351. + * Elements being removed from the head of the list should use the explicit
  10352. + * macro for this purpose for optimum efficiency. A singly-linked list may
  10353. + * only be traversed in the forward direction. Singly-linked lists are ideal
  10354. + * for applications with large datasets and few or no removals or for
  10355. + * implementing a LIFO queue.
  10356. + *
  10357. + * A list is headed by a single forward pointer (or an array of forward
  10358. + * pointers for a hash table header). The elements are doubly linked
  10359. + * so that an arbitrary element can be removed without a need to
  10360. + * traverse the list. New elements can be added to the list before
  10361. + * or after an existing element or at the head of the list. A list
  10362. + * may only be traversed in the forward direction.
  10363. + *
  10364. + * A simple queue is headed by a pair of pointers, one the head of the
  10365. + * list and the other to the tail of the list. The elements are singly
  10366. + * linked to save space, so elements can only be removed from the
  10367. + * head of the list. New elements can be added to the list before or after
  10368. + * an existing element, at the head of the list, or at the end of the
  10369. + * list. A simple queue may only be traversed in the forward direction.
  10370. + *
  10371. + * A tail queue is headed by a pair of pointers, one to the head of the
  10372. + * list and the other to the tail of the list. The elements are doubly
  10373. + * linked so that an arbitrary element can be removed without a need to
  10374. + * traverse the list. New elements can be added to the list before or
  10375. + * after an existing element, at the head of the list, or at the end of
  10376. + * the list. A tail queue may be traversed in either direction.
  10377. + *
  10378. + * A circle queue is headed by a pair of pointers, one to the head of the
  10379. + * list and the other to the tail of the list. The elements are doubly
  10380. + * linked so that an arbitrary element can be removed without a need to
  10381. + * traverse the list. New elements can be added to the list before or after
  10382. + * an existing element, at the head of the list, or at the end of the list.
  10383. + * A circle queue may be traversed in either direction, but has a more
  10384. + * complex end of list detection.
  10385. + *
  10386. + * For details on the use of these macros, see the queue(3) manual page.
  10387. + */
  10388. +
  10389. +/*
  10390. + * Double-linked List.
  10391. + */
  10392. +
  10393. +typedef struct dwc_list_link {
  10394. + struct dwc_list_link *next;
  10395. + struct dwc_list_link *prev;
  10396. +} dwc_list_link_t;
  10397. +
  10398. +#define DWC_LIST_INIT(link) do { \
  10399. + (link)->next = (link); \
  10400. + (link)->prev = (link); \
  10401. +} while (0)
  10402. +
  10403. +#define DWC_LIST_FIRST(link) ((link)->next)
  10404. +#define DWC_LIST_LAST(link) ((link)->prev)
  10405. +#define DWC_LIST_END(link) (link)
  10406. +#define DWC_LIST_NEXT(link) ((link)->next)
  10407. +#define DWC_LIST_PREV(link) ((link)->prev)
  10408. +#define DWC_LIST_EMPTY(link) \
  10409. + (DWC_LIST_FIRST(link) == DWC_LIST_END(link))
  10410. +#define DWC_LIST_ENTRY(link, type, field) \
  10411. + (type *)((uint8_t *)(link) - (size_t)(&((type *)0)->field))
  10412. +
  10413. +#if 0
  10414. +#define DWC_LIST_INSERT_HEAD(list, link) do { \
  10415. + (link)->next = (list)->next; \
  10416. + (link)->prev = (list); \
  10417. + (list)->next->prev = (link); \
  10418. + (list)->next = (link); \
  10419. +} while (0)
  10420. +
  10421. +#define DWC_LIST_INSERT_TAIL(list, link) do { \
  10422. + (link)->next = (list); \
  10423. + (link)->prev = (list)->prev; \
  10424. + (list)->prev->next = (link); \
  10425. + (list)->prev = (link); \
  10426. +} while (0)
  10427. +#else
  10428. +#define DWC_LIST_INSERT_HEAD(list, link) do { \
  10429. + dwc_list_link_t *__next__ = (list)->next; \
  10430. + __next__->prev = (link); \
  10431. + (link)->next = __next__; \
  10432. + (link)->prev = (list); \
  10433. + (list)->next = (link); \
  10434. +} while (0)
  10435. +
  10436. +#define DWC_LIST_INSERT_TAIL(list, link) do { \
  10437. + dwc_list_link_t *__prev__ = (list)->prev; \
  10438. + (list)->prev = (link); \
  10439. + (link)->next = (list); \
  10440. + (link)->prev = __prev__; \
  10441. + __prev__->next = (link); \
  10442. +} while (0)
  10443. +#endif
  10444. +
  10445. +#if 0
  10446. +static inline void __list_add(struct list_head *new,
  10447. + struct list_head *prev,
  10448. + struct list_head *next)
  10449. +{
  10450. + next->prev = new;
  10451. + new->next = next;
  10452. + new->prev = prev;
  10453. + prev->next = new;
  10454. +}
  10455. +
  10456. +static inline void list_add(struct list_head *new, struct list_head *head)
  10457. +{
  10458. + __list_add(new, head, head->next);
  10459. +}
  10460. +
  10461. +static inline void list_add_tail(struct list_head *new, struct list_head *head)
  10462. +{
  10463. + __list_add(new, head->prev, head);
  10464. +}
  10465. +
  10466. +static inline void __list_del(struct list_head * prev, struct list_head * next)
  10467. +{
  10468. + next->prev = prev;
  10469. + prev->next = next;
  10470. +}
  10471. +
  10472. +static inline void list_del(struct list_head *entry)
  10473. +{
  10474. + __list_del(entry->prev, entry->next);
  10475. + entry->next = LIST_POISON1;
  10476. + entry->prev = LIST_POISON2;
  10477. +}
  10478. +#endif
  10479. +
  10480. +#define DWC_LIST_REMOVE(link) do { \
  10481. + (link)->next->prev = (link)->prev; \
  10482. + (link)->prev->next = (link)->next; \
  10483. +} while (0)
  10484. +
  10485. +#define DWC_LIST_REMOVE_INIT(link) do { \
  10486. + DWC_LIST_REMOVE(link); \
  10487. + DWC_LIST_INIT(link); \
  10488. +} while (0)
  10489. +
  10490. +#define DWC_LIST_MOVE_HEAD(list, link) do { \
  10491. + DWC_LIST_REMOVE(link); \
  10492. + DWC_LIST_INSERT_HEAD(list, link); \
  10493. +} while (0)
  10494. +
  10495. +#define DWC_LIST_MOVE_TAIL(list, link) do { \
  10496. + DWC_LIST_REMOVE(link); \
  10497. + DWC_LIST_INSERT_TAIL(list, link); \
  10498. +} while (0)
  10499. +
  10500. +#define DWC_LIST_FOREACH(var, list) \
  10501. + for((var) = DWC_LIST_FIRST(list); \
  10502. + (var) != DWC_LIST_END(list); \
  10503. + (var) = DWC_LIST_NEXT(var))
  10504. +
  10505. +#define DWC_LIST_FOREACH_SAFE(var, var2, list) \
  10506. + for((var) = DWC_LIST_FIRST(list), (var2) = DWC_LIST_NEXT(var); \
  10507. + (var) != DWC_LIST_END(list); \
  10508. + (var) = (var2), (var2) = DWC_LIST_NEXT(var2))
  10509. +
  10510. +#define DWC_LIST_FOREACH_REVERSE(var, list) \
  10511. + for((var) = DWC_LIST_LAST(list); \
  10512. + (var) != DWC_LIST_END(list); \
  10513. + (var) = DWC_LIST_PREV(var))
  10514. +
  10515. +/*
  10516. + * Singly-linked List definitions.
  10517. + */
  10518. +#define DWC_SLIST_HEAD(name, type) \
  10519. +struct name { \
  10520. + struct type *slh_first; /* first element */ \
  10521. +}
  10522. +
  10523. +#define DWC_SLIST_HEAD_INITIALIZER(head) \
  10524. + { NULL }
  10525. +
  10526. +#define DWC_SLIST_ENTRY(type) \
  10527. +struct { \
  10528. + struct type *sle_next; /* next element */ \
  10529. +}
  10530. +
  10531. +/*
  10532. + * Singly-linked List access methods.
  10533. + */
  10534. +#define DWC_SLIST_FIRST(head) ((head)->slh_first)
  10535. +#define DWC_SLIST_END(head) NULL
  10536. +#define DWC_SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
  10537. +#define DWC_SLIST_NEXT(elm, field) ((elm)->field.sle_next)
  10538. +
  10539. +#define DWC_SLIST_FOREACH(var, head, field) \
  10540. + for((var) = SLIST_FIRST(head); \
  10541. + (var) != SLIST_END(head); \
  10542. + (var) = SLIST_NEXT(var, field))
  10543. +
  10544. +#define DWC_SLIST_FOREACH_PREVPTR(var, varp, head, field) \
  10545. + for((varp) = &SLIST_FIRST((head)); \
  10546. + ((var) = *(varp)) != SLIST_END(head); \
  10547. + (varp) = &SLIST_NEXT((var), field))
  10548. +
  10549. +/*
  10550. + * Singly-linked List functions.
  10551. + */
  10552. +#define DWC_SLIST_INIT(head) { \
  10553. + SLIST_FIRST(head) = SLIST_END(head); \
  10554. +}
  10555. +
  10556. +#define DWC_SLIST_INSERT_AFTER(slistelm, elm, field) do { \
  10557. + (elm)->field.sle_next = (slistelm)->field.sle_next; \
  10558. + (slistelm)->field.sle_next = (elm); \
  10559. +} while (0)
  10560. +
  10561. +#define DWC_SLIST_INSERT_HEAD(head, elm, field) do { \
  10562. + (elm)->field.sle_next = (head)->slh_first; \
  10563. + (head)->slh_first = (elm); \
  10564. +} while (0)
  10565. +
  10566. +#define DWC_SLIST_REMOVE_NEXT(head, elm, field) do { \
  10567. + (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \
  10568. +} while (0)
  10569. +
  10570. +#define DWC_SLIST_REMOVE_HEAD(head, field) do { \
  10571. + (head)->slh_first = (head)->slh_first->field.sle_next; \
  10572. +} while (0)
  10573. +
  10574. +#define DWC_SLIST_REMOVE(head, elm, type, field) do { \
  10575. + if ((head)->slh_first == (elm)) { \
  10576. + SLIST_REMOVE_HEAD((head), field); \
  10577. + } \
  10578. + else { \
  10579. + struct type *curelm = (head)->slh_first; \
  10580. + while( curelm->field.sle_next != (elm) ) \
  10581. + curelm = curelm->field.sle_next; \
  10582. + curelm->field.sle_next = \
  10583. + curelm->field.sle_next->field.sle_next; \
  10584. + } \
  10585. +} while (0)
  10586. +
  10587. +/*
  10588. + * Simple queue definitions.
  10589. + */
  10590. +#define DWC_SIMPLEQ_HEAD(name, type) \
  10591. +struct name { \
  10592. + struct type *sqh_first; /* first element */ \
  10593. + struct type **sqh_last; /* addr of last next element */ \
  10594. +}
  10595. +
  10596. +#define DWC_SIMPLEQ_HEAD_INITIALIZER(head) \
  10597. + { NULL, &(head).sqh_first }
  10598. +
  10599. +#define DWC_SIMPLEQ_ENTRY(type) \
  10600. +struct { \
  10601. + struct type *sqe_next; /* next element */ \
  10602. +}
  10603. +
  10604. +/*
  10605. + * Simple queue access methods.
  10606. + */
  10607. +#define DWC_SIMPLEQ_FIRST(head) ((head)->sqh_first)
  10608. +#define DWC_SIMPLEQ_END(head) NULL
  10609. +#define DWC_SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
  10610. +#define DWC_SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
  10611. +
  10612. +#define DWC_SIMPLEQ_FOREACH(var, head, field) \
  10613. + for((var) = SIMPLEQ_FIRST(head); \
  10614. + (var) != SIMPLEQ_END(head); \
  10615. + (var) = SIMPLEQ_NEXT(var, field))
  10616. +
  10617. +/*
  10618. + * Simple queue functions.
  10619. + */
  10620. +#define DWC_SIMPLEQ_INIT(head) do { \
  10621. + (head)->sqh_first = NULL; \
  10622. + (head)->sqh_last = &(head)->sqh_first; \
  10623. +} while (0)
  10624. +
  10625. +#define DWC_SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
  10626. + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
  10627. + (head)->sqh_last = &(elm)->field.sqe_next; \
  10628. + (head)->sqh_first = (elm); \
  10629. +} while (0)
  10630. +
  10631. +#define DWC_SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
  10632. + (elm)->field.sqe_next = NULL; \
  10633. + *(head)->sqh_last = (elm); \
  10634. + (head)->sqh_last = &(elm)->field.sqe_next; \
  10635. +} while (0)
  10636. +
  10637. +#define DWC_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
  10638. + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
  10639. + (head)->sqh_last = &(elm)->field.sqe_next; \
  10640. + (listelm)->field.sqe_next = (elm); \
  10641. +} while (0)
  10642. +
  10643. +#define DWC_SIMPLEQ_REMOVE_HEAD(head, field) do { \
  10644. + if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
  10645. + (head)->sqh_last = &(head)->sqh_first; \
  10646. +} while (0)
  10647. +
  10648. +/*
  10649. + * Tail queue definitions.
  10650. + */
  10651. +#define DWC_TAILQ_HEAD(name, type) \
  10652. +struct name { \
  10653. + struct type *tqh_first; /* first element */ \
  10654. + struct type **tqh_last; /* addr of last next element */ \
  10655. +}
  10656. +
  10657. +#define DWC_TAILQ_HEAD_INITIALIZER(head) \
  10658. + { NULL, &(head).tqh_first }
  10659. +
  10660. +#define DWC_TAILQ_ENTRY(type) \
  10661. +struct { \
  10662. + struct type *tqe_next; /* next element */ \
  10663. + struct type **tqe_prev; /* address of previous next element */ \
  10664. +}
  10665. +
  10666. +/*
  10667. + * tail queue access methods
  10668. + */
  10669. +#define DWC_TAILQ_FIRST(head) ((head)->tqh_first)
  10670. +#define DWC_TAILQ_END(head) NULL
  10671. +#define DWC_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
  10672. +#define DWC_TAILQ_LAST(head, headname) \
  10673. + (*(((struct headname *)((head)->tqh_last))->tqh_last))
  10674. +/* XXX */
  10675. +#define DWC_TAILQ_PREV(elm, headname, field) \
  10676. + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
  10677. +#define DWC_TAILQ_EMPTY(head) \
  10678. + (TAILQ_FIRST(head) == TAILQ_END(head))
  10679. +
  10680. +#define DWC_TAILQ_FOREACH(var, head, field) \
  10681. + for((var) = TAILQ_FIRST(head); \
  10682. + (var) != TAILQ_END(head); \
  10683. + (var) = TAILQ_NEXT(var, field))
  10684. +
  10685. +#define DWC_TAILQ_FOREACH_REVERSE(var, head, headname, field) \
  10686. + for((var) = TAILQ_LAST(head, headname); \
  10687. + (var) != TAILQ_END(head); \
  10688. + (var) = TAILQ_PREV(var, headname, field))
  10689. +
  10690. +/*
  10691. + * Tail queue functions.
  10692. + */
  10693. +#define DWC_TAILQ_INIT(head) do { \
  10694. + (head)->tqh_first = NULL; \
  10695. + (head)->tqh_last = &(head)->tqh_first; \
  10696. +} while (0)
  10697. +
  10698. +#define DWC_TAILQ_INSERT_HEAD(head, elm, field) do { \
  10699. + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
  10700. + (head)->tqh_first->field.tqe_prev = \
  10701. + &(elm)->field.tqe_next; \
  10702. + else \
  10703. + (head)->tqh_last = &(elm)->field.tqe_next; \
  10704. + (head)->tqh_first = (elm); \
  10705. + (elm)->field.tqe_prev = &(head)->tqh_first; \
  10706. +} while (0)
  10707. +
  10708. +#define DWC_TAILQ_INSERT_TAIL(head, elm, field) do { \
  10709. + (elm)->field.tqe_next = NULL; \
  10710. + (elm)->field.tqe_prev = (head)->tqh_last; \
  10711. + *(head)->tqh_last = (elm); \
  10712. + (head)->tqh_last = &(elm)->field.tqe_next; \
  10713. +} while (0)
  10714. +
  10715. +#define DWC_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
  10716. + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
  10717. + (elm)->field.tqe_next->field.tqe_prev = \
  10718. + &(elm)->field.tqe_next; \
  10719. + else \
  10720. + (head)->tqh_last = &(elm)->field.tqe_next; \
  10721. + (listelm)->field.tqe_next = (elm); \
  10722. + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
  10723. +} while (0)
  10724. +
  10725. +#define DWC_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
  10726. + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
  10727. + (elm)->field.tqe_next = (listelm); \
  10728. + *(listelm)->field.tqe_prev = (elm); \
  10729. + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
  10730. +} while (0)
  10731. +
  10732. +#define DWC_TAILQ_REMOVE(head, elm, field) do { \
  10733. + if (((elm)->field.tqe_next) != NULL) \
  10734. + (elm)->field.tqe_next->field.tqe_prev = \
  10735. + (elm)->field.tqe_prev; \
  10736. + else \
  10737. + (head)->tqh_last = (elm)->field.tqe_prev; \
  10738. + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
  10739. +} while (0)
  10740. +
  10741. +#define DWC_TAILQ_REPLACE(head, elm, elm2, field) do { \
  10742. + if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
  10743. + (elm2)->field.tqe_next->field.tqe_prev = \
  10744. + &(elm2)->field.tqe_next; \
  10745. + else \
  10746. + (head)->tqh_last = &(elm2)->field.tqe_next; \
  10747. + (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
  10748. + *(elm2)->field.tqe_prev = (elm2); \
  10749. +} while (0)
  10750. +
  10751. +/*
  10752. + * Circular queue definitions.
  10753. + */
  10754. +#define DWC_CIRCLEQ_HEAD(name, type) \
  10755. +struct name { \
  10756. + struct type *cqh_first; /* first element */ \
  10757. + struct type *cqh_last; /* last element */ \
  10758. +}
  10759. +
  10760. +#define DWC_CIRCLEQ_HEAD_INITIALIZER(head) \
  10761. + { DWC_CIRCLEQ_END(&head), DWC_CIRCLEQ_END(&head) }
  10762. +
  10763. +#define DWC_CIRCLEQ_ENTRY(type) \
  10764. +struct { \
  10765. + struct type *cqe_next; /* next element */ \
  10766. + struct type *cqe_prev; /* previous element */ \
  10767. +}
  10768. +
  10769. +/*
  10770. + * Circular queue access methods
  10771. + */
  10772. +#define DWC_CIRCLEQ_FIRST(head) ((head)->cqh_first)
  10773. +#define DWC_CIRCLEQ_LAST(head) ((head)->cqh_last)
  10774. +#define DWC_CIRCLEQ_END(head) ((void *)(head))
  10775. +#define DWC_CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
  10776. +#define DWC_CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
  10777. +#define DWC_CIRCLEQ_EMPTY(head) \
  10778. + (DWC_CIRCLEQ_FIRST(head) == DWC_CIRCLEQ_END(head))
  10779. +
  10780. +#define DWC_CIRCLEQ_EMPTY_ENTRY(elm, field) (((elm)->field.cqe_next == NULL) && ((elm)->field.cqe_prev == NULL))
  10781. +
  10782. +#define DWC_CIRCLEQ_FOREACH(var, head, field) \
  10783. + for((var) = DWC_CIRCLEQ_FIRST(head); \
  10784. + (var) != DWC_CIRCLEQ_END(head); \
  10785. + (var) = DWC_CIRCLEQ_NEXT(var, field))
  10786. +
  10787. +#define DWC_CIRCLEQ_FOREACH_SAFE(var, var2, head, field) \
  10788. + for((var) = DWC_CIRCLEQ_FIRST(head), var2 = DWC_CIRCLEQ_NEXT(var, field); \
  10789. + (var) != DWC_CIRCLEQ_END(head); \
  10790. + (var) = var2, var2 = DWC_CIRCLEQ_NEXT(var, field))
  10791. +
  10792. +#define DWC_CIRCLEQ_FOREACH_REVERSE(var, head, field) \
  10793. + for((var) = DWC_CIRCLEQ_LAST(head); \
  10794. + (var) != DWC_CIRCLEQ_END(head); \
  10795. + (var) = DWC_CIRCLEQ_PREV(var, field))
  10796. +
  10797. +/*
  10798. + * Circular queue functions.
  10799. + */
  10800. +#define DWC_CIRCLEQ_INIT(head) do { \
  10801. + (head)->cqh_first = DWC_CIRCLEQ_END(head); \
  10802. + (head)->cqh_last = DWC_CIRCLEQ_END(head); \
  10803. +} while (0)
  10804. +
  10805. +#define DWC_CIRCLEQ_INIT_ENTRY(elm, field) do { \
  10806. + (elm)->field.cqe_next = NULL; \
  10807. + (elm)->field.cqe_prev = NULL; \
  10808. +} while (0)
  10809. +
  10810. +#define DWC_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
  10811. + (elm)->field.cqe_next = (listelm)->field.cqe_next; \
  10812. + (elm)->field.cqe_prev = (listelm); \
  10813. + if ((listelm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \
  10814. + (head)->cqh_last = (elm); \
  10815. + else \
  10816. + (listelm)->field.cqe_next->field.cqe_prev = (elm); \
  10817. + (listelm)->field.cqe_next = (elm); \
  10818. +} while (0)
  10819. +
  10820. +#define DWC_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
  10821. + (elm)->field.cqe_next = (listelm); \
  10822. + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
  10823. + if ((listelm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \
  10824. + (head)->cqh_first = (elm); \
  10825. + else \
  10826. + (listelm)->field.cqe_prev->field.cqe_next = (elm); \
  10827. + (listelm)->field.cqe_prev = (elm); \
  10828. +} while (0)
  10829. +
  10830. +#define DWC_CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
  10831. + (elm)->field.cqe_next = (head)->cqh_first; \
  10832. + (elm)->field.cqe_prev = DWC_CIRCLEQ_END(head); \
  10833. + if ((head)->cqh_last == DWC_CIRCLEQ_END(head)) \
  10834. + (head)->cqh_last = (elm); \
  10835. + else \
  10836. + (head)->cqh_first->field.cqe_prev = (elm); \
  10837. + (head)->cqh_first = (elm); \
  10838. +} while (0)
  10839. +
  10840. +#define DWC_CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
  10841. + (elm)->field.cqe_next = DWC_CIRCLEQ_END(head); \
  10842. + (elm)->field.cqe_prev = (head)->cqh_last; \
  10843. + if ((head)->cqh_first == DWC_CIRCLEQ_END(head)) \
  10844. + (head)->cqh_first = (elm); \
  10845. + else \
  10846. + (head)->cqh_last->field.cqe_next = (elm); \
  10847. + (head)->cqh_last = (elm); \
  10848. +} while (0)
  10849. +
  10850. +#define DWC_CIRCLEQ_REMOVE(head, elm, field) do { \
  10851. + if ((elm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \
  10852. + (head)->cqh_last = (elm)->field.cqe_prev; \
  10853. + else \
  10854. + (elm)->field.cqe_next->field.cqe_prev = \
  10855. + (elm)->field.cqe_prev; \
  10856. + if ((elm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \
  10857. + (head)->cqh_first = (elm)->field.cqe_next; \
  10858. + else \
  10859. + (elm)->field.cqe_prev->field.cqe_next = \
  10860. + (elm)->field.cqe_next; \
  10861. +} while (0)
  10862. +
  10863. +#define DWC_CIRCLEQ_REMOVE_INIT(head, elm, field) do { \
  10864. + DWC_CIRCLEQ_REMOVE(head, elm, field); \
  10865. + DWC_CIRCLEQ_INIT_ENTRY(elm, field); \
  10866. +} while (0)
  10867. +
  10868. +#define DWC_CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
  10869. + if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
  10870. + DWC_CIRCLEQ_END(head)) \
  10871. + (head).cqh_last = (elm2); \
  10872. + else \
  10873. + (elm2)->field.cqe_next->field.cqe_prev = (elm2); \
  10874. + if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
  10875. + DWC_CIRCLEQ_END(head)) \
  10876. + (head).cqh_first = (elm2); \
  10877. + else \
  10878. + (elm2)->field.cqe_prev->field.cqe_next = (elm2); \
  10879. +} while (0)
  10880. +
  10881. +#ifdef __cplusplus
  10882. +}
  10883. +#endif
  10884. +
  10885. +#endif /* _DWC_LIST_H_ */
  10886. --- /dev/null
  10887. +++ b/drivers/usb/host/dwc_common_port/dwc_mem.c
  10888. @@ -0,0 +1,245 @@
  10889. +/* Memory Debugging */
  10890. +#ifdef DWC_DEBUG_MEMORY
  10891. +
  10892. +#include "dwc_os.h"
  10893. +#include "dwc_list.h"
  10894. +
  10895. +struct allocation {
  10896. + void *addr;
  10897. + void *ctx;
  10898. + char *func;
  10899. + int line;
  10900. + uint32_t size;
  10901. + int dma;
  10902. + DWC_CIRCLEQ_ENTRY(allocation) entry;
  10903. +};
  10904. +
  10905. +DWC_CIRCLEQ_HEAD(allocation_queue, allocation);
  10906. +
  10907. +struct allocation_manager {
  10908. + void *mem_ctx;
  10909. + struct allocation_queue allocations;
  10910. +
  10911. + /* statistics */
  10912. + int num;
  10913. + int num_freed;
  10914. + int num_active;
  10915. + uint32_t total;
  10916. + uint32_t cur;
  10917. + uint32_t max;
  10918. +};
  10919. +
  10920. +static struct allocation_manager *manager = NULL;
  10921. +
  10922. +static int add_allocation(void *ctx, uint32_t size, char const *func, int line, void *addr,
  10923. + int dma)
  10924. +{
  10925. + struct allocation *a;
  10926. +
  10927. + DWC_ASSERT(manager != NULL, "manager not allocated");
  10928. +
  10929. + a = __DWC_ALLOC_ATOMIC(manager->mem_ctx, sizeof(*a));
  10930. + if (!a) {
  10931. + return -DWC_E_NO_MEMORY;
  10932. + }
  10933. +
  10934. + a->func = __DWC_ALLOC_ATOMIC(manager->mem_ctx, DWC_STRLEN(func) + 1);
  10935. + if (!a->func) {
  10936. + __DWC_FREE(manager->mem_ctx, a);
  10937. + return -DWC_E_NO_MEMORY;
  10938. + }
  10939. +
  10940. + DWC_MEMCPY(a->func, func, DWC_STRLEN(func) + 1);
  10941. + a->addr = addr;
  10942. + a->ctx = ctx;
  10943. + a->line = line;
  10944. + a->size = size;
  10945. + a->dma = dma;
  10946. + DWC_CIRCLEQ_INSERT_TAIL(&manager->allocations, a, entry);
  10947. +
  10948. + /* Update stats */
  10949. + manager->num++;
  10950. + manager->num_active++;
  10951. + manager->total += size;
  10952. + manager->cur += size;
  10953. +
  10954. + if (manager->max < manager->cur) {
  10955. + manager->max = manager->cur;
  10956. + }
  10957. +
  10958. + return 0;
  10959. +}
  10960. +
  10961. +static struct allocation *find_allocation(void *ctx, void *addr)
  10962. +{
  10963. + struct allocation *a;
  10964. +
  10965. + DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
  10966. + if (a->ctx == ctx && a->addr == addr) {
  10967. + return a;
  10968. + }
  10969. + }
  10970. +
  10971. + return NULL;
  10972. +}
  10973. +
  10974. +static void free_allocation(void *ctx, void *addr, char const *func, int line)
  10975. +{
  10976. + struct allocation *a = find_allocation(ctx, addr);
  10977. +
  10978. + if (!a) {
  10979. + DWC_ASSERT(0,
  10980. + "Free of address %p that was never allocated or already freed %s:%d",
  10981. + addr, func, line);
  10982. + return;
  10983. + }
  10984. +
  10985. + DWC_CIRCLEQ_REMOVE(&manager->allocations, a, entry);
  10986. +
  10987. + manager->num_active--;
  10988. + manager->num_freed++;
  10989. + manager->cur -= a->size;
  10990. + __DWC_FREE(manager->mem_ctx, a->func);
  10991. + __DWC_FREE(manager->mem_ctx, a);
  10992. +}
  10993. +
  10994. +int dwc_memory_debug_start(void *mem_ctx)
  10995. +{
  10996. + DWC_ASSERT(manager == NULL, "Memory debugging has already started\n");
  10997. +
  10998. + if (manager) {
  10999. + return -DWC_E_BUSY;
  11000. + }
  11001. +
  11002. + manager = __DWC_ALLOC(mem_ctx, sizeof(*manager));
  11003. + if (!manager) {
  11004. + return -DWC_E_NO_MEMORY;
  11005. + }
  11006. +
  11007. + DWC_CIRCLEQ_INIT(&manager->allocations);
  11008. + manager->mem_ctx = mem_ctx;
  11009. + manager->num = 0;
  11010. + manager->num_freed = 0;
  11011. + manager->num_active = 0;
  11012. + manager->total = 0;
  11013. + manager->cur = 0;
  11014. + manager->max = 0;
  11015. +
  11016. + return 0;
  11017. +}
  11018. +
  11019. +void dwc_memory_debug_stop(void)
  11020. +{
  11021. + struct allocation *a;
  11022. +
  11023. + dwc_memory_debug_report();
  11024. +
  11025. + DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
  11026. + DWC_ERROR("Memory leaked from %s:%d\n", a->func, a->line);
  11027. + free_allocation(a->ctx, a->addr, NULL, -1);
  11028. + }
  11029. +
  11030. + __DWC_FREE(manager->mem_ctx, manager);
  11031. +}
  11032. +
  11033. +void dwc_memory_debug_report(void)
  11034. +{
  11035. + struct allocation *a;
  11036. +
  11037. + DWC_PRINTF("\n\n\n----------------- Memory Debugging Report -----------------\n\n");
  11038. + DWC_PRINTF("Num Allocations = %d\n", manager->num);
  11039. + DWC_PRINTF("Freed = %d\n", manager->num_freed);
  11040. + DWC_PRINTF("Active = %d\n", manager->num_active);
  11041. + DWC_PRINTF("Current Memory Used = %d\n", manager->cur);
  11042. + DWC_PRINTF("Total Memory Used = %d\n", manager->total);
  11043. + DWC_PRINTF("Maximum Memory Used at Once = %d\n", manager->max);
  11044. + DWC_PRINTF("Unfreed allocations:\n");
  11045. +
  11046. + DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
  11047. + DWC_PRINTF(" addr=%p, size=%d from %s:%d, DMA=%d\n",
  11048. + a->addr, a->size, a->func, a->line, a->dma);
  11049. + }
  11050. +}
  11051. +
  11052. +/* The replacement functions */
  11053. +void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line)
  11054. +{
  11055. + void *addr = __DWC_ALLOC(mem_ctx, size);
  11056. +
  11057. + if (!addr) {
  11058. + return NULL;
  11059. + }
  11060. +
  11061. + if (add_allocation(mem_ctx, size, func, line, addr, 0)) {
  11062. + __DWC_FREE(mem_ctx, addr);
  11063. + return NULL;
  11064. + }
  11065. +
  11066. + return addr;
  11067. +}
  11068. +
  11069. +void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func,
  11070. + int line)
  11071. +{
  11072. + void *addr = __DWC_ALLOC_ATOMIC(mem_ctx, size);
  11073. +
  11074. + if (!addr) {
  11075. + return NULL;
  11076. + }
  11077. +
  11078. + if (add_allocation(mem_ctx, size, func, line, addr, 0)) {
  11079. + __DWC_FREE(mem_ctx, addr);
  11080. + return NULL;
  11081. + }
  11082. +
  11083. + return addr;
  11084. +}
  11085. +
  11086. +void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line)
  11087. +{
  11088. + free_allocation(mem_ctx, addr, func, line);
  11089. + __DWC_FREE(mem_ctx, addr);
  11090. +}
  11091. +
  11092. +void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
  11093. + char const *func, int line)
  11094. +{
  11095. + void *addr = __DWC_DMA_ALLOC(dma_ctx, size, dma_addr);
  11096. +
  11097. + if (!addr) {
  11098. + return NULL;
  11099. + }
  11100. +
  11101. + if (add_allocation(dma_ctx, size, func, line, addr, 1)) {
  11102. + __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr);
  11103. + return NULL;
  11104. + }
  11105. +
  11106. + return addr;
  11107. +}
  11108. +
  11109. +void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size,
  11110. + dwc_dma_t *dma_addr, char const *func, int line)
  11111. +{
  11112. + void *addr = __DWC_DMA_ALLOC_ATOMIC(dma_ctx, size, dma_addr);
  11113. +
  11114. + if (!addr) {
  11115. + return NULL;
  11116. + }
  11117. +
  11118. + if (add_allocation(dma_ctx, size, func, line, addr, 1)) {
  11119. + __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr);
  11120. + return NULL;
  11121. + }
  11122. +
  11123. + return addr;
  11124. +}
  11125. +
  11126. +void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr,
  11127. + dwc_dma_t dma_addr, char const *func, int line)
  11128. +{
  11129. + free_allocation(dma_ctx, virt_addr, func, line);
  11130. + __DWC_DMA_FREE(dma_ctx, size, virt_addr, dma_addr);
  11131. +}
  11132. +
  11133. +#endif /* DWC_DEBUG_MEMORY */
  11134. --- /dev/null
  11135. +++ b/drivers/usb/host/dwc_common_port/dwc_modpow.c
  11136. @@ -0,0 +1,636 @@
  11137. +/* Bignum routines adapted from PUTTY sources. PuTTY copyright notice follows.
  11138. + *
  11139. + * PuTTY is copyright 1997-2007 Simon Tatham.
  11140. + *
  11141. + * Portions copyright Robert de Bath, Joris van Rantwijk, Delian
  11142. + * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
  11143. + * Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus
  11144. + * Kuhn, and CORE SDI S.A.
  11145. + *
  11146. + * Permission is hereby granted, free of charge, to any person
  11147. + * obtaining a copy of this software and associated documentation files
  11148. + * (the "Software"), to deal in the Software without restriction,
  11149. + * including without limitation the rights to use, copy, modify, merge,
  11150. + * publish, distribute, sublicense, and/or sell copies of the Software,
  11151. + * and to permit persons to whom the Software is furnished to do so,
  11152. + * subject to the following conditions:
  11153. + *
  11154. + * The above copyright notice and this permission notice shall be
  11155. + * included in all copies or substantial portions of the Software.
  11156. +
  11157. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  11158. + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  11159. + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  11160. + * NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
  11161. + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  11162. + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  11163. + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  11164. + *
  11165. + */
  11166. +#ifdef DWC_CRYPTOLIB
  11167. +
  11168. +#ifndef CONFIG_MACH_IPMATE
  11169. +
  11170. +#include "dwc_modpow.h"
  11171. +
  11172. +#define BIGNUM_INT_MASK 0xFFFFFFFFUL
  11173. +#define BIGNUM_TOP_BIT 0x80000000UL
  11174. +#define BIGNUM_INT_BITS 32
  11175. +
  11176. +
  11177. +static void *snmalloc(void *mem_ctx, size_t n, size_t size)
  11178. +{
  11179. + void *p;
  11180. + size *= n;
  11181. + if (size == 0) size = 1;
  11182. + p = dwc_alloc(mem_ctx, size);
  11183. + return p;
  11184. +}
  11185. +
  11186. +#define snewn(ctx, n, type) ((type *)snmalloc((ctx), (n), sizeof(type)))
  11187. +#define sfree dwc_free
  11188. +
  11189. +/*
  11190. + * Usage notes:
  11191. + * * Do not call the DIVMOD_WORD macro with expressions such as array
  11192. + * subscripts, as some implementations object to this (see below).
  11193. + * * Note that none of the division methods below will cope if the
  11194. + * quotient won't fit into BIGNUM_INT_BITS. Callers should be careful
  11195. + * to avoid this case.
  11196. + * If this condition occurs, in the case of the x86 DIV instruction,
  11197. + * an overflow exception will occur, which (according to a correspondent)
  11198. + * will manifest on Windows as something like
  11199. + * 0xC0000095: Integer overflow
  11200. + * The C variant won't give the right answer, either.
  11201. + */
  11202. +
  11203. +#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
  11204. +
  11205. +#if defined __GNUC__ && defined __i386__
  11206. +#define DIVMOD_WORD(q, r, hi, lo, w) \
  11207. + __asm__("div %2" : \
  11208. + "=d" (r), "=a" (q) : \
  11209. + "r" (w), "d" (hi), "a" (lo))
  11210. +#else
  11211. +#define DIVMOD_WORD(q, r, hi, lo, w) do { \
  11212. + BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
  11213. + q = n / w; \
  11214. + r = n % w; \
  11215. +} while (0)
  11216. +#endif
  11217. +
  11218. +// q = n / w;
  11219. +// r = n % w;
  11220. +
  11221. +#define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8)
  11222. +
  11223. +#define BIGNUM_INTERNAL
  11224. +
  11225. +static Bignum newbn(void *mem_ctx, int length)
  11226. +{
  11227. + Bignum b = snewn(mem_ctx, length + 1, BignumInt);
  11228. + //if (!b)
  11229. + //abort(); /* FIXME */
  11230. + DWC_MEMSET(b, 0, (length + 1) * sizeof(*b));
  11231. + b[0] = length;
  11232. + return b;
  11233. +}
  11234. +
  11235. +void freebn(void *mem_ctx, Bignum b)
  11236. +{
  11237. + /*
  11238. + * Burn the evidence, just in case.
  11239. + */
  11240. + DWC_MEMSET(b, 0, sizeof(b[0]) * (b[0] + 1));
  11241. + sfree(mem_ctx, b);
  11242. +}
  11243. +
  11244. +/*
  11245. + * Compute c = a * b.
  11246. + * Input is in the first len words of a and b.
  11247. + * Result is returned in the first 2*len words of c.
  11248. + */
  11249. +static void internal_mul(BignumInt *a, BignumInt *b,
  11250. + BignumInt *c, int len)
  11251. +{
  11252. + int i, j;
  11253. + BignumDblInt t;
  11254. +
  11255. + for (j = 0; j < 2 * len; j++)
  11256. + c[j] = 0;
  11257. +
  11258. + for (i = len - 1; i >= 0; i--) {
  11259. + t = 0;
  11260. + for (j = len - 1; j >= 0; j--) {
  11261. + t += MUL_WORD(a[i], (BignumDblInt) b[j]);
  11262. + t += (BignumDblInt) c[i + j + 1];
  11263. + c[i + j + 1] = (BignumInt) t;
  11264. + t = t >> BIGNUM_INT_BITS;
  11265. + }
  11266. + c[i] = (BignumInt) t;
  11267. + }
  11268. +}
  11269. +
  11270. +static void internal_add_shifted(BignumInt *number,
  11271. + unsigned n, int shift)
  11272. +{
  11273. + int word = 1 + (shift / BIGNUM_INT_BITS);
  11274. + int bshift = shift % BIGNUM_INT_BITS;
  11275. + BignumDblInt addend;
  11276. +
  11277. + addend = (BignumDblInt)n << bshift;
  11278. +
  11279. + while (addend) {
  11280. + addend += number[word];
  11281. + number[word] = (BignumInt) addend & BIGNUM_INT_MASK;
  11282. + addend >>= BIGNUM_INT_BITS;
  11283. + word++;
  11284. + }
  11285. +}
  11286. +
  11287. +/*
  11288. + * Compute a = a % m.
  11289. + * Input in first alen words of a and first mlen words of m.
  11290. + * Output in first alen words of a
  11291. + * (of which first alen-mlen words will be zero).
  11292. + * The MSW of m MUST have its high bit set.
  11293. + * Quotient is accumulated in the `quotient' array, which is a Bignum
  11294. + * rather than the internal bigendian format. Quotient parts are shifted
  11295. + * left by `qshift' before adding into quot.
  11296. + */
  11297. +static void internal_mod(BignumInt *a, int alen,
  11298. + BignumInt *m, int mlen,
  11299. + BignumInt *quot, int qshift)
  11300. +{
  11301. + BignumInt m0, m1;
  11302. + unsigned int h;
  11303. + int i, k;
  11304. +
  11305. + m0 = m[0];
  11306. + if (mlen > 1)
  11307. + m1 = m[1];
  11308. + else
  11309. + m1 = 0;
  11310. +
  11311. + for (i = 0; i <= alen - mlen; i++) {
  11312. + BignumDblInt t;
  11313. + unsigned int q, r, c, ai1;
  11314. +
  11315. + if (i == 0) {
  11316. + h = 0;
  11317. + } else {
  11318. + h = a[i - 1];
  11319. + a[i - 1] = 0;
  11320. + }
  11321. +
  11322. + if (i == alen - 1)
  11323. + ai1 = 0;
  11324. + else
  11325. + ai1 = a[i + 1];
  11326. +
  11327. + /* Find q = h:a[i] / m0 */
  11328. + if (h >= m0) {
  11329. + /*
  11330. + * Special case.
  11331. + *
  11332. + * To illustrate it, suppose a BignumInt is 8 bits, and
  11333. + * we are dividing (say) A1:23:45:67 by A1:B2:C3. Then
  11334. + * our initial division will be 0xA123 / 0xA1, which
  11335. + * will give a quotient of 0x100 and a divide overflow.
  11336. + * However, the invariants in this division algorithm
  11337. + * are not violated, since the full number A1:23:... is
  11338. + * _less_ than the quotient prefix A1:B2:... and so the
  11339. + * following correction loop would have sorted it out.
  11340. + *
  11341. + * In this situation we set q to be the largest
  11342. + * quotient we _can_ stomach (0xFF, of course).
  11343. + */
  11344. + q = BIGNUM_INT_MASK;
  11345. + } else {
  11346. + /* Macro doesn't want an array subscript expression passed
  11347. + * into it (see definition), so use a temporary. */
  11348. + BignumInt tmplo = a[i];
  11349. + DIVMOD_WORD(q, r, h, tmplo, m0);
  11350. +
  11351. + /* Refine our estimate of q by looking at
  11352. + h:a[i]:a[i+1] / m0:m1 */
  11353. + t = MUL_WORD(m1, q);
  11354. + if (t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) {
  11355. + q--;
  11356. + t -= m1;
  11357. + r = (r + m0) & BIGNUM_INT_MASK; /* overflow? */
  11358. + if (r >= (BignumDblInt) m0 &&
  11359. + t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) q--;
  11360. + }
  11361. + }
  11362. +
  11363. + /* Subtract q * m from a[i...] */
  11364. + c = 0;
  11365. + for (k = mlen - 1; k >= 0; k--) {
  11366. + t = MUL_WORD(q, m[k]);
  11367. + t += c;
  11368. + c = (unsigned)(t >> BIGNUM_INT_BITS);
  11369. + if ((BignumInt) t > a[i + k])
  11370. + c++;
  11371. + a[i + k] -= (BignumInt) t;
  11372. + }
  11373. +
  11374. + /* Add back m in case of borrow */
  11375. + if (c != h) {
  11376. + t = 0;
  11377. + for (k = mlen - 1; k >= 0; k--) {
  11378. + t += m[k];
  11379. + t += a[i + k];
  11380. + a[i + k] = (BignumInt) t;
  11381. + t = t >> BIGNUM_INT_BITS;
  11382. + }
  11383. + q--;
  11384. + }
  11385. + if (quot)
  11386. + internal_add_shifted(quot, q, qshift + BIGNUM_INT_BITS * (alen - mlen - i));
  11387. + }
  11388. +}
  11389. +
  11390. +/*
  11391. + * Compute p % mod.
  11392. + * The most significant word of mod MUST be non-zero.
  11393. + * We assume that the result array is the same size as the mod array.
  11394. + * We optionally write out a quotient if `quotient' is non-NULL.
  11395. + * We can avoid writing out the result if `result' is NULL.
  11396. + */
  11397. +void bigdivmod(void *mem_ctx, Bignum p, Bignum mod, Bignum result, Bignum quotient)
  11398. +{
  11399. + BignumInt *n, *m;
  11400. + int mshift;
  11401. + int plen, mlen, i, j;
  11402. +
  11403. + /* Allocate m of size mlen, copy mod to m */
  11404. + /* We use big endian internally */
  11405. + mlen = mod[0];
  11406. + m = snewn(mem_ctx, mlen, BignumInt);
  11407. + //if (!m)
  11408. + //abort(); /* FIXME */
  11409. + for (j = 0; j < mlen; j++)
  11410. + m[j] = mod[mod[0] - j];
  11411. +
  11412. + /* Shift m left to make msb bit set */
  11413. + for (mshift = 0; mshift < BIGNUM_INT_BITS-1; mshift++)
  11414. + if ((m[0] << mshift) & BIGNUM_TOP_BIT)
  11415. + break;
  11416. + if (mshift) {
  11417. + for (i = 0; i < mlen - 1; i++)
  11418. + m[i] = (m[i] << mshift) | (m[i + 1] >> (BIGNUM_INT_BITS - mshift));
  11419. + m[mlen - 1] = m[mlen - 1] << mshift;
  11420. + }
  11421. +
  11422. + plen = p[0];
  11423. + /* Ensure plen > mlen */
  11424. + if (plen <= mlen)
  11425. + plen = mlen + 1;
  11426. +
  11427. + /* Allocate n of size plen, copy p to n */
  11428. + n = snewn(mem_ctx, plen, BignumInt);
  11429. + //if (!n)
  11430. + //abort(); /* FIXME */
  11431. + for (j = 0; j < plen; j++)
  11432. + n[j] = 0;
  11433. + for (j = 1; j <= (int)p[0]; j++)
  11434. + n[plen - j] = p[j];
  11435. +
  11436. + /* Main computation */
  11437. + internal_mod(n, plen, m, mlen, quotient, mshift);
  11438. +
  11439. + /* Fixup result in case the modulus was shifted */
  11440. + if (mshift) {
  11441. + for (i = plen - mlen - 1; i < plen - 1; i++)
  11442. + n[i] = (n[i] << mshift) | (n[i + 1] >> (BIGNUM_INT_BITS - mshift));
  11443. + n[plen - 1] = n[plen - 1] << mshift;
  11444. + internal_mod(n, plen, m, mlen, quotient, 0);
  11445. + for (i = plen - 1; i >= plen - mlen; i--)
  11446. + n[i] = (n[i] >> mshift) | (n[i - 1] << (BIGNUM_INT_BITS - mshift));
  11447. + }
  11448. +
  11449. + /* Copy result to buffer */
  11450. + if (result) {
  11451. + for (i = 1; i <= (int)result[0]; i++) {
  11452. + int j = plen - i;
  11453. + result[i] = j >= 0 ? n[j] : 0;
  11454. + }
  11455. + }
  11456. +
  11457. + /* Free temporary arrays */
  11458. + for (i = 0; i < mlen; i++)
  11459. + m[i] = 0;
  11460. + sfree(mem_ctx, m);
  11461. + for (i = 0; i < plen; i++)
  11462. + n[i] = 0;
  11463. + sfree(mem_ctx, n);
  11464. +}
  11465. +
  11466. +/*
  11467. + * Simple remainder.
  11468. + */
  11469. +Bignum bigmod(void *mem_ctx, Bignum a, Bignum b)
  11470. +{
  11471. + Bignum r = newbn(mem_ctx, b[0]);
  11472. + bigdivmod(mem_ctx, a, b, r, NULL);
  11473. + return r;
  11474. +}
  11475. +
  11476. +/*
  11477. + * Compute (base ^ exp) % mod.
  11478. + */
  11479. +Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod)
  11480. +{
  11481. + BignumInt *a, *b, *n, *m;
  11482. + int mshift;
  11483. + int mlen, i, j;
  11484. + Bignum base, result;
  11485. +
  11486. + /*
  11487. + * The most significant word of mod needs to be non-zero. It
  11488. + * should already be, but let's make sure.
  11489. + */
  11490. + //assert(mod[mod[0]] != 0);
  11491. +
  11492. + /*
  11493. + * Make sure the base is smaller than the modulus, by reducing
  11494. + * it modulo the modulus if not.
  11495. + */
  11496. + base = bigmod(mem_ctx, base_in, mod);
  11497. +
  11498. + /* Allocate m of size mlen, copy mod to m */
  11499. + /* We use big endian internally */
  11500. + mlen = mod[0];
  11501. + m = snewn(mem_ctx, mlen, BignumInt);
  11502. + //if (!m)
  11503. + //abort(); /* FIXME */
  11504. + for (j = 0; j < mlen; j++)
  11505. + m[j] = mod[mod[0] - j];
  11506. +
  11507. + /* Shift m left to make msb bit set */
  11508. + for (mshift = 0; mshift < BIGNUM_INT_BITS - 1; mshift++)
  11509. + if ((m[0] << mshift) & BIGNUM_TOP_BIT)
  11510. + break;
  11511. + if (mshift) {
  11512. + for (i = 0; i < mlen - 1; i++)
  11513. + m[i] =
  11514. + (m[i] << mshift) | (m[i + 1] >>
  11515. + (BIGNUM_INT_BITS - mshift));
  11516. + m[mlen - 1] = m[mlen - 1] << mshift;
  11517. + }
  11518. +
  11519. + /* Allocate n of size mlen, copy base to n */
  11520. + n = snewn(mem_ctx, mlen, BignumInt);
  11521. + //if (!n)
  11522. + //abort(); /* FIXME */
  11523. + i = mlen - base[0];
  11524. + for (j = 0; j < i; j++)
  11525. + n[j] = 0;
  11526. + for (j = 0; j < base[0]; j++)
  11527. + n[i + j] = base[base[0] - j];
  11528. +
  11529. + /* Allocate a and b of size 2*mlen. Set a = 1 */
  11530. + a = snewn(mem_ctx, 2 * mlen, BignumInt);
  11531. + //if (!a)
  11532. + //abort(); /* FIXME */
  11533. + b = snewn(mem_ctx, 2 * mlen, BignumInt);
  11534. + //if (!b)
  11535. + //abort(); /* FIXME */
  11536. + for (i = 0; i < 2 * mlen; i++)
  11537. + a[i] = 0;
  11538. + a[2 * mlen - 1] = 1;
  11539. +
  11540. + /* Skip leading zero bits of exp. */
  11541. + i = 0;
  11542. + j = BIGNUM_INT_BITS - 1;
  11543. + while (i < exp[0] && (exp[exp[0] - i] & (1 << j)) == 0) {
  11544. + j--;
  11545. + if (j < 0) {
  11546. + i++;
  11547. + j = BIGNUM_INT_BITS - 1;
  11548. + }
  11549. + }
  11550. +
  11551. + /* Main computation */
  11552. + while (i < exp[0]) {
  11553. + while (j >= 0) {
  11554. + internal_mul(a + mlen, a + mlen, b, mlen);
  11555. + internal_mod(b, mlen * 2, m, mlen, NULL, 0);
  11556. + if ((exp[exp[0] - i] & (1 << j)) != 0) {
  11557. + internal_mul(b + mlen, n, a, mlen);
  11558. + internal_mod(a, mlen * 2, m, mlen, NULL, 0);
  11559. + } else {
  11560. + BignumInt *t;
  11561. + t = a;
  11562. + a = b;
  11563. + b = t;
  11564. + }
  11565. + j--;
  11566. + }
  11567. + i++;
  11568. + j = BIGNUM_INT_BITS - 1;
  11569. + }
  11570. +
  11571. + /* Fixup result in case the modulus was shifted */
  11572. + if (mshift) {
  11573. + for (i = mlen - 1; i < 2 * mlen - 1; i++)
  11574. + a[i] =
  11575. + (a[i] << mshift) | (a[i + 1] >>
  11576. + (BIGNUM_INT_BITS - mshift));
  11577. + a[2 * mlen - 1] = a[2 * mlen - 1] << mshift;
  11578. + internal_mod(a, mlen * 2, m, mlen, NULL, 0);
  11579. + for (i = 2 * mlen - 1; i >= mlen; i--)
  11580. + a[i] =
  11581. + (a[i] >> mshift) | (a[i - 1] <<
  11582. + (BIGNUM_INT_BITS - mshift));
  11583. + }
  11584. +
  11585. + /* Copy result to buffer */
  11586. + result = newbn(mem_ctx, mod[0]);
  11587. + for (i = 0; i < mlen; i++)
  11588. + result[result[0] - i] = a[i + mlen];
  11589. + while (result[0] > 1 && result[result[0]] == 0)
  11590. + result[0]--;
  11591. +
  11592. + /* Free temporary arrays */
  11593. + for (i = 0; i < 2 * mlen; i++)
  11594. + a[i] = 0;
  11595. + sfree(mem_ctx, a);
  11596. + for (i = 0; i < 2 * mlen; i++)
  11597. + b[i] = 0;
  11598. + sfree(mem_ctx, b);
  11599. + for (i = 0; i < mlen; i++)
  11600. + m[i] = 0;
  11601. + sfree(mem_ctx, m);
  11602. + for (i = 0; i < mlen; i++)
  11603. + n[i] = 0;
  11604. + sfree(mem_ctx, n);
  11605. +
  11606. + freebn(mem_ctx, base);
  11607. +
  11608. + return result;
  11609. +}
  11610. +
  11611. +
  11612. +#ifdef UNITTEST
  11613. +
  11614. +static __u32 dh_p[] = {
  11615. + 96,
  11616. + 0xFFFFFFFF,
  11617. + 0xFFFFFFFF,
  11618. + 0xA93AD2CA,
  11619. + 0x4B82D120,
  11620. + 0xE0FD108E,
  11621. + 0x43DB5BFC,
  11622. + 0x74E5AB31,
  11623. + 0x08E24FA0,
  11624. + 0xBAD946E2,
  11625. + 0x770988C0,
  11626. + 0x7A615D6C,
  11627. + 0xBBE11757,
  11628. + 0x177B200C,
  11629. + 0x521F2B18,
  11630. + 0x3EC86A64,
  11631. + 0xD8760273,
  11632. + 0xD98A0864,
  11633. + 0xF12FFA06,
  11634. + 0x1AD2EE6B,
  11635. + 0xCEE3D226,
  11636. + 0x4A25619D,
  11637. + 0x1E8C94E0,
  11638. + 0xDB0933D7,
  11639. + 0xABF5AE8C,
  11640. + 0xA6E1E4C7,
  11641. + 0xB3970F85,
  11642. + 0x5D060C7D,
  11643. + 0x8AEA7157,
  11644. + 0x58DBEF0A,
  11645. + 0xECFB8504,
  11646. + 0xDF1CBA64,
  11647. + 0xA85521AB,
  11648. + 0x04507A33,
  11649. + 0xAD33170D,
  11650. + 0x8AAAC42D,
  11651. + 0x15728E5A,
  11652. + 0x98FA0510,
  11653. + 0x15D22618,
  11654. + 0xEA956AE5,
  11655. + 0x3995497C,
  11656. + 0x95581718,
  11657. + 0xDE2BCBF6,
  11658. + 0x6F4C52C9,
  11659. + 0xB5C55DF0,
  11660. + 0xEC07A28F,
  11661. + 0x9B2783A2,
  11662. + 0x180E8603,
  11663. + 0xE39E772C,
  11664. + 0x2E36CE3B,
  11665. + 0x32905E46,
  11666. + 0xCA18217C,
  11667. + 0xF1746C08,
  11668. + 0x4ABC9804,
  11669. + 0x670C354E,
  11670. + 0x7096966D,
  11671. + 0x9ED52907,
  11672. + 0x208552BB,
  11673. + 0x1C62F356,
  11674. + 0xDCA3AD96,
  11675. + 0x83655D23,
  11676. + 0xFD24CF5F,
  11677. + 0x69163FA8,
  11678. + 0x1C55D39A,
  11679. + 0x98DA4836,
  11680. + 0xA163BF05,
  11681. + 0xC2007CB8,
  11682. + 0xECE45B3D,
  11683. + 0x49286651,
  11684. + 0x7C4B1FE6,
  11685. + 0xAE9F2411,
  11686. + 0x5A899FA5,
  11687. + 0xEE386BFB,
  11688. + 0xF406B7ED,
  11689. + 0x0BFF5CB6,
  11690. + 0xA637ED6B,
  11691. + 0xF44C42E9,
  11692. + 0x625E7EC6,
  11693. + 0xE485B576,
  11694. + 0x6D51C245,
  11695. + 0x4FE1356D,
  11696. + 0xF25F1437,
  11697. + 0x302B0A6D,
  11698. + 0xCD3A431B,
  11699. + 0xEF9519B3,
  11700. + 0x8E3404DD,
  11701. + 0x514A0879,
  11702. + 0x3B139B22,
  11703. + 0x020BBEA6,
  11704. + 0x8A67CC74,
  11705. + 0x29024E08,
  11706. + 0x80DC1CD1,
  11707. + 0xC4C6628B,
  11708. + 0x2168C234,
  11709. + 0xC90FDAA2,
  11710. + 0xFFFFFFFF,
  11711. + 0xFFFFFFFF,
  11712. +};
  11713. +
  11714. +static __u32 dh_a[] = {
  11715. + 8,
  11716. + 0xdf367516,
  11717. + 0x86459caa,
  11718. + 0xe2d459a4,
  11719. + 0xd910dae0,
  11720. + 0x8a8b5e37,
  11721. + 0x67ab31c6,
  11722. + 0xf0b55ea9,
  11723. + 0x440051d6,
  11724. +};
  11725. +
  11726. +static __u32 dh_b[] = {
  11727. + 8,
  11728. + 0xded92656,
  11729. + 0xe07a048a,
  11730. + 0x6fa452cd,
  11731. + 0x2df89d30,
  11732. + 0xc75f1b0f,
  11733. + 0x8ce3578f,
  11734. + 0x7980a324,
  11735. + 0x5daec786,
  11736. +};
  11737. +
  11738. +static __u32 dh_g[] = {
  11739. + 1,
  11740. + 2,
  11741. +};
  11742. +
  11743. +int main(void)
  11744. +{
  11745. + int i;
  11746. + __u32 *k;
  11747. + k = dwc_modpow(NULL, dh_g, dh_a, dh_p);
  11748. +
  11749. + printf("\n\n");
  11750. + for (i=0; i<k[0]; i++) {
  11751. + __u32 word32 = k[k[0] - i];
  11752. + __u16 l = word32 & 0xffff;
  11753. + __u16 m = (word32 & 0xffff0000) >> 16;
  11754. + printf("%04x %04x ", m, l);
  11755. + if (!((i + 1)%13)) printf("\n");
  11756. + }
  11757. + printf("\n\n");
  11758. +
  11759. + if ((k[0] == 0x60) && (k[1] == 0x28e490e5) && (k[0x60] == 0x5a0d3d4e)) {
  11760. + printf("PASS\n\n");
  11761. + }
  11762. + else {
  11763. + printf("FAIL\n\n");
  11764. + }
  11765. +
  11766. +}
  11767. +
  11768. +#endif /* UNITTEST */
  11769. +
  11770. +#endif /* CONFIG_MACH_IPMATE */
  11771. +
  11772. +#endif /*DWC_CRYPTOLIB */
  11773. --- /dev/null
  11774. +++ b/drivers/usb/host/dwc_common_port/dwc_modpow.h
  11775. @@ -0,0 +1,34 @@
  11776. +/*
  11777. + * dwc_modpow.h
  11778. + * See dwc_modpow.c for license and changes
  11779. + */
  11780. +#ifndef _DWC_MODPOW_H
  11781. +#define _DWC_MODPOW_H
  11782. +
  11783. +#ifdef __cplusplus
  11784. +extern "C" {
  11785. +#endif
  11786. +
  11787. +#include "dwc_os.h"
  11788. +
  11789. +/** @file
  11790. + *
  11791. + * This file defines the module exponentiation function which is only used
  11792. + * internally by the DWC UWB modules for calculation of PKs during numeric
  11793. + * association. The routine is taken from the PUTTY, an open source terminal
  11794. + * emulator. The PUTTY License is preserved in the dwc_modpow.c file.
  11795. + *
  11796. + */
  11797. +
  11798. +typedef uint32_t BignumInt;
  11799. +typedef uint64_t BignumDblInt;
  11800. +typedef BignumInt *Bignum;
  11801. +
  11802. +/* Compute modular exponentiaion */
  11803. +extern Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod);
  11804. +
  11805. +#ifdef __cplusplus
  11806. +}
  11807. +#endif
  11808. +
  11809. +#endif /* _LINUX_BIGNUM_H */
  11810. --- /dev/null
  11811. +++ b/drivers/usb/host/dwc_common_port/dwc_notifier.c
  11812. @@ -0,0 +1,319 @@
  11813. +#ifdef DWC_NOTIFYLIB
  11814. +
  11815. +#include "dwc_notifier.h"
  11816. +#include "dwc_list.h"
  11817. +
  11818. +typedef struct dwc_observer {
  11819. + void *observer;
  11820. + dwc_notifier_callback_t callback;
  11821. + void *data;
  11822. + char *notification;
  11823. + DWC_CIRCLEQ_ENTRY(dwc_observer) list_entry;
  11824. +} observer_t;
  11825. +
  11826. +DWC_CIRCLEQ_HEAD(observer_queue, dwc_observer);
  11827. +
  11828. +typedef struct dwc_notifier {
  11829. + void *mem_ctx;
  11830. + void *object;
  11831. + struct observer_queue observers;
  11832. + DWC_CIRCLEQ_ENTRY(dwc_notifier) list_entry;
  11833. +} notifier_t;
  11834. +
  11835. +DWC_CIRCLEQ_HEAD(notifier_queue, dwc_notifier);
  11836. +
  11837. +typedef struct manager {
  11838. + void *mem_ctx;
  11839. + void *wkq_ctx;
  11840. + dwc_workq_t *wq;
  11841. +// dwc_mutex_t *mutex;
  11842. + struct notifier_queue notifiers;
  11843. +} manager_t;
  11844. +
  11845. +static manager_t *manager = NULL;
  11846. +
  11847. +static int create_manager(void *mem_ctx, void *wkq_ctx)
  11848. +{
  11849. + manager = dwc_alloc(mem_ctx, sizeof(manager_t));
  11850. + if (!manager) {
  11851. + return -DWC_E_NO_MEMORY;
  11852. + }
  11853. +
  11854. + DWC_CIRCLEQ_INIT(&manager->notifiers);
  11855. +
  11856. + manager->wq = dwc_workq_alloc(wkq_ctx, "DWC Notification WorkQ");
  11857. + if (!manager->wq) {
  11858. + return -DWC_E_NO_MEMORY;
  11859. + }
  11860. +
  11861. + return 0;
  11862. +}
  11863. +
  11864. +static void free_manager(void)
  11865. +{
  11866. + dwc_workq_free(manager->wq);
  11867. +
  11868. + /* All notifiers must have unregistered themselves before this module
  11869. + * can be removed. Hitting this assertion indicates a programmer
  11870. + * error. */
  11871. + DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&manager->notifiers),
  11872. + "Notification manager being freed before all notifiers have been removed");
  11873. + dwc_free(manager->mem_ctx, manager);
  11874. +}
  11875. +
  11876. +#ifdef DEBUG
  11877. +static void dump_manager(void)
  11878. +{
  11879. + notifier_t *n;
  11880. + observer_t *o;
  11881. +
  11882. + DWC_ASSERT(manager, "Notification manager not found");
  11883. +
  11884. + DWC_DEBUG("List of all notifiers and observers:\n");
  11885. + DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) {
  11886. + DWC_DEBUG("Notifier %p has observers:\n", n->object);
  11887. + DWC_CIRCLEQ_FOREACH(o, &n->observers, list_entry) {
  11888. + DWC_DEBUG(" %p watching %s\n", o->observer, o->notification);
  11889. + }
  11890. + }
  11891. +}
  11892. +#else
  11893. +#define dump_manager(...)
  11894. +#endif
  11895. +
  11896. +static observer_t *alloc_observer(void *mem_ctx, void *observer, char *notification,
  11897. + dwc_notifier_callback_t callback, void *data)
  11898. +{
  11899. + observer_t *new_observer = dwc_alloc(mem_ctx, sizeof(observer_t));
  11900. +
  11901. + if (!new_observer) {
  11902. + return NULL;
  11903. + }
  11904. +
  11905. + DWC_CIRCLEQ_INIT_ENTRY(new_observer, list_entry);
  11906. + new_observer->observer = observer;
  11907. + new_observer->notification = notification;
  11908. + new_observer->callback = callback;
  11909. + new_observer->data = data;
  11910. + return new_observer;
  11911. +}
  11912. +
  11913. +static void free_observer(void *mem_ctx, observer_t *observer)
  11914. +{
  11915. + dwc_free(mem_ctx, observer);
  11916. +}
  11917. +
  11918. +static notifier_t *alloc_notifier(void *mem_ctx, void *object)
  11919. +{
  11920. + notifier_t *notifier;
  11921. +
  11922. + if (!object) {
  11923. + return NULL;
  11924. + }
  11925. +
  11926. + notifier = dwc_alloc(mem_ctx, sizeof(notifier_t));
  11927. + if (!notifier) {
  11928. + return NULL;
  11929. + }
  11930. +
  11931. + DWC_CIRCLEQ_INIT(&notifier->observers);
  11932. + DWC_CIRCLEQ_INIT_ENTRY(notifier, list_entry);
  11933. +
  11934. + notifier->mem_ctx = mem_ctx;
  11935. + notifier->object = object;
  11936. + return notifier;
  11937. +}
  11938. +
  11939. +static void free_notifier(notifier_t *notifier)
  11940. +{
  11941. + observer_t *observer;
  11942. +
  11943. + DWC_CIRCLEQ_FOREACH(observer, &notifier->observers, list_entry) {
  11944. + free_observer(notifier->mem_ctx, observer);
  11945. + }
  11946. +
  11947. + dwc_free(notifier->mem_ctx, notifier);
  11948. +}
  11949. +
  11950. +static notifier_t *find_notifier(void *object)
  11951. +{
  11952. + notifier_t *notifier;
  11953. +
  11954. + DWC_ASSERT(manager, "Notification manager not found");
  11955. +
  11956. + if (!object) {
  11957. + return NULL;
  11958. + }
  11959. +
  11960. + DWC_CIRCLEQ_FOREACH(notifier, &manager->notifiers, list_entry) {
  11961. + if (notifier->object == object) {
  11962. + return notifier;
  11963. + }
  11964. + }
  11965. +
  11966. + return NULL;
  11967. +}
  11968. +
  11969. +int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx)
  11970. +{
  11971. + return create_manager(mem_ctx, wkq_ctx);
  11972. +}
  11973. +
  11974. +void dwc_free_notification_manager(void)
  11975. +{
  11976. + free_manager();
  11977. +}
  11978. +
  11979. +dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object)
  11980. +{
  11981. + notifier_t *notifier;
  11982. +
  11983. + DWC_ASSERT(manager, "Notification manager not found");
  11984. +
  11985. + notifier = find_notifier(object);
  11986. + if (notifier) {
  11987. + DWC_ERROR("Notifier %p is already registered\n", object);
  11988. + return NULL;
  11989. + }
  11990. +
  11991. + notifier = alloc_notifier(mem_ctx, object);
  11992. + if (!notifier) {
  11993. + return NULL;
  11994. + }
  11995. +
  11996. + DWC_CIRCLEQ_INSERT_TAIL(&manager->notifiers, notifier, list_entry);
  11997. +
  11998. + DWC_INFO("Notifier %p registered", object);
  11999. + dump_manager();
  12000. +
  12001. + return notifier;
  12002. +}
  12003. +
  12004. +void dwc_unregister_notifier(dwc_notifier_t *notifier)
  12005. +{
  12006. + DWC_ASSERT(manager, "Notification manager not found");
  12007. +
  12008. + if (!DWC_CIRCLEQ_EMPTY(&notifier->observers)) {
  12009. + observer_t *o;
  12010. +
  12011. + DWC_ERROR("Notifier %p has active observers when removing\n", notifier->object);
  12012. + DWC_CIRCLEQ_FOREACH(o, &notifier->observers, list_entry) {
  12013. + DWC_DEBUGC(" %p watching %s\n", o->observer, o->notification);
  12014. + }
  12015. +
  12016. + DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&notifier->observers),
  12017. + "Notifier %p has active observers when removing", notifier);
  12018. + }
  12019. +
  12020. + DWC_CIRCLEQ_REMOVE_INIT(&manager->notifiers, notifier, list_entry);
  12021. + free_notifier(notifier);
  12022. +
  12023. + DWC_INFO("Notifier unregistered");
  12024. + dump_manager();
  12025. +}
  12026. +
  12027. +/* Add an observer to observe the notifier for a particular state, event, or notification. */
  12028. +int dwc_add_observer(void *observer, void *object, char *notification,
  12029. + dwc_notifier_callback_t callback, void *data)
  12030. +{
  12031. + notifier_t *notifier = find_notifier(object);
  12032. + observer_t *new_observer;
  12033. +
  12034. + if (!notifier) {
  12035. + DWC_ERROR("Notifier %p is not found when adding observer\n", object);
  12036. + return -DWC_E_INVALID;
  12037. + }
  12038. +
  12039. + new_observer = alloc_observer(notifier->mem_ctx, observer, notification, callback, data);
  12040. + if (!new_observer) {
  12041. + return -DWC_E_NO_MEMORY;
  12042. + }
  12043. +
  12044. + DWC_CIRCLEQ_INSERT_TAIL(&notifier->observers, new_observer, list_entry);
  12045. +
  12046. + DWC_INFO("Added observer %p to notifier %p observing notification %s, callback=%p, data=%p",
  12047. + observer, object, notification, callback, data);
  12048. +
  12049. + dump_manager();
  12050. + return 0;
  12051. +}
  12052. +
  12053. +int dwc_remove_observer(void *observer)
  12054. +{
  12055. + notifier_t *n;
  12056. +
  12057. + DWC_ASSERT(manager, "Notification manager not found");
  12058. +
  12059. + DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) {
  12060. + observer_t *o;
  12061. + observer_t *o2;
  12062. +
  12063. + DWC_CIRCLEQ_FOREACH_SAFE(o, o2, &n->observers, list_entry) {
  12064. + if (o->observer == observer) {
  12065. + DWC_CIRCLEQ_REMOVE_INIT(&n->observers, o, list_entry);
  12066. + DWC_INFO("Removing observer %p from notifier %p watching notification %s:",
  12067. + o->observer, n->object, o->notification);
  12068. + free_observer(n->mem_ctx, o);
  12069. + }
  12070. + }
  12071. + }
  12072. +
  12073. + dump_manager();
  12074. + return 0;
  12075. +}
  12076. +
  12077. +typedef struct callback_data {
  12078. + void *mem_ctx;
  12079. + dwc_notifier_callback_t cb;
  12080. + void *observer;
  12081. + void *data;
  12082. + void *object;
  12083. + char *notification;
  12084. + void *notification_data;
  12085. +} cb_data_t;
  12086. +
  12087. +static void cb_task(void *data)
  12088. +{
  12089. + cb_data_t *cb = (cb_data_t *)data;
  12090. +
  12091. + cb->cb(cb->object, cb->notification, cb->observer, cb->notification_data, cb->data);
  12092. + dwc_free(cb->mem_ctx, cb);
  12093. +}
  12094. +
  12095. +void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data)
  12096. +{
  12097. + observer_t *o;
  12098. +
  12099. + DWC_ASSERT(manager, "Notification manager not found");
  12100. +
  12101. + DWC_CIRCLEQ_FOREACH(o, &notifier->observers, list_entry) {
  12102. + int len = DWC_STRLEN(notification);
  12103. +
  12104. + if (DWC_STRLEN(o->notification) != len) {
  12105. + continue;
  12106. + }
  12107. +
  12108. + if (DWC_STRNCMP(o->notification, notification, len) == 0) {
  12109. + cb_data_t *cb_data = dwc_alloc(notifier->mem_ctx, sizeof(cb_data_t));
  12110. +
  12111. + if (!cb_data) {
  12112. + DWC_ERROR("Failed to allocate callback data\n");
  12113. + return;
  12114. + }
  12115. +
  12116. + cb_data->mem_ctx = notifier->mem_ctx;
  12117. + cb_data->cb = o->callback;
  12118. + cb_data->observer = o->observer;
  12119. + cb_data->data = o->data;
  12120. + cb_data->object = notifier->object;
  12121. + cb_data->notification = notification;
  12122. + cb_data->notification_data = notification_data;
  12123. + DWC_DEBUGC("Observer found %p for notification %s\n", o->observer, notification);
  12124. + DWC_WORKQ_SCHEDULE(manager->wq, cb_task, cb_data,
  12125. + "Notify callback from %p for Notification %s, to observer %p",
  12126. + cb_data->object, notification, cb_data->observer);
  12127. + }
  12128. + }
  12129. +}
  12130. +
  12131. +#endif /* DWC_NOTIFYLIB */
  12132. --- /dev/null
  12133. +++ b/drivers/usb/host/dwc_common_port/dwc_notifier.h
  12134. @@ -0,0 +1,122 @@
  12135. +
  12136. +#ifndef __DWC_NOTIFIER_H__
  12137. +#define __DWC_NOTIFIER_H__
  12138. +
  12139. +#ifdef __cplusplus
  12140. +extern "C" {
  12141. +#endif
  12142. +
  12143. +#include "dwc_os.h"
  12144. +
  12145. +/** @file
  12146. + *
  12147. + * A simple implementation of the Observer pattern. Any "module" can
  12148. + * register as an observer or notifier. The notion of "module" is abstract and
  12149. + * can mean anything used to identify either an observer or notifier. Usually
  12150. + * it will be a pointer to a data structure which contains some state, ie an
  12151. + * object.
  12152. + *
  12153. + * Before any notifiers can be added, the global notification manager must be
  12154. + * brought up with dwc_alloc_notification_manager().
  12155. + * dwc_free_notification_manager() will bring it down and free all resources.
  12156. + * These would typically be called upon module load and unload. The
  12157. + * notification manager is a single global instance that handles all registered
  12158. + * observable modules and observers so this should be done only once.
  12159. + *
  12160. + * A module can be observable by using Notifications to publicize some general
  12161. + * information about it's state or operation. It does not care who listens, or
  12162. + * even if anyone listens, or what they do with the information. The observable
  12163. + * modules do not need to know any information about it's observers or their
  12164. + * interface, or their state or data.
  12165. + *
  12166. + * Any module can register to emit Notifications. It should publish a list of
  12167. + * notifications that it can emit and their behavior, such as when they will get
  12168. + * triggered, and what information will be provided to the observer. Then it
  12169. + * should register itself as an observable module. See dwc_register_notifier().
  12170. + *
  12171. + * Any module can observe any observable, registered module, provided it has a
  12172. + * handle to the other module and knows what notifications to observe. See
  12173. + * dwc_add_observer().
  12174. + *
  12175. + * A function of type dwc_notifier_callback_t is called whenever a notification
  12176. + * is triggered with one or more observers observing it. This function is
  12177. + * called in it's own process so it may sleep or block if needed. It is
  12178. + * guaranteed to be called sometime after the notification has occurred and will
  12179. + * be called once per each time the notification is triggered. It will NOT be
  12180. + * called in the same process context used to trigger the notification.
  12181. + *
  12182. + * @section Limitiations
  12183. + *
  12184. + * Keep in mind that Notifications that can be triggered in rapid sucession may
  12185. + * schedule too many processes too handle. Be aware of this limitation when
  12186. + * designing to use notifications, and only add notifications for appropriate
  12187. + * observable information.
  12188. + *
  12189. + * Also Notification callbacks are not synchronous. If you need to synchronize
  12190. + * the behavior between module/observer you must use other means. And perhaps
  12191. + * that will mean Notifications are not the proper solution.
  12192. + */
  12193. +
  12194. +struct dwc_notifier;
  12195. +typedef struct dwc_notifier dwc_notifier_t;
  12196. +
  12197. +/** The callback function must be of this type.
  12198. + *
  12199. + * @param object This is the object that is being observed.
  12200. + * @param notification This is the notification that was triggered.
  12201. + * @param observer This is the observer
  12202. + * @param notification_data This is notification-specific data that the notifier
  12203. + * has included in this notification. The value of this should be published in
  12204. + * the documentation of the observable module with the notifications.
  12205. + * @param user_data This is any custom data that the observer provided when
  12206. + * adding itself as an observer to the notification. */
  12207. +typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer,
  12208. + void *notification_data, void *user_data);
  12209. +
  12210. +/** Brings up the notification manager. */
  12211. +extern int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx);
  12212. +/** Brings down the notification manager. */
  12213. +extern void dwc_free_notification_manager(void);
  12214. +
  12215. +/** This function registers an observable module. A dwc_notifier_t object is
  12216. + * returned to the observable module. This is an opaque object that is used by
  12217. + * the observable module to trigger notifications. This object should only be
  12218. + * accessible to functions that are authorized to trigger notifications for this
  12219. + * module. Observers do not need this object. */
  12220. +extern dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object);
  12221. +
  12222. +/** This function unregisters an observable module. All observers have to be
  12223. + * removed prior to unregistration. */
  12224. +extern void dwc_unregister_notifier(dwc_notifier_t *notifier);
  12225. +
  12226. +/** Add a module as an observer to the observable module. The observable module
  12227. + * needs to have previously registered with the notification manager.
  12228. + *
  12229. + * @param observer The observer module
  12230. + * @param object The module to observe
  12231. + * @param notification The notification to observe
  12232. + * @param callback The callback function to call
  12233. + * @param user_data Any additional user data to pass into the callback function */
  12234. +extern int dwc_add_observer(void *observer, void *object, char *notification,
  12235. + dwc_notifier_callback_t callback, void *user_data);
  12236. +
  12237. +/** Removes the specified observer from all notifications that it is currently
  12238. + * observing. */
  12239. +extern int dwc_remove_observer(void *observer);
  12240. +
  12241. +/** This function triggers a Notification. It should be called by the
  12242. + * observable module, or any module or library which the observable module
  12243. + * allows to trigger notification on it's behalf. Such as the dwc_cc_t.
  12244. + *
  12245. + * dwc_notify is a non-blocking function. Callbacks are scheduled called in
  12246. + * their own process context for each trigger. Callbacks can be blocking.
  12247. + * dwc_notify can be called from interrupt context if needed.
  12248. + *
  12249. + */
  12250. +void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data);
  12251. +
  12252. +#ifdef __cplusplus
  12253. +}
  12254. +#endif
  12255. +
  12256. +#endif /* __DWC_NOTIFIER_H__ */
  12257. --- /dev/null
  12258. +++ b/drivers/usb/host/dwc_common_port/dwc_os.h
  12259. @@ -0,0 +1,1274 @@
  12260. +/* =========================================================================
  12261. + * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_os.h $
  12262. + * $Revision: #14 $
  12263. + * $Date: 2010/11/04 $
  12264. + * $Change: 1621695 $
  12265. + *
  12266. + * Synopsys Portability Library Software and documentation
  12267. + * (hereinafter, "Software") is an Unsupported proprietary work of
  12268. + * Synopsys, Inc. unless otherwise expressly agreed to in writing
  12269. + * between Synopsys and you.
  12270. + *
  12271. + * The Software IS NOT an item of Licensed Software or Licensed Product
  12272. + * under any End User Software License Agreement or Agreement for
  12273. + * Licensed Product with Synopsys or any supplement thereto. You are
  12274. + * permitted to use and redistribute this Software in source and binary
  12275. + * forms, with or without modification, provided that redistributions
  12276. + * of source code must retain this notice. You may not view, use,
  12277. + * disclose, copy or distribute this file or any information contained
  12278. + * herein except pursuant to this license grant from Synopsys. If you
  12279. + * do not agree with this notice, including the disclaimer below, then
  12280. + * you are not authorized to use the Software.
  12281. + *
  12282. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
  12283. + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  12284. + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  12285. + * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
  12286. + * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  12287. + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  12288. + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  12289. + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  12290. + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  12291. + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  12292. + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  12293. + * DAMAGE.
  12294. + * ========================================================================= */
  12295. +#ifndef _DWC_OS_H_
  12296. +#define _DWC_OS_H_
  12297. +
  12298. +#ifdef __cplusplus
  12299. +extern "C" {
  12300. +#endif
  12301. +
  12302. +/** @file
  12303. + *
  12304. + * DWC portability library, low level os-wrapper functions
  12305. + *
  12306. + */
  12307. +
  12308. +/* These basic types need to be defined by some OS header file or custom header
  12309. + * file for your specific target architecture.
  12310. + *
  12311. + * uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t
  12312. + *
  12313. + * Any custom or alternate header file must be added and enabled here.
  12314. + */
  12315. +
  12316. +#ifdef DWC_LINUX
  12317. +# include <linux/types.h>
  12318. +# ifdef CONFIG_DEBUG_MUTEXES
  12319. +# include <linux/mutex.h>
  12320. +# endif
  12321. +# include <linux/spinlock.h>
  12322. +# include <linux/errno.h>
  12323. +# include <stdarg.h>
  12324. +#endif
  12325. +
  12326. +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
  12327. +# include <os_dep.h>
  12328. +#endif
  12329. +
  12330. +
  12331. +/** @name Primitive Types and Values */
  12332. +
  12333. +/** We define a boolean type for consistency. Can be either YES or NO */
  12334. +typedef uint8_t dwc_bool_t;
  12335. +#define YES 1
  12336. +#define NO 0
  12337. +
  12338. +#ifdef DWC_LINUX
  12339. +
  12340. +/** @name Error Codes */
  12341. +#define DWC_E_INVALID EINVAL
  12342. +#define DWC_E_NO_MEMORY ENOMEM
  12343. +#define DWC_E_NO_DEVICE ENODEV
  12344. +#define DWC_E_NOT_SUPPORTED EOPNOTSUPP
  12345. +#define DWC_E_TIMEOUT ETIMEDOUT
  12346. +#define DWC_E_BUSY EBUSY
  12347. +#define DWC_E_AGAIN EAGAIN
  12348. +#define DWC_E_RESTART ERESTART
  12349. +#define DWC_E_ABORT ECONNABORTED
  12350. +#define DWC_E_SHUTDOWN ESHUTDOWN
  12351. +#define DWC_E_NO_DATA ENODATA
  12352. +#define DWC_E_DISCONNECT ECONNRESET
  12353. +#define DWC_E_UNKNOWN EINVAL
  12354. +#define DWC_E_NO_STREAM_RES ENOSR
  12355. +#define DWC_E_COMMUNICATION ECOMM
  12356. +#define DWC_E_OVERFLOW EOVERFLOW
  12357. +#define DWC_E_PROTOCOL EPROTO
  12358. +#define DWC_E_IN_PROGRESS EINPROGRESS
  12359. +#define DWC_E_PIPE EPIPE
  12360. +#define DWC_E_IO EIO
  12361. +#define DWC_E_NO_SPACE ENOSPC
  12362. +
  12363. +#else
  12364. +
  12365. +/** @name Error Codes */
  12366. +#define DWC_E_INVALID 1001
  12367. +#define DWC_E_NO_MEMORY 1002
  12368. +#define DWC_E_NO_DEVICE 1003
  12369. +#define DWC_E_NOT_SUPPORTED 1004
  12370. +#define DWC_E_TIMEOUT 1005
  12371. +#define DWC_E_BUSY 1006
  12372. +#define DWC_E_AGAIN 1007
  12373. +#define DWC_E_RESTART 1008
  12374. +#define DWC_E_ABORT 1009
  12375. +#define DWC_E_SHUTDOWN 1010
  12376. +#define DWC_E_NO_DATA 1011
  12377. +#define DWC_E_DISCONNECT 2000
  12378. +#define DWC_E_UNKNOWN 3000
  12379. +#define DWC_E_NO_STREAM_RES 4001
  12380. +#define DWC_E_COMMUNICATION 4002
  12381. +#define DWC_E_OVERFLOW 4003
  12382. +#define DWC_E_PROTOCOL 4004
  12383. +#define DWC_E_IN_PROGRESS 4005
  12384. +#define DWC_E_PIPE 4006
  12385. +#define DWC_E_IO 4007
  12386. +#define DWC_E_NO_SPACE 4008
  12387. +
  12388. +#endif
  12389. +
  12390. +
  12391. +/** @name Tracing/Logging Functions
  12392. + *
  12393. + * These function provide the capability to add tracing, debugging, and error
  12394. + * messages, as well exceptions as assertions. The WUDEV uses these
  12395. + * extensively. These could be logged to the main console, the serial port, an
  12396. + * internal buffer, etc. These functions could also be no-op if they are too
  12397. + * expensive on your system. By default undefining the DEBUG macro already
  12398. + * no-ops some of these functions. */
  12399. +
  12400. +/** Returns non-zero if in interrupt context. */
  12401. +extern dwc_bool_t DWC_IN_IRQ(void);
  12402. +#define dwc_in_irq DWC_IN_IRQ
  12403. +
  12404. +/** Returns "IRQ" if DWC_IN_IRQ is true. */
  12405. +static inline char *dwc_irq(void) {
  12406. + return DWC_IN_IRQ() ? "IRQ" : "";
  12407. +}
  12408. +
  12409. +/** Returns non-zero if in bottom-half context. */
  12410. +extern dwc_bool_t DWC_IN_BH(void);
  12411. +#define dwc_in_bh DWC_IN_BH
  12412. +
  12413. +/** Returns "BH" if DWC_IN_BH is true. */
  12414. +static inline char *dwc_bh(void) {
  12415. + return DWC_IN_BH() ? "BH" : "";
  12416. +}
  12417. +
  12418. +/**
  12419. + * A vprintf() clone. Just call vprintf if you've got it.
  12420. + */
  12421. +extern void DWC_VPRINTF(char *format, va_list args);
  12422. +#define dwc_vprintf DWC_VPRINTF
  12423. +
  12424. +/**
  12425. + * A vsnprintf() clone. Just call vprintf if you've got it.
  12426. + */
  12427. +extern int DWC_VSNPRINTF(char *str, int size, char *format, va_list args);
  12428. +#define dwc_vsnprintf DWC_VSNPRINTF
  12429. +
  12430. +/**
  12431. + * printf() clone. Just call printf if you've go it.
  12432. + */
  12433. +extern void DWC_PRINTF(char *format, ...)
  12434. +/* This provides compiler level static checking of the parameters if you're
  12435. + * using GCC. */
  12436. +#ifdef __GNUC__
  12437. + __attribute__ ((format(printf, 1, 2)));
  12438. +#else
  12439. + ;
  12440. +#endif
  12441. +#define dwc_printf DWC_PRINTF
  12442. +
  12443. +/**
  12444. + * sprintf() clone. Just call sprintf if you've got it.
  12445. + */
  12446. +extern int DWC_SPRINTF(char *string, char *format, ...)
  12447. +#ifdef __GNUC__
  12448. + __attribute__ ((format(printf, 2, 3)));
  12449. +#else
  12450. + ;
  12451. +#endif
  12452. +#define dwc_sprintf DWC_SPRINTF
  12453. +
  12454. +/**
  12455. + * snprintf() clone. Just call snprintf if you've got it.
  12456. + */
  12457. +extern int DWC_SNPRINTF(char *string, int size, char *format, ...)
  12458. +#ifdef __GNUC__
  12459. + __attribute__ ((format(printf, 3, 4)));
  12460. +#else
  12461. + ;
  12462. +#endif
  12463. +#define dwc_snprintf DWC_SNPRINTF
  12464. +
  12465. +/**
  12466. + * Prints a WARNING message. On systems that don't differentiate between
  12467. + * warnings and regular log messages, just print it. Indicates that something
  12468. + * may be wrong with the driver. Works like printf().
  12469. + *
  12470. + * Use the DWC_WARN macro to call this function.
  12471. + */
  12472. +extern void __DWC_WARN(char *format, ...)
  12473. +#ifdef __GNUC__
  12474. + __attribute__ ((format(printf, 1, 2)));
  12475. +#else
  12476. + ;
  12477. +#endif
  12478. +
  12479. +/**
  12480. + * Prints an error message. On systems that don't differentiate between errors
  12481. + * and regular log messages, just print it. Indicates that something went wrong
  12482. + * with the driver. Works like printf().
  12483. + *
  12484. + * Use the DWC_ERROR macro to call this function.
  12485. + */
  12486. +extern void __DWC_ERROR(char *format, ...)
  12487. +#ifdef __GNUC__
  12488. + __attribute__ ((format(printf, 1, 2)));
  12489. +#else
  12490. + ;
  12491. +#endif
  12492. +
  12493. +/**
  12494. + * Prints an exception error message and takes some user-defined action such as
  12495. + * print out a backtrace or trigger a breakpoint. Indicates that something went
  12496. + * abnormally wrong with the driver such as programmer error, or other
  12497. + * exceptional condition. It should not be ignored so even on systems without
  12498. + * printing capability, some action should be taken to notify the developer of
  12499. + * it. Works like printf().
  12500. + */
  12501. +extern void DWC_EXCEPTION(char *format, ...)
  12502. +#ifdef __GNUC__
  12503. + __attribute__ ((format(printf, 1, 2)));
  12504. +#else
  12505. + ;
  12506. +#endif
  12507. +#define dwc_exception DWC_EXCEPTION
  12508. +
  12509. +#ifndef DWC_OTG_DEBUG_LEV
  12510. +#define DWC_OTG_DEBUG_LEV 0
  12511. +#endif
  12512. +
  12513. +#ifdef DEBUG
  12514. +/**
  12515. + * Prints out a debug message. Used for logging/trace messages.
  12516. + *
  12517. + * Use the DWC_DEBUG macro to call this function
  12518. + */
  12519. +extern void __DWC_DEBUG(char *format, ...)
  12520. +#ifdef __GNUC__
  12521. + __attribute__ ((format(printf, 1, 2)));
  12522. +#else
  12523. + ;
  12524. +#endif
  12525. +#else
  12526. +#define __DWC_DEBUG printk
  12527. +#endif
  12528. +
  12529. +/**
  12530. + * Prints out a Debug message.
  12531. + */
  12532. +#define DWC_DEBUG(_format, _args...) __DWC_DEBUG("DEBUG:%s:%s: " _format "\n", \
  12533. + __func__, dwc_irq(), ## _args)
  12534. +#define dwc_debug DWC_DEBUG
  12535. +/**
  12536. + * Prints out a Debug message if enabled at compile time.
  12537. + */
  12538. +#if DWC_OTG_DEBUG_LEV > 0
  12539. +#define DWC_DEBUGC(_format, _args...) DWC_DEBUG(_format, ##_args )
  12540. +#else
  12541. +#define DWC_DEBUGC(_format, _args...)
  12542. +#endif
  12543. +#define dwc_debugc DWC_DEBUGC
  12544. +/**
  12545. + * Prints out an informative message.
  12546. + */
  12547. +#define DWC_INFO(_format, _args...) DWC_PRINTF("INFO:%s: " _format "\n", \
  12548. + dwc_irq(), ## _args)
  12549. +#define dwc_info DWC_INFO
  12550. +/**
  12551. + * Prints out an informative message if enabled at compile time.
  12552. + */
  12553. +#if DWC_OTG_DEBUG_LEV > 1
  12554. +#define DWC_INFOC(_format, _args...) DWC_INFO(_format, ##_args )
  12555. +#else
  12556. +#define DWC_INFOC(_format, _args...)
  12557. +#endif
  12558. +#define dwc_infoc DWC_INFOC
  12559. +/**
  12560. + * Prints out a warning message.
  12561. + */
  12562. +#define DWC_WARN(_format, _args...) __DWC_WARN("WARN:%s:%s:%d: " _format "\n", \
  12563. + dwc_irq(), __func__, __LINE__, ## _args)
  12564. +#define dwc_warn DWC_WARN
  12565. +/**
  12566. + * Prints out an error message.
  12567. + */
  12568. +#define DWC_ERROR(_format, _args...) __DWC_ERROR("ERROR:%s:%s:%d: " _format "\n", \
  12569. + dwc_irq(), __func__, __LINE__, ## _args)
  12570. +#define dwc_error DWC_ERROR
  12571. +
  12572. +#define DWC_PROTO_ERROR(_format, _args...) __DWC_WARN("ERROR:%s:%s:%d: " _format "\n", \
  12573. + dwc_irq(), __func__, __LINE__, ## _args)
  12574. +#define dwc_proto_error DWC_PROTO_ERROR
  12575. +
  12576. +#ifdef DEBUG
  12577. +/** Prints out a exception error message if the _expr expression fails. Disabled
  12578. + * if DEBUG is not enabled. */
  12579. +#define DWC_ASSERT(_expr, _format, _args...) do { \
  12580. + if (!(_expr)) { DWC_EXCEPTION("%s:%s:%d: " _format "\n", dwc_irq(), \
  12581. + __FILE__, __LINE__, ## _args); } \
  12582. + } while (0)
  12583. +#else
  12584. +#define DWC_ASSERT(_x...)
  12585. +#endif
  12586. +#define dwc_assert DWC_ASSERT
  12587. +
  12588. +
  12589. +/** @name Byte Ordering
  12590. + * The following functions are for conversions between processor's byte ordering
  12591. + * and specific ordering you want.
  12592. + */
  12593. +
  12594. +/** Converts 32 bit data in CPU byte ordering to little endian. */
  12595. +extern uint32_t DWC_CPU_TO_LE32(uint32_t *p);
  12596. +#define dwc_cpu_to_le32 DWC_CPU_TO_LE32
  12597. +
  12598. +/** Converts 32 bit data in CPU byte orderint to big endian. */
  12599. +extern uint32_t DWC_CPU_TO_BE32(uint32_t *p);
  12600. +#define dwc_cpu_to_be32 DWC_CPU_TO_BE32
  12601. +
  12602. +/** Converts 32 bit little endian data to CPU byte ordering. */
  12603. +extern uint32_t DWC_LE32_TO_CPU(uint32_t *p);
  12604. +#define dwc_le32_to_cpu DWC_LE32_TO_CPU
  12605. +
  12606. +/** Converts 32 bit big endian data to CPU byte ordering. */
  12607. +extern uint32_t DWC_BE32_TO_CPU(uint32_t *p);
  12608. +#define dwc_be32_to_cpu DWC_BE32_TO_CPU
  12609. +
  12610. +/** Converts 16 bit data in CPU byte ordering to little endian. */
  12611. +extern uint16_t DWC_CPU_TO_LE16(uint16_t *p);
  12612. +#define dwc_cpu_to_le16 DWC_CPU_TO_LE16
  12613. +
  12614. +/** Converts 16 bit data in CPU byte orderint to big endian. */
  12615. +extern uint16_t DWC_CPU_TO_BE16(uint16_t *p);
  12616. +#define dwc_cpu_to_be16 DWC_CPU_TO_BE16
  12617. +
  12618. +/** Converts 16 bit little endian data to CPU byte ordering. */
  12619. +extern uint16_t DWC_LE16_TO_CPU(uint16_t *p);
  12620. +#define dwc_le16_to_cpu DWC_LE16_TO_CPU
  12621. +
  12622. +/** Converts 16 bit bi endian data to CPU byte ordering. */
  12623. +extern uint16_t DWC_BE16_TO_CPU(uint16_t *p);
  12624. +#define dwc_be16_to_cpu DWC_BE16_TO_CPU
  12625. +
  12626. +
  12627. +/** @name Register Read/Write
  12628. + *
  12629. + * The following six functions should be implemented to read/write registers of
  12630. + * 32-bit and 64-bit sizes. All modules use this to read/write register values.
  12631. + * The reg value is a pointer to the register calculated from the void *base
  12632. + * variable passed into the driver when it is started. */
  12633. +
  12634. +#ifdef DWC_LINUX
  12635. +/* Linux doesn't need any extra parameters for register read/write, so we
  12636. + * just throw away the IO context parameter.
  12637. + */
  12638. +/** Reads the content of a 32-bit register. */
  12639. +extern uint32_t DWC_READ_REG32(uint32_t volatile *reg);
  12640. +#define dwc_read_reg32(_ctx_,_reg_) DWC_READ_REG32(_reg_)
  12641. +
  12642. +/** Reads the content of a 64-bit register. */
  12643. +extern uint64_t DWC_READ_REG64(uint64_t volatile *reg);
  12644. +#define dwc_read_reg64(_ctx_,_reg_) DWC_READ_REG64(_reg_)
  12645. +
  12646. +/** Writes to a 32-bit register. */
  12647. +extern void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value);
  12648. +#define dwc_write_reg32(_ctx_,_reg_,_val_) DWC_WRITE_REG32(_reg_, _val_)
  12649. +
  12650. +/** Writes to a 64-bit register. */
  12651. +extern void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value);
  12652. +#define dwc_write_reg64(_ctx_,_reg_,_val_) DWC_WRITE_REG64(_reg_, _val_)
  12653. +
  12654. +/**
  12655. + * Modify bit values in a register. Using the
  12656. + * algorithm: (reg_contents & ~clear_mask) | set_mask.
  12657. + */
  12658. +extern void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);
  12659. +#define dwc_modify_reg32(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG32(_reg_,_cmsk_,_smsk_)
  12660. +extern void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask);
  12661. +#define dwc_modify_reg64(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG64(_reg_,_cmsk_,_smsk_)
  12662. +
  12663. +#endif /* DWC_LINUX */
  12664. +
  12665. +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
  12666. +typedef struct dwc_ioctx {
  12667. + struct device *dev;
  12668. + bus_space_tag_t iot;
  12669. + bus_space_handle_t ioh;
  12670. +} dwc_ioctx_t;
  12671. +
  12672. +/** BSD needs two extra parameters for register read/write, so we pass
  12673. + * them in using the IO context parameter.
  12674. + */
  12675. +/** Reads the content of a 32-bit register. */
  12676. +extern uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg);
  12677. +#define dwc_read_reg32 DWC_READ_REG32
  12678. +
  12679. +/** Reads the content of a 64-bit register. */
  12680. +extern uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg);
  12681. +#define dwc_read_reg64 DWC_READ_REG64
  12682. +
  12683. +/** Writes to a 32-bit register. */
  12684. +extern void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value);
  12685. +#define dwc_write_reg32 DWC_WRITE_REG32
  12686. +
  12687. +/** Writes to a 64-bit register. */
  12688. +extern void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value);
  12689. +#define dwc_write_reg64 DWC_WRITE_REG64
  12690. +
  12691. +/**
  12692. + * Modify bit values in a register. Using the
  12693. + * algorithm: (reg_contents & ~clear_mask) | set_mask.
  12694. + */
  12695. +extern void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);
  12696. +#define dwc_modify_reg32 DWC_MODIFY_REG32
  12697. +extern void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask);
  12698. +#define dwc_modify_reg64 DWC_MODIFY_REG64
  12699. +
  12700. +#endif /* DWC_FREEBSD || DWC_NETBSD */
  12701. +
  12702. +/** @cond */
  12703. +
  12704. +/** @name Some convenience MACROS used internally. Define DWC_DEBUG_REGS to log the
  12705. + * register writes. */
  12706. +
  12707. +#ifdef DWC_LINUX
  12708. +
  12709. +# ifdef DWC_DEBUG_REGS
  12710. +
  12711. +#define dwc_define_read_write_reg_n(_reg,_container_type) \
  12712. +static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \
  12713. + return DWC_READ_REG32(&container->regs->_reg[num]); \
  12714. +} \
  12715. +static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \
  12716. + DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \
  12717. + &(((uint32_t*)container->regs->_reg)[num]), data); \
  12718. + DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \
  12719. +}
  12720. +
  12721. +#define dwc_define_read_write_reg(_reg,_container_type) \
  12722. +static inline uint32_t dwc_read_##_reg(_container_type *container) { \
  12723. + return DWC_READ_REG32(&container->regs->_reg); \
  12724. +} \
  12725. +static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \
  12726. + DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \
  12727. + DWC_WRITE_REG32(&container->regs->_reg, data); \
  12728. +}
  12729. +
  12730. +# else /* DWC_DEBUG_REGS */
  12731. +
  12732. +#define dwc_define_read_write_reg_n(_reg,_container_type) \
  12733. +static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \
  12734. + return DWC_READ_REG32(&container->regs->_reg[num]); \
  12735. +} \
  12736. +static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \
  12737. + DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \
  12738. +}
  12739. +
  12740. +#define dwc_define_read_write_reg(_reg,_container_type) \
  12741. +static inline uint32_t dwc_read_##_reg(_container_type *container) { \
  12742. + return DWC_READ_REG32(&container->regs->_reg); \
  12743. +} \
  12744. +static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \
  12745. + DWC_WRITE_REG32(&container->regs->_reg, data); \
  12746. +}
  12747. +
  12748. +# endif /* DWC_DEBUG_REGS */
  12749. +
  12750. +#endif /* DWC_LINUX */
  12751. +
  12752. +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
  12753. +
  12754. +# ifdef DWC_DEBUG_REGS
  12755. +
  12756. +#define dwc_define_read_write_reg_n(_reg,_container_type) \
  12757. +static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \
  12758. + return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \
  12759. +} \
  12760. +static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \
  12761. + DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \
  12762. + &(((uint32_t*)container->regs->_reg)[num]), data); \
  12763. + DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \
  12764. +}
  12765. +
  12766. +#define dwc_define_read_write_reg(_reg,_container_type) \
  12767. +static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \
  12768. + return DWC_READ_REG32(io_ctx, &container->regs->_reg); \
  12769. +} \
  12770. +static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \
  12771. + DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \
  12772. + DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \
  12773. +}
  12774. +
  12775. +# else /* DWC_DEBUG_REGS */
  12776. +
  12777. +#define dwc_define_read_write_reg_n(_reg,_container_type) \
  12778. +static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \
  12779. + return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \
  12780. +} \
  12781. +static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \
  12782. + DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \
  12783. +}
  12784. +
  12785. +#define dwc_define_read_write_reg(_reg,_container_type) \
  12786. +static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \
  12787. + return DWC_READ_REG32(io_ctx, &container->regs->_reg); \
  12788. +} \
  12789. +static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \
  12790. + DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \
  12791. +}
  12792. +
  12793. +# endif /* DWC_DEBUG_REGS */
  12794. +
  12795. +#endif /* DWC_FREEBSD || DWC_NETBSD */
  12796. +
  12797. +/** @endcond */
  12798. +
  12799. +
  12800. +#ifdef DWC_CRYPTOLIB
  12801. +/** @name Crypto Functions
  12802. + *
  12803. + * These are the low-level cryptographic functions used by the driver. */
  12804. +
  12805. +/** Perform AES CBC */
  12806. +extern int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out);
  12807. +#define dwc_aes_cbc DWC_AES_CBC
  12808. +
  12809. +/** Fill the provided buffer with random bytes. These should be cryptographic grade random numbers. */
  12810. +extern void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length);
  12811. +#define dwc_random_bytes DWC_RANDOM_BYTES
  12812. +
  12813. +/** Perform the SHA-256 hash function */
  12814. +extern int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out);
  12815. +#define dwc_sha256 DWC_SHA256
  12816. +
  12817. +/** Calculated the HMAC-SHA256 */
  12818. +extern int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t *out);
  12819. +#define dwc_hmac_sha256 DWC_HMAC_SHA256
  12820. +
  12821. +#endif /* DWC_CRYPTOLIB */
  12822. +
  12823. +
  12824. +/** @name Memory Allocation
  12825. + *
  12826. + * These function provide access to memory allocation. There are only 2 DMA
  12827. + * functions and 3 Regular memory functions that need to be implemented. None
  12828. + * of the memory debugging routines need to be implemented. The allocation
  12829. + * routines all ZERO the contents of the memory.
  12830. + *
  12831. + * Defining DWC_DEBUG_MEMORY turns on memory debugging and statistic gathering.
  12832. + * This checks for memory leaks, keeping track of alloc/free pairs. It also
  12833. + * keeps track of how much memory the driver is using at any given time. */
  12834. +
  12835. +#define DWC_PAGE_SIZE 4096
  12836. +#define DWC_PAGE_OFFSET(addr) (((uint32_t)addr) & 0xfff)
  12837. +#define DWC_PAGE_ALIGNED(addr) ((((uint32_t)addr) & 0xfff) == 0)
  12838. +
  12839. +#define DWC_INVALID_DMA_ADDR 0x0
  12840. +
  12841. +#ifdef DWC_LINUX
  12842. +/** Type for a DMA address */
  12843. +typedef dma_addr_t dwc_dma_t;
  12844. +#endif
  12845. +
  12846. +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
  12847. +typedef bus_addr_t dwc_dma_t;
  12848. +#endif
  12849. +
  12850. +#ifdef DWC_FREEBSD
  12851. +typedef struct dwc_dmactx {
  12852. + struct device *dev;
  12853. + bus_dma_tag_t dma_tag;
  12854. + bus_dmamap_t dma_map;
  12855. + bus_addr_t dma_paddr;
  12856. + void *dma_vaddr;
  12857. +} dwc_dmactx_t;
  12858. +#endif
  12859. +
  12860. +#ifdef DWC_NETBSD
  12861. +typedef struct dwc_dmactx {
  12862. + struct device *dev;
  12863. + bus_dma_tag_t dma_tag;
  12864. + bus_dmamap_t dma_map;
  12865. + bus_dma_segment_t segs[1];
  12866. + int nsegs;
  12867. + bus_addr_t dma_paddr;
  12868. + void *dma_vaddr;
  12869. +} dwc_dmactx_t;
  12870. +#endif
  12871. +
  12872. +/* @todo these functions will be added in the future */
  12873. +#if 0
  12874. +/**
  12875. + * Creates a DMA pool from which you can allocate DMA buffers. Buffers
  12876. + * allocated from this pool will be guaranteed to meet the size, alignment, and
  12877. + * boundary requirements specified.
  12878. + *
  12879. + * @param[in] size Specifies the size of the buffers that will be allocated from
  12880. + * this pool.
  12881. + * @param[in] align Specifies the byte alignment requirements of the buffers
  12882. + * allocated from this pool. Must be a power of 2.
  12883. + * @param[in] boundary Specifies the N-byte boundary that buffers allocated from
  12884. + * this pool must not cross.
  12885. + *
  12886. + * @returns A pointer to an internal opaque structure which is not to be
  12887. + * accessed outside of these library functions. Use this handle to specify
  12888. + * which pools to allocate/free DMA buffers from and also to destroy the pool,
  12889. + * when you are done with it.
  12890. + */
  12891. +extern dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, uint32_t align, uint32_t boundary);
  12892. +
  12893. +/**
  12894. + * Destroy a DMA pool. All buffers allocated from that pool must be freed first.
  12895. + */
  12896. +extern void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool);
  12897. +
  12898. +/**
  12899. + * Allocate a buffer from the specified DMA pool and zeros its contents.
  12900. + */
  12901. +extern void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr);
  12902. +
  12903. +/**
  12904. + * Free a previously allocated buffer from the DMA pool.
  12905. + */
  12906. +extern void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr);
  12907. +#endif
  12908. +
  12909. +/** Allocates a DMA capable buffer and zeroes its contents. */
  12910. +extern void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr);
  12911. +
  12912. +/** Allocates a DMA capable buffer and zeroes its contents in atomic contest */
  12913. +extern void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr);
  12914. +
  12915. +/** Frees a previously allocated buffer. */
  12916. +extern void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr);
  12917. +
  12918. +/** Allocates a block of memory and zeroes its contents. */
  12919. +extern void *__DWC_ALLOC(void *mem_ctx, uint32_t size);
  12920. +
  12921. +/** Allocates a block of memory and zeroes its contents, in an atomic manner
  12922. + * which can be used inside interrupt context. The size should be sufficiently
  12923. + * small, a few KB at most, such that failures are not likely to occur. Can just call
  12924. + * __DWC_ALLOC if it is atomic. */
  12925. +extern void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size);
  12926. +
  12927. +/** Frees a previously allocated buffer. */
  12928. +extern void __DWC_FREE(void *mem_ctx, void *addr);
  12929. +
  12930. +#ifndef DWC_DEBUG_MEMORY
  12931. +
  12932. +#define DWC_ALLOC(_size_) __DWC_ALLOC(NULL, _size_)
  12933. +#define DWC_ALLOC_ATOMIC(_size_) __DWC_ALLOC_ATOMIC(NULL, _size_)
  12934. +#define DWC_FREE(_addr_) __DWC_FREE(NULL, _addr_)
  12935. +
  12936. +# ifdef DWC_LINUX
  12937. +#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(NULL, _size_, _dma_)
  12938. +#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(NULL, _size_,_dma_)
  12939. +#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(NULL, _size_, _virt_, _dma_)
  12940. +# endif
  12941. +
  12942. +# if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
  12943. +#define DWC_DMA_ALLOC __DWC_DMA_ALLOC
  12944. +#define DWC_DMA_FREE __DWC_DMA_FREE
  12945. +# endif
  12946. +extern void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line);
  12947. +
  12948. +#else /* DWC_DEBUG_MEMORY */
  12949. +
  12950. +extern void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line);
  12951. +extern void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, int line);
  12952. +extern void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line);
  12953. +extern void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
  12954. + char const *func, int line);
  12955. +extern void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
  12956. + char const *func, int line);
  12957. +extern void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr,
  12958. + dwc_dma_t dma_addr, char const *func, int line);
  12959. +
  12960. +extern int dwc_memory_debug_start(void *mem_ctx);
  12961. +extern void dwc_memory_debug_stop(void);
  12962. +extern void dwc_memory_debug_report(void);
  12963. +
  12964. +#define DWC_ALLOC(_size_) dwc_alloc_debug(NULL, _size_, __func__, __LINE__)
  12965. +#define DWC_ALLOC_ATOMIC(_size_) dwc_alloc_atomic_debug(NULL, _size_, \
  12966. + __func__, __LINE__)
  12967. +#define DWC_FREE(_addr_) dwc_free_debug(NULL, _addr_, __func__, __LINE__)
  12968. +
  12969. +# ifdef DWC_LINUX
  12970. +#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(NULL, _size_, \
  12971. + _dma_, __func__, __LINE__)
  12972. +#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(NULL, _size_, \
  12973. + _dma_, __func__, __LINE__)
  12974. +#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(NULL, _size_, \
  12975. + _virt_, _dma_, __func__, __LINE__)
  12976. +# endif
  12977. +
  12978. +# if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
  12979. +#define DWC_DMA_ALLOC(_ctx_,_size_,_dma_) dwc_dma_alloc_debug(_ctx_, _size_, \
  12980. + _dma_, __func__, __LINE__)
  12981. +#define DWC_DMA_FREE(_ctx_,_size_,_virt_,_dma_) dwc_dma_free_debug(_ctx_, _size_, \
  12982. + _virt_, _dma_, __func__, __LINE__)
  12983. +# endif
  12984. +
  12985. +#endif /* DWC_DEBUG_MEMORY */
  12986. +
  12987. +#define dwc_alloc(_ctx_,_size_) DWC_ALLOC(_size_)
  12988. +#define dwc_alloc_atomic(_ctx_,_size_) DWC_ALLOC_ATOMIC(_size_)
  12989. +#define dwc_free(_ctx_,_addr_) DWC_FREE(_addr_)
  12990. +
  12991. +#ifdef DWC_LINUX
  12992. +/* Linux doesn't need any extra parameters for DMA buffer allocation, so we
  12993. + * just throw away the DMA context parameter.
  12994. + */
  12995. +#define dwc_dma_alloc(_ctx_,_size_,_dma_) DWC_DMA_ALLOC(_size_, _dma_)
  12996. +#define dwc_dma_alloc_atomic(_ctx_,_size_,_dma_) DWC_DMA_ALLOC_ATOMIC(_size_, _dma_)
  12997. +#define dwc_dma_free(_ctx_,_size_,_virt_,_dma_) DWC_DMA_FREE(_size_, _virt_, _dma_)
  12998. +#endif
  12999. +
  13000. +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
  13001. +/** BSD needs several extra parameters for DMA buffer allocation, so we pass
  13002. + * them in using the DMA context parameter.
  13003. + */
  13004. +#define dwc_dma_alloc DWC_DMA_ALLOC
  13005. +#define dwc_dma_free DWC_DMA_FREE
  13006. +#endif
  13007. +
  13008. +
  13009. +/** @name Memory and String Processing */
  13010. +
  13011. +/** memset() clone */
  13012. +extern void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size);
  13013. +#define dwc_memset DWC_MEMSET
  13014. +
  13015. +/** memcpy() clone */
  13016. +extern void *DWC_MEMCPY(void *dest, void const *src, uint32_t size);
  13017. +#define dwc_memcpy DWC_MEMCPY
  13018. +
  13019. +/** memmove() clone */
  13020. +extern void *DWC_MEMMOVE(void *dest, void *src, uint32_t size);
  13021. +#define dwc_memmove DWC_MEMMOVE
  13022. +
  13023. +/** memcmp() clone */
  13024. +extern int DWC_MEMCMP(void *m1, void *m2, uint32_t size);
  13025. +#define dwc_memcmp DWC_MEMCMP
  13026. +
  13027. +/** strcmp() clone */
  13028. +extern int DWC_STRCMP(void *s1, void *s2);
  13029. +#define dwc_strcmp DWC_STRCMP
  13030. +
  13031. +/** strncmp() clone */
  13032. +extern int DWC_STRNCMP(void *s1, void *s2, uint32_t size);
  13033. +#define dwc_strncmp DWC_STRNCMP
  13034. +
  13035. +/** strlen() clone, for NULL terminated ASCII strings */
  13036. +extern int DWC_STRLEN(char const *str);
  13037. +#define dwc_strlen DWC_STRLEN
  13038. +
  13039. +/** strcpy() clone, for NULL terminated ASCII strings */
  13040. +extern char *DWC_STRCPY(char *to, const char *from);
  13041. +#define dwc_strcpy DWC_STRCPY
  13042. +
  13043. +/** strdup() clone. If you wish to use memory allocation debugging, this
  13044. + * implementation of strdup should use the DWC_* memory routines instead of
  13045. + * calling a predefined strdup. Otherwise the memory allocated by this routine
  13046. + * will not be seen by the debugging routines. */
  13047. +extern char *DWC_STRDUP(char const *str);
  13048. +#define dwc_strdup(_ctx_,_str_) DWC_STRDUP(_str_)
  13049. +
  13050. +/** NOT an atoi() clone. Read the description carefully. Returns an integer
  13051. + * converted from the string str in base 10 unless the string begins with a "0x"
  13052. + * in which case it is base 16. String must be a NULL terminated sequence of
  13053. + * ASCII characters and may optionally begin with whitespace, a + or -, and a
  13054. + * "0x" prefix if base 16. The remaining characters must be valid digits for
  13055. + * the number and end with a NULL character. If any invalid characters are
  13056. + * encountered or it returns with a negative error code and the results of the
  13057. + * conversion are undefined. On sucess it returns 0. Overflow conditions are
  13058. + * undefined. An example implementation using atoi() can be referenced from the
  13059. + * Linux implementation. */
  13060. +extern int DWC_ATOI(const char *str, int32_t *value);
  13061. +#define dwc_atoi DWC_ATOI
  13062. +
  13063. +/** Same as above but for unsigned. */
  13064. +extern int DWC_ATOUI(const char *str, uint32_t *value);
  13065. +#define dwc_atoui DWC_ATOUI
  13066. +
  13067. +#ifdef DWC_UTFLIB
  13068. +/** This routine returns a UTF16LE unicode encoded string from a UTF8 string. */
  13069. +extern int DWC_UTF8_TO_UTF16LE(uint8_t const *utf8string, uint16_t *utf16string, unsigned len);
  13070. +#define dwc_utf8_to_utf16le DWC_UTF8_TO_UTF16LE
  13071. +#endif
  13072. +
  13073. +
  13074. +/** @name Wait queues
  13075. + *
  13076. + * Wait queues provide a means of synchronizing between threads or processes. A
  13077. + * process can block on a waitq if some condition is not true, waiting for it to
  13078. + * become true. When the waitq is triggered all waiting process will get
  13079. + * unblocked and the condition will be check again. Waitqs should be triggered
  13080. + * every time a condition can potentially change.*/
  13081. +struct dwc_waitq;
  13082. +
  13083. +/** Type for a waitq */
  13084. +typedef struct dwc_waitq dwc_waitq_t;
  13085. +
  13086. +/** The type of waitq condition callback function. This is called every time
  13087. + * condition is evaluated. */
  13088. +typedef int (*dwc_waitq_condition_t)(void *data);
  13089. +
  13090. +/** Allocate a waitq */
  13091. +extern dwc_waitq_t *DWC_WAITQ_ALLOC(void);
  13092. +#define dwc_waitq_alloc(_ctx_) DWC_WAITQ_ALLOC()
  13093. +
  13094. +/** Free a waitq */
  13095. +extern void DWC_WAITQ_FREE(dwc_waitq_t *wq);
  13096. +#define dwc_waitq_free DWC_WAITQ_FREE
  13097. +
  13098. +/** Check the condition and if it is false, block on the waitq. When unblocked, check the
  13099. + * condition again. The function returns when the condition becomes true. The return value
  13100. + * is 0 on condition true, DWC_WAITQ_ABORTED on abort or killed, or DWC_WAITQ_UNKNOWN on error. */
  13101. +extern int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data);
  13102. +#define dwc_waitq_wait DWC_WAITQ_WAIT
  13103. +
  13104. +/** Check the condition and if it is false, block on the waitq. When unblocked,
  13105. + * check the condition again. The function returns when the condition become
  13106. + * true or the timeout has passed. The return value is 0 on condition true or
  13107. + * DWC_TIMED_OUT on timeout, or DWC_WAITQ_ABORTED, or DWC_WAITQ_UNKNOWN on
  13108. + * error. */
  13109. +extern int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
  13110. + void *data, int32_t msecs);
  13111. +#define dwc_waitq_wait_timeout DWC_WAITQ_WAIT_TIMEOUT
  13112. +
  13113. +/** Trigger a waitq, unblocking all processes. This should be called whenever a condition
  13114. + * has potentially changed. */
  13115. +extern void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq);
  13116. +#define dwc_waitq_trigger DWC_WAITQ_TRIGGER
  13117. +
  13118. +/** Unblock all processes waiting on the waitq with an ABORTED result. */
  13119. +extern void DWC_WAITQ_ABORT(dwc_waitq_t *wq);
  13120. +#define dwc_waitq_abort DWC_WAITQ_ABORT
  13121. +
  13122. +
  13123. +/** @name Threads
  13124. + *
  13125. + * A thread must be explicitly stopped. It must check DWC_THREAD_SHOULD_STOP
  13126. + * whenever it is woken up, and then return. The DWC_THREAD_STOP function
  13127. + * returns the value from the thread.
  13128. + */
  13129. +
  13130. +struct dwc_thread;
  13131. +
  13132. +/** Type for a thread */
  13133. +typedef struct dwc_thread dwc_thread_t;
  13134. +
  13135. +/** The thread function */
  13136. +typedef int (*dwc_thread_function_t)(void *data);
  13137. +
  13138. +/** Create a thread and start it running the thread_function. Returns a handle
  13139. + * to the thread */
  13140. +extern dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data);
  13141. +#define dwc_thread_run(_ctx_,_func_,_name_,_data_) DWC_THREAD_RUN(_func_, _name_, _data_)
  13142. +
  13143. +/** Stops a thread. Return the value returned by the thread. Or will return
  13144. + * DWC_ABORT if the thread never started. */
  13145. +extern int DWC_THREAD_STOP(dwc_thread_t *thread);
  13146. +#define dwc_thread_stop DWC_THREAD_STOP
  13147. +
  13148. +/** Signifies to the thread that it must stop. */
  13149. +#ifdef DWC_LINUX
  13150. +/* Linux doesn't need any parameters for kthread_should_stop() */
  13151. +extern dwc_bool_t DWC_THREAD_SHOULD_STOP(void);
  13152. +#define dwc_thread_should_stop(_thrd_) DWC_THREAD_SHOULD_STOP()
  13153. +
  13154. +/* No thread_exit function in Linux */
  13155. +#define dwc_thread_exit(_thrd_)
  13156. +#endif
  13157. +
  13158. +#if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
  13159. +/** BSD needs the thread pointer for kthread_suspend_check() */
  13160. +extern dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread);
  13161. +#define dwc_thread_should_stop DWC_THREAD_SHOULD_STOP
  13162. +
  13163. +/** The thread must call this to exit. */
  13164. +extern void DWC_THREAD_EXIT(dwc_thread_t *thread);
  13165. +#define dwc_thread_exit DWC_THREAD_EXIT
  13166. +#endif
  13167. +
  13168. +
  13169. +/** @name Work queues
  13170. + *
  13171. + * Workqs are used to queue a callback function to be called at some later time,
  13172. + * in another thread. */
  13173. +struct dwc_workq;
  13174. +
  13175. +/** Type for a workq */
  13176. +typedef struct dwc_workq dwc_workq_t;
  13177. +
  13178. +/** The type of the callback function to be called. */
  13179. +typedef void (*dwc_work_callback_t)(void *data);
  13180. +
  13181. +/** Allocate a workq */
  13182. +extern dwc_workq_t *DWC_WORKQ_ALLOC(char *name);
  13183. +#define dwc_workq_alloc(_ctx_,_name_) DWC_WORKQ_ALLOC(_name_)
  13184. +
  13185. +/** Free a workq. All work must be completed before being freed. */
  13186. +extern void DWC_WORKQ_FREE(dwc_workq_t *workq);
  13187. +#define dwc_workq_free DWC_WORKQ_FREE
  13188. +
  13189. +/** Schedule a callback on the workq, passing in data. The function will be
  13190. + * scheduled at some later time. */
  13191. +extern void DWC_WORKQ_SCHEDULE(dwc_workq_t *workq, dwc_work_callback_t cb,
  13192. + void *data, char *format, ...)
  13193. +#ifdef __GNUC__
  13194. + __attribute__ ((format(printf, 4, 5)));
  13195. +#else
  13196. + ;
  13197. +#endif
  13198. +#define dwc_workq_schedule DWC_WORKQ_SCHEDULE
  13199. +
  13200. +/** Schedule a callback on the workq, that will be called until at least
  13201. + * given number miliseconds have passed. */
  13202. +extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t cb,
  13203. + void *data, uint32_t time, char *format, ...)
  13204. +#ifdef __GNUC__
  13205. + __attribute__ ((format(printf, 5, 6)));
  13206. +#else
  13207. + ;
  13208. +#endif
  13209. +#define dwc_workq_schedule_delayed DWC_WORKQ_SCHEDULE_DELAYED
  13210. +
  13211. +/** The number of processes in the workq */
  13212. +extern int DWC_WORKQ_PENDING(dwc_workq_t *workq);
  13213. +#define dwc_workq_pending DWC_WORKQ_PENDING
  13214. +
  13215. +/** Blocks until all the work in the workq is complete or timed out. Returns <
  13216. + * 0 on timeout. */
  13217. +extern int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout);
  13218. +#define dwc_workq_wait_work_done DWC_WORKQ_WAIT_WORK_DONE
  13219. +
  13220. +
  13221. +/** @name Tasklets
  13222. + *
  13223. + */
  13224. +struct dwc_tasklet;
  13225. +
  13226. +/** Type for a tasklet */
  13227. +typedef struct dwc_tasklet dwc_tasklet_t;
  13228. +
  13229. +/** The type of the callback function to be called */
  13230. +typedef void (*dwc_tasklet_callback_t)(void *data);
  13231. +
  13232. +/** Allocates a tasklet */
  13233. +extern dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data);
  13234. +#define dwc_task_alloc(_ctx_,_name_,_cb_,_data_) DWC_TASK_ALLOC(_name_, _cb_, _data_)
  13235. +
  13236. +/** Frees a tasklet */
  13237. +extern void DWC_TASK_FREE(dwc_tasklet_t *task);
  13238. +#define dwc_task_free DWC_TASK_FREE
  13239. +
  13240. +/** Schedules a tasklet to run */
  13241. +extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task);
  13242. +#define dwc_task_schedule DWC_TASK_SCHEDULE
  13243. +
  13244. +
  13245. +/** @name Timer
  13246. + *
  13247. + * Callbacks must be small and atomic.
  13248. + */
  13249. +struct dwc_timer;
  13250. +
  13251. +/** Type for a timer */
  13252. +typedef struct dwc_timer dwc_timer_t;
  13253. +
  13254. +/** The type of the callback function to be called */
  13255. +typedef void (*dwc_timer_callback_t)(void *data);
  13256. +
  13257. +/** Allocates a timer */
  13258. +extern dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data);
  13259. +#define dwc_timer_alloc(_ctx_,_name_,_cb_,_data_) DWC_TIMER_ALLOC(_name_,_cb_,_data_)
  13260. +
  13261. +/** Frees a timer */
  13262. +extern void DWC_TIMER_FREE(dwc_timer_t *timer);
  13263. +#define dwc_timer_free DWC_TIMER_FREE
  13264. +
  13265. +/** Schedules the timer to run at time ms from now. And will repeat at every
  13266. + * repeat_interval msec therafter
  13267. + *
  13268. + * Modifies a timer that is still awaiting execution to a new expiration time.
  13269. + * The mod_time is added to the old time. */
  13270. +extern void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time);
  13271. +#define dwc_timer_schedule DWC_TIMER_SCHEDULE
  13272. +
  13273. +/** Disables the timer from execution. */
  13274. +extern void DWC_TIMER_CANCEL(dwc_timer_t *timer);
  13275. +#define dwc_timer_cancel DWC_TIMER_CANCEL
  13276. +
  13277. +
  13278. +/** @name Spinlocks
  13279. + *
  13280. + * These locks are used when the work between the lock/unlock is atomic and
  13281. + * short. Interrupts are also disabled during the lock/unlock and thus they are
  13282. + * suitable to lock between interrupt/non-interrupt context. They also lock
  13283. + * between processes if you have multiple CPUs or Preemption. If you don't have
  13284. + * multiple CPUS or Preemption, then the you can simply implement the
  13285. + * DWC_SPINLOCK and DWC_SPINUNLOCK to disable and enable interrupts. Because
  13286. + * the work between the lock/unlock is atomic, the process context will never
  13287. + * change, and so you never have to lock between processes. */
  13288. +
  13289. +struct dwc_spinlock;
  13290. +
  13291. +/** Type for a spinlock */
  13292. +typedef struct dwc_spinlock dwc_spinlock_t;
  13293. +
  13294. +/** Type for the 'flags' argument to spinlock funtions */
  13295. +typedef unsigned long dwc_irqflags_t;
  13296. +
  13297. +/** Returns an initialized lock variable. This function should allocate and
  13298. + * initialize the OS-specific data structure used for locking. This data
  13299. + * structure is to be used for the DWC_LOCK and DWC_UNLOCK functions and should
  13300. + * be freed by the DWC_FREE_LOCK when it is no longer used.
  13301. + *
  13302. + * For Linux Spinlock Debugging make it macro because the debugging routines use
  13303. + * the symbol name to determine recursive locking. Using a wrapper function
  13304. + * makes it falsely think recursive locking occurs. */
  13305. +#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_SPINLOCK)
  13306. +#define DWC_SPINLOCK_ALLOC_LINUX_DEBUG(lock) ({ \
  13307. + lock = DWC_ALLOC(sizeof(spinlock_t)); \
  13308. + if (lock) { \
  13309. + spin_lock_init((spinlock_t *)lock); \
  13310. + } \
  13311. +})
  13312. +#else
  13313. +extern dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void);
  13314. +#define dwc_spinlock_alloc(_ctx_) DWC_SPINLOCK_ALLOC()
  13315. +#endif
  13316. +
  13317. +/** Frees an initialized lock variable. */
  13318. +extern void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock);
  13319. +#define dwc_spinlock_free(_ctx_,_lock_) DWC_SPINLOCK_FREE(_lock_)
  13320. +
  13321. +/** Disables interrupts and blocks until it acquires the lock.
  13322. + *
  13323. + * @param lock Pointer to the spinlock.
  13324. + * @param flags Unsigned long for irq flags storage.
  13325. + */
  13326. +extern void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags);
  13327. +#define dwc_spinlock_irqsave DWC_SPINLOCK_IRQSAVE
  13328. +
  13329. +/** Re-enables the interrupt and releases the lock.
  13330. + *
  13331. + * @param lock Pointer to the spinlock.
  13332. + * @param flags Unsigned long for irq flags storage. Must be the same as was
  13333. + * passed into DWC_LOCK.
  13334. + */
  13335. +extern void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags);
  13336. +#define dwc_spinunlock_irqrestore DWC_SPINUNLOCK_IRQRESTORE
  13337. +
  13338. +/** Blocks until it acquires the lock.
  13339. + *
  13340. + * @param lock Pointer to the spinlock.
  13341. + */
  13342. +extern void DWC_SPINLOCK(dwc_spinlock_t *lock);
  13343. +#define dwc_spinlock DWC_SPINLOCK
  13344. +
  13345. +/** Releases the lock.
  13346. + *
  13347. + * @param lock Pointer to the spinlock.
  13348. + */
  13349. +extern void DWC_SPINUNLOCK(dwc_spinlock_t *lock);
  13350. +#define dwc_spinunlock DWC_SPINUNLOCK
  13351. +
  13352. +
  13353. +/** @name Mutexes
  13354. + *
  13355. + * Unlike spinlocks Mutexes lock only between processes and the work between the
  13356. + * lock/unlock CAN block, therefore it CANNOT be called from interrupt context.
  13357. + */
  13358. +
  13359. +struct dwc_mutex;
  13360. +
  13361. +/** Type for a mutex */
  13362. +typedef struct dwc_mutex dwc_mutex_t;
  13363. +
  13364. +/* For Linux Mutex Debugging make it inline because the debugging routines use
  13365. + * the symbol to determine recursive locking. This makes it falsely think
  13366. + * recursive locking occurs. */
  13367. +#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)
  13368. +#define DWC_MUTEX_ALLOC_LINUX_DEBUG(__mutexp) ({ \
  13369. + __mutexp = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); \
  13370. + mutex_init((struct mutex *)__mutexp); \
  13371. +})
  13372. +#endif
  13373. +
  13374. +/** Allocate a mutex */
  13375. +extern dwc_mutex_t *DWC_MUTEX_ALLOC(void);
  13376. +#define dwc_mutex_alloc(_ctx_) DWC_MUTEX_ALLOC()
  13377. +
  13378. +/* For memory leak debugging when using Linux Mutex Debugging */
  13379. +#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)
  13380. +#define DWC_MUTEX_FREE(__mutexp) do { \
  13381. + mutex_destroy((struct mutex *)__mutexp); \
  13382. + DWC_FREE(__mutexp); \
  13383. +} while(0)
  13384. +#else
  13385. +/** Free a mutex */
  13386. +extern void DWC_MUTEX_FREE(dwc_mutex_t *mutex);
  13387. +#define dwc_mutex_free(_ctx_,_mutex_) DWC_MUTEX_FREE(_mutex_)
  13388. +#endif
  13389. +
  13390. +/** Lock a mutex */
  13391. +extern void DWC_MUTEX_LOCK(dwc_mutex_t *mutex);
  13392. +#define dwc_mutex_lock DWC_MUTEX_LOCK
  13393. +
  13394. +/** Non-blocking lock returns 1 on successful lock. */
  13395. +extern int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex);
  13396. +#define dwc_mutex_trylock DWC_MUTEX_TRYLOCK
  13397. +
  13398. +/** Unlock a mutex */
  13399. +extern void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex);
  13400. +#define dwc_mutex_unlock DWC_MUTEX_UNLOCK
  13401. +
  13402. +
  13403. +/** @name Time */
  13404. +
  13405. +/** Microsecond delay.
  13406. + *
  13407. + * @param usecs Microseconds to delay.
  13408. + */
  13409. +extern void DWC_UDELAY(uint32_t usecs);
  13410. +#define dwc_udelay DWC_UDELAY
  13411. +
  13412. +/** Millisecond delay.
  13413. + *
  13414. + * @param msecs Milliseconds to delay.
  13415. + */
  13416. +extern void DWC_MDELAY(uint32_t msecs);
  13417. +#define dwc_mdelay DWC_MDELAY
  13418. +
  13419. +/** Non-busy waiting.
  13420. + * Sleeps for specified number of milliseconds.
  13421. + *
  13422. + * @param msecs Milliseconds to sleep.
  13423. + */
  13424. +extern void DWC_MSLEEP(uint32_t msecs);
  13425. +#define dwc_msleep DWC_MSLEEP
  13426. +
  13427. +/**
  13428. + * Returns number of milliseconds since boot.
  13429. + */
  13430. +extern uint32_t DWC_TIME(void);
  13431. +#define dwc_time DWC_TIME
  13432. +
  13433. +
  13434. +
  13435. +
  13436. +/* @mainpage DWC Portability and Common Library
  13437. + *
  13438. + * This is the documentation for the DWC Portability and Common Library.
  13439. + *
  13440. + * @section intro Introduction
  13441. + *
  13442. + * The DWC Portability library consists of wrapper calls and data structures to
  13443. + * all low-level functions which are typically provided by the OS. The WUDEV
  13444. + * driver uses only these functions. In order to port the WUDEV driver, only
  13445. + * the functions in this library need to be re-implemented, with the same
  13446. + * behavior as documented here.
  13447. + *
  13448. + * The Common library consists of higher level functions, which rely only on
  13449. + * calling the functions from the DWC Portability library. These common
  13450. + * routines are shared across modules. Some of the common libraries need to be
  13451. + * used directly by the driver programmer when porting WUDEV. Such as the
  13452. + * parameter and notification libraries.
  13453. + *
  13454. + * @section low Portability Library OS Wrapper Functions
  13455. + *
  13456. + * Any function starting with DWC and in all CAPS is a low-level OS-wrapper that
  13457. + * needs to be implemented when porting, for example DWC_MUTEX_ALLOC(). All of
  13458. + * these functions are included in the dwc_os.h file.
  13459. + *
  13460. + * There are many functions here covering a wide array of OS services. Please
  13461. + * see dwc_os.h for details, and implementation notes for each function.
  13462. + *
  13463. + * @section common Common Library Functions
  13464. + *
  13465. + * Any function starting with dwc and in all lowercase is a common library
  13466. + * routine. These functions have a portable implementation and do not need to
  13467. + * be reimplemented when porting. The common routines can be used by any
  13468. + * driver, and some must be used by the end user to control the drivers. For
  13469. + * example, you must use the Parameter common library in order to set the
  13470. + * parameters in the WUDEV module.
  13471. + *
  13472. + * The common libraries consist of the following:
  13473. + *
  13474. + * - Connection Contexts - Used internally and can be used by end-user. See dwc_cc.h
  13475. + * - Parameters - Used internally and can be used by end-user. See dwc_params.h
  13476. + * - Notifications - Used internally and can be used by end-user. See dwc_notifier.h
  13477. + * - Lists - Used internally and can be used by end-user. See dwc_list.h
  13478. + * - Memory Debugging - Used internally and can be used by end-user. See dwc_os.h
  13479. + * - Modpow - Used internally only. See dwc_modpow.h
  13480. + * - DH - Used internally only. See dwc_dh.h
  13481. + * - Crypto - Used internally only. See dwc_crypto.h
  13482. + *
  13483. + *
  13484. + * @section prereq Prerequistes For dwc_os.h
  13485. + * @subsection types Data Types
  13486. + *
  13487. + * The dwc_os.h file assumes that several low-level data types are pre defined for the
  13488. + * compilation environment. These data types are:
  13489. + *
  13490. + * - uint8_t - unsigned 8-bit data type
  13491. + * - int8_t - signed 8-bit data type
  13492. + * - uint16_t - unsigned 16-bit data type
  13493. + * - int16_t - signed 16-bit data type
  13494. + * - uint32_t - unsigned 32-bit data type
  13495. + * - int32_t - signed 32-bit data type
  13496. + * - uint64_t - unsigned 64-bit data type
  13497. + * - int64_t - signed 64-bit data type
  13498. + *
  13499. + * Ensure that these are defined before using dwc_os.h. The easiest way to do
  13500. + * that is to modify the top of the file to include the appropriate header.
  13501. + * This is already done for the Linux environment. If the DWC_LINUX macro is
  13502. + * defined, the correct header will be added. A standard header <stdint.h> is
  13503. + * also used for environments where standard C headers are available.
  13504. + *
  13505. + * @subsection stdarg Variable Arguments
  13506. + *
  13507. + * Variable arguments are provided by a standard C header <stdarg.h>. it is
  13508. + * available in Both the Linux and ANSI C enviornment. An equivalent must be
  13509. + * provided in your enviornment in order to use dwc_os.h with the debug and
  13510. + * tracing message functionality.
  13511. + *
  13512. + * @subsection thread Threading
  13513. + *
  13514. + * WUDEV Core must be run on an operating system that provides for multiple
  13515. + * threads/processes. Threading can be implemented in many ways, even in
  13516. + * embedded systems without an operating system. At the bare minimum, the
  13517. + * system should be able to start any number of processes at any time to handle
  13518. + * special work. It need not be a pre-emptive system. Process context can
  13519. + * change upon a call to a blocking function. The hardware interrupt context
  13520. + * that calls the module's ISR() function must be differentiable from process
  13521. + * context, even if your processes are impemented via a hardware interrupt.
  13522. + * Further locking mechanism between process must exist (or be implemented), and
  13523. + * process context must have a way to disable interrupts for a period of time to
  13524. + * lock them out. If all of this exists, the functions in dwc_os.h related to
  13525. + * threading should be able to be implemented with the defined behavior.
  13526. + *
  13527. + */
  13528. +
  13529. +#ifdef __cplusplus
  13530. +}
  13531. +#endif
  13532. +
  13533. +#endif /* _DWC_OS_H_ */
  13534. --- /dev/null
  13535. +++ b/drivers/usb/host/dwc_common_port/usb.h
  13536. @@ -0,0 +1,946 @@
  13537. +/*
  13538. + * Copyright (c) 1998 The NetBSD Foundation, Inc.
  13539. + * All rights reserved.
  13540. + *
  13541. + * This code is derived from software contributed to The NetBSD Foundation
  13542. + * by Lennart Augustsson (lennart@augustsson.net) at
  13543. + * Carlstedt Research & Technology.
  13544. + *
  13545. + * Redistribution and use in source and binary forms, with or without
  13546. + * modification, are permitted provided that the following conditions
  13547. + * are met:
  13548. + * 1. Redistributions of source code must retain the above copyright
  13549. + * notice, this list of conditions and the following disclaimer.
  13550. + * 2. Redistributions in binary form must reproduce the above copyright
  13551. + * notice, this list of conditions and the following disclaimer in the
  13552. + * documentation and/or other materials provided with the distribution.
  13553. + * 3. All advertising materials mentioning features or use of this software
  13554. + * must display the following acknowledgement:
  13555. + * This product includes software developed by the NetBSD
  13556. + * Foundation, Inc. and its contributors.
  13557. + * 4. Neither the name of The NetBSD Foundation nor the names of its
  13558. + * contributors may be used to endorse or promote products derived
  13559. + * from this software without specific prior written permission.
  13560. + *
  13561. + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  13562. + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  13563. + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  13564. + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  13565. + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  13566. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  13567. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  13568. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  13569. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  13570. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  13571. + * POSSIBILITY OF SUCH DAMAGE.
  13572. + */
  13573. +
  13574. +/* Modified by Synopsys, Inc, 12/12/2007 */
  13575. +
  13576. +
  13577. +#ifndef _USB_H_
  13578. +#define _USB_H_
  13579. +
  13580. +#ifdef __cplusplus
  13581. +extern "C" {
  13582. +#endif
  13583. +
  13584. +/*
  13585. + * The USB records contain some unaligned little-endian word
  13586. + * components. The U[SG]ETW macros take care of both the alignment
  13587. + * and endian problem and should always be used to access non-byte
  13588. + * values.
  13589. + */
  13590. +typedef u_int8_t uByte;
  13591. +typedef u_int8_t uWord[2];
  13592. +typedef u_int8_t uDWord[4];
  13593. +
  13594. +#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h))
  13595. +#define UCONSTW(x) { (x) & 0xff, ((x) >> 8) & 0xff }
  13596. +#define UCONSTDW(x) { (x) & 0xff, ((x) >> 8) & 0xff, \
  13597. + ((x) >> 16) & 0xff, ((x) >> 24) & 0xff }
  13598. +
  13599. +#if 1
  13600. +#define UGETW(w) ((w)[0] | ((w)[1] << 8))
  13601. +#define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8))
  13602. +#define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24))
  13603. +#define USETDW(w,v) ((w)[0] = (u_int8_t)(v), \
  13604. + (w)[1] = (u_int8_t)((v) >> 8), \
  13605. + (w)[2] = (u_int8_t)((v) >> 16), \
  13606. + (w)[3] = (u_int8_t)((v) >> 24))
  13607. +#else
  13608. +/*
  13609. + * On little-endian machines that can handle unanliged accesses
  13610. + * (e.g. i386) these macros can be replaced by the following.
  13611. + */
  13612. +#define UGETW(w) (*(u_int16_t *)(w))
  13613. +#define USETW(w,v) (*(u_int16_t *)(w) = (v))
  13614. +#define UGETDW(w) (*(u_int32_t *)(w))
  13615. +#define USETDW(w,v) (*(u_int32_t *)(w) = (v))
  13616. +#endif
  13617. +
  13618. +/*
  13619. + * Macros for accessing UAS IU fields, which are big-endian
  13620. + */
  13621. +#define IUSETW2(w,h,l) ((w)[0] = (u_int8_t)(h), (w)[1] = (u_int8_t)(l))
  13622. +#define IUCONSTW(x) { ((x) >> 8) & 0xff, (x) & 0xff }
  13623. +#define IUCONSTDW(x) { ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \
  13624. + ((x) >> 8) & 0xff, (x) & 0xff }
  13625. +#define IUGETW(w) (((w)[0] << 8) | (w)[1])
  13626. +#define IUSETW(w,v) ((w)[0] = (u_int8_t)((v) >> 8), (w)[1] = (u_int8_t)(v))
  13627. +#define IUGETDW(w) (((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3])
  13628. +#define IUSETDW(w,v) ((w)[0] = (u_int8_t)((v) >> 24), \
  13629. + (w)[1] = (u_int8_t)((v) >> 16), \
  13630. + (w)[2] = (u_int8_t)((v) >> 8), \
  13631. + (w)[3] = (u_int8_t)(v))
  13632. +
  13633. +#define UPACKED __attribute__((__packed__))
  13634. +
  13635. +typedef struct {
  13636. + uByte bmRequestType;
  13637. + uByte bRequest;
  13638. + uWord wValue;
  13639. + uWord wIndex;
  13640. + uWord wLength;
  13641. +} UPACKED usb_device_request_t;
  13642. +
  13643. +#define UT_GET_DIR(a) ((a) & 0x80)
  13644. +#define UT_WRITE 0x00
  13645. +#define UT_READ 0x80
  13646. +
  13647. +#define UT_GET_TYPE(a) ((a) & 0x60)
  13648. +#define UT_STANDARD 0x00
  13649. +#define UT_CLASS 0x20
  13650. +#define UT_VENDOR 0x40
  13651. +
  13652. +#define UT_GET_RECIPIENT(a) ((a) & 0x1f)
  13653. +#define UT_DEVICE 0x00
  13654. +#define UT_INTERFACE 0x01
  13655. +#define UT_ENDPOINT 0x02
  13656. +#define UT_OTHER 0x03
  13657. +
  13658. +#define UT_READ_DEVICE (UT_READ | UT_STANDARD | UT_DEVICE)
  13659. +#define UT_READ_INTERFACE (UT_READ | UT_STANDARD | UT_INTERFACE)
  13660. +#define UT_READ_ENDPOINT (UT_READ | UT_STANDARD | UT_ENDPOINT)
  13661. +#define UT_WRITE_DEVICE (UT_WRITE | UT_STANDARD | UT_DEVICE)
  13662. +#define UT_WRITE_INTERFACE (UT_WRITE | UT_STANDARD | UT_INTERFACE)
  13663. +#define UT_WRITE_ENDPOINT (UT_WRITE | UT_STANDARD | UT_ENDPOINT)
  13664. +#define UT_READ_CLASS_DEVICE (UT_READ | UT_CLASS | UT_DEVICE)
  13665. +#define UT_READ_CLASS_INTERFACE (UT_READ | UT_CLASS | UT_INTERFACE)
  13666. +#define UT_READ_CLASS_OTHER (UT_READ | UT_CLASS | UT_OTHER)
  13667. +#define UT_READ_CLASS_ENDPOINT (UT_READ | UT_CLASS | UT_ENDPOINT)
  13668. +#define UT_WRITE_CLASS_DEVICE (UT_WRITE | UT_CLASS | UT_DEVICE)
  13669. +#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE)
  13670. +#define UT_WRITE_CLASS_OTHER (UT_WRITE | UT_CLASS | UT_OTHER)
  13671. +#define UT_WRITE_CLASS_ENDPOINT (UT_WRITE | UT_CLASS | UT_ENDPOINT)
  13672. +#define UT_READ_VENDOR_DEVICE (UT_READ | UT_VENDOR | UT_DEVICE)
  13673. +#define UT_READ_VENDOR_INTERFACE (UT_READ | UT_VENDOR | UT_INTERFACE)
  13674. +#define UT_READ_VENDOR_OTHER (UT_READ | UT_VENDOR | UT_OTHER)
  13675. +#define UT_READ_VENDOR_ENDPOINT (UT_READ | UT_VENDOR | UT_ENDPOINT)
  13676. +#define UT_WRITE_VENDOR_DEVICE (UT_WRITE | UT_VENDOR | UT_DEVICE)
  13677. +#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE)
  13678. +#define UT_WRITE_VENDOR_OTHER (UT_WRITE | UT_VENDOR | UT_OTHER)
  13679. +#define UT_WRITE_VENDOR_ENDPOINT (UT_WRITE | UT_VENDOR | UT_ENDPOINT)
  13680. +
  13681. +/* Requests */
  13682. +#define UR_GET_STATUS 0x00
  13683. +#define USTAT_STANDARD_STATUS 0x00
  13684. +#define WUSTAT_WUSB_FEATURE 0x01
  13685. +#define WUSTAT_CHANNEL_INFO 0x02
  13686. +#define WUSTAT_RECEIVED_DATA 0x03
  13687. +#define WUSTAT_MAS_AVAILABILITY 0x04
  13688. +#define WUSTAT_CURRENT_TRANSMIT_POWER 0x05
  13689. +#define UR_CLEAR_FEATURE 0x01
  13690. +#define UR_SET_FEATURE 0x03
  13691. +#define UR_SET_AND_TEST_FEATURE 0x0c
  13692. +#define UR_SET_ADDRESS 0x05
  13693. +#define UR_GET_DESCRIPTOR 0x06
  13694. +#define UDESC_DEVICE 0x01
  13695. +#define UDESC_CONFIG 0x02
  13696. +#define UDESC_STRING 0x03
  13697. +#define UDESC_INTERFACE 0x04
  13698. +#define UDESC_ENDPOINT 0x05
  13699. +#define UDESC_SS_USB_COMPANION 0x30
  13700. +#define UDESC_DEVICE_QUALIFIER 0x06
  13701. +#define UDESC_OTHER_SPEED_CONFIGURATION 0x07
  13702. +#define UDESC_INTERFACE_POWER 0x08
  13703. +#define UDESC_OTG 0x09
  13704. +#define WUDESC_SECURITY 0x0c
  13705. +#define WUDESC_KEY 0x0d
  13706. +#define WUD_GET_KEY_INDEX(_wValue_) ((_wValue_) & 0xf)
  13707. +#define WUD_GET_KEY_TYPE(_wValue_) (((_wValue_) & 0x30) >> 4)
  13708. +#define WUD_KEY_TYPE_ASSOC 0x01
  13709. +#define WUD_KEY_TYPE_GTK 0x02
  13710. +#define WUD_GET_KEY_ORIGIN(_wValue_) (((_wValue_) & 0x40) >> 6)
  13711. +#define WUD_KEY_ORIGIN_HOST 0x00
  13712. +#define WUD_KEY_ORIGIN_DEVICE 0x01
  13713. +#define WUDESC_ENCRYPTION_TYPE 0x0e
  13714. +#define WUDESC_BOS 0x0f
  13715. +#define WUDESC_DEVICE_CAPABILITY 0x10
  13716. +#define WUDESC_WIRELESS_ENDPOINT_COMPANION 0x11
  13717. +#define UDESC_BOS 0x0f
  13718. +#define UDESC_DEVICE_CAPABILITY 0x10
  13719. +#define UDESC_CS_DEVICE 0x21 /* class specific */
  13720. +#define UDESC_CS_CONFIG 0x22
  13721. +#define UDESC_CS_STRING 0x23
  13722. +#define UDESC_CS_INTERFACE 0x24
  13723. +#define UDESC_CS_ENDPOINT 0x25
  13724. +#define UDESC_HUB 0x29
  13725. +#define UR_SET_DESCRIPTOR 0x07
  13726. +#define UR_GET_CONFIG 0x08
  13727. +#define UR_SET_CONFIG 0x09
  13728. +#define UR_GET_INTERFACE 0x0a
  13729. +#define UR_SET_INTERFACE 0x0b
  13730. +#define UR_SYNCH_FRAME 0x0c
  13731. +#define WUR_SET_ENCRYPTION 0x0d
  13732. +#define WUR_GET_ENCRYPTION 0x0e
  13733. +#define WUR_SET_HANDSHAKE 0x0f
  13734. +#define WUR_GET_HANDSHAKE 0x10
  13735. +#define WUR_SET_CONNECTION 0x11
  13736. +#define WUR_SET_SECURITY_DATA 0x12
  13737. +#define WUR_GET_SECURITY_DATA 0x13
  13738. +#define WUR_SET_WUSB_DATA 0x14
  13739. +#define WUDATA_DRPIE_INFO 0x01
  13740. +#define WUDATA_TRANSMIT_DATA 0x02
  13741. +#define WUDATA_TRANSMIT_PARAMS 0x03
  13742. +#define WUDATA_RECEIVE_PARAMS 0x04
  13743. +#define WUDATA_TRANSMIT_POWER 0x05
  13744. +#define WUR_LOOPBACK_DATA_WRITE 0x15
  13745. +#define WUR_LOOPBACK_DATA_READ 0x16
  13746. +#define WUR_SET_INTERFACE_DS 0x17
  13747. +
  13748. +/* Feature numbers */
  13749. +#define UF_ENDPOINT_HALT 0
  13750. +#define UF_DEVICE_REMOTE_WAKEUP 1
  13751. +#define UF_TEST_MODE 2
  13752. +#define UF_DEVICE_B_HNP_ENABLE 3
  13753. +#define UF_DEVICE_A_HNP_SUPPORT 4
  13754. +#define UF_DEVICE_A_ALT_HNP_SUPPORT 5
  13755. +#define WUF_WUSB 3
  13756. +#define WUF_TX_DRPIE 0x0
  13757. +#define WUF_DEV_XMIT_PACKET 0x1
  13758. +#define WUF_COUNT_PACKETS 0x2
  13759. +#define WUF_CAPTURE_PACKETS 0x3
  13760. +#define UF_FUNCTION_SUSPEND 0
  13761. +#define UF_U1_ENABLE 48
  13762. +#define UF_U2_ENABLE 49
  13763. +#define UF_LTM_ENABLE 50
  13764. +
  13765. +/* Class requests from the USB 2.0 hub spec, table 11-15 */
  13766. +#define UCR_CLEAR_HUB_FEATURE (0x2000 | UR_CLEAR_FEATURE)
  13767. +#define UCR_CLEAR_PORT_FEATURE (0x2300 | UR_CLEAR_FEATURE)
  13768. +#define UCR_GET_HUB_DESCRIPTOR (0xa000 | UR_GET_DESCRIPTOR)
  13769. +#define UCR_GET_HUB_STATUS (0xa000 | UR_GET_STATUS)
  13770. +#define UCR_GET_PORT_STATUS (0xa300 | UR_GET_STATUS)
  13771. +#define UCR_SET_HUB_FEATURE (0x2000 | UR_SET_FEATURE)
  13772. +#define UCR_SET_PORT_FEATURE (0x2300 | UR_SET_FEATURE)
  13773. +#define UCR_SET_AND_TEST_PORT_FEATURE (0xa300 | UR_SET_AND_TEST_FEATURE)
  13774. +
  13775. +#ifdef _MSC_VER
  13776. +#include <pshpack1.h>
  13777. +#endif
  13778. +
  13779. +typedef struct {
  13780. + uByte bLength;
  13781. + uByte bDescriptorType;
  13782. + uByte bDescriptorSubtype;
  13783. +} UPACKED usb_descriptor_t;
  13784. +
  13785. +typedef struct {
  13786. + uByte bLength;
  13787. + uByte bDescriptorType;
  13788. +} UPACKED usb_descriptor_header_t;
  13789. +
  13790. +typedef struct {
  13791. + uByte bLength;
  13792. + uByte bDescriptorType;
  13793. + uWord bcdUSB;
  13794. +#define UD_USB_2_0 0x0200
  13795. +#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0)
  13796. + uByte bDeviceClass;
  13797. + uByte bDeviceSubClass;
  13798. + uByte bDeviceProtocol;
  13799. + uByte bMaxPacketSize;
  13800. + /* The fields below are not part of the initial descriptor. */
  13801. + uWord idVendor;
  13802. + uWord idProduct;
  13803. + uWord bcdDevice;
  13804. + uByte iManufacturer;
  13805. + uByte iProduct;
  13806. + uByte iSerialNumber;
  13807. + uByte bNumConfigurations;
  13808. +} UPACKED usb_device_descriptor_t;
  13809. +#define USB_DEVICE_DESCRIPTOR_SIZE 18
  13810. +
  13811. +typedef struct {
  13812. + uByte bLength;
  13813. + uByte bDescriptorType;
  13814. + uWord wTotalLength;
  13815. + uByte bNumInterface;
  13816. + uByte bConfigurationValue;
  13817. + uByte iConfiguration;
  13818. +#define UC_ATT_ONE (1 << 7) /* must be set */
  13819. +#define UC_ATT_SELFPOWER (1 << 6) /* self powered */
  13820. +#define UC_ATT_WAKEUP (1 << 5) /* can wakeup */
  13821. +#define UC_ATT_BATTERY (1 << 4) /* battery powered */
  13822. + uByte bmAttributes;
  13823. +#define UC_BUS_POWERED 0x80
  13824. +#define UC_SELF_POWERED 0x40
  13825. +#define UC_REMOTE_WAKEUP 0x20
  13826. + uByte bMaxPower; /* max current in 2 mA units */
  13827. +#define UC_POWER_FACTOR 2
  13828. +} UPACKED usb_config_descriptor_t;
  13829. +#define USB_CONFIG_DESCRIPTOR_SIZE 9
  13830. +
  13831. +typedef struct {
  13832. + uByte bLength;
  13833. + uByte bDescriptorType;
  13834. + uByte bInterfaceNumber;
  13835. + uByte bAlternateSetting;
  13836. + uByte bNumEndpoints;
  13837. + uByte bInterfaceClass;
  13838. + uByte bInterfaceSubClass;
  13839. + uByte bInterfaceProtocol;
  13840. + uByte iInterface;
  13841. +} UPACKED usb_interface_descriptor_t;
  13842. +#define USB_INTERFACE_DESCRIPTOR_SIZE 9
  13843. +
  13844. +typedef struct {
  13845. + uByte bLength;
  13846. + uByte bDescriptorType;
  13847. + uByte bEndpointAddress;
  13848. +#define UE_GET_DIR(a) ((a) & 0x80)
  13849. +#define UE_SET_DIR(a,d) ((a) | (((d)&1) << 7))
  13850. +#define UE_DIR_IN 0x80
  13851. +#define UE_DIR_OUT 0x00
  13852. +#define UE_ADDR 0x0f
  13853. +#define UE_GET_ADDR(a) ((a) & UE_ADDR)
  13854. + uByte bmAttributes;
  13855. +#define UE_XFERTYPE 0x03
  13856. +#define UE_CONTROL 0x00
  13857. +#define UE_ISOCHRONOUS 0x01
  13858. +#define UE_BULK 0x02
  13859. +#define UE_INTERRUPT 0x03
  13860. +#define UE_GET_XFERTYPE(a) ((a) & UE_XFERTYPE)
  13861. +#define UE_ISO_TYPE 0x0c
  13862. +#define UE_ISO_ASYNC 0x04
  13863. +#define UE_ISO_ADAPT 0x08
  13864. +#define UE_ISO_SYNC 0x0c
  13865. +#define UE_GET_ISO_TYPE(a) ((a) & UE_ISO_TYPE)
  13866. + uWord wMaxPacketSize;
  13867. + uByte bInterval;
  13868. +} UPACKED usb_endpoint_descriptor_t;
  13869. +#define USB_ENDPOINT_DESCRIPTOR_SIZE 7
  13870. +
  13871. +typedef struct ss_endpoint_companion_descriptor {
  13872. + uByte bLength;
  13873. + uByte bDescriptorType;
  13874. + uByte bMaxBurst;
  13875. +#define USSE_GET_MAX_STREAMS(a) ((a) & 0x1f)
  13876. +#define USSE_SET_MAX_STREAMS(a, b) ((a) | ((b) & 0x1f))
  13877. +#define USSE_GET_MAX_PACKET_NUM(a) ((a) & 0x03)
  13878. +#define USSE_SET_MAX_PACKET_NUM(a, b) ((a) | ((b) & 0x03))
  13879. + uByte bmAttributes;
  13880. + uWord wBytesPerInterval;
  13881. +} UPACKED ss_endpoint_companion_descriptor_t;
  13882. +#define USB_SS_ENDPOINT_COMPANION_DESCRIPTOR_SIZE 6
  13883. +
  13884. +typedef struct {
  13885. + uByte bLength;
  13886. + uByte bDescriptorType;
  13887. + uWord bString[127];
  13888. +} UPACKED usb_string_descriptor_t;
  13889. +#define USB_MAX_STRING_LEN 128
  13890. +#define USB_LANGUAGE_TABLE 0 /* # of the string language id table */
  13891. +
  13892. +/* Hub specific request */
  13893. +#define UR_GET_BUS_STATE 0x02
  13894. +#define UR_CLEAR_TT_BUFFER 0x08
  13895. +#define UR_RESET_TT 0x09
  13896. +#define UR_GET_TT_STATE 0x0a
  13897. +#define UR_STOP_TT 0x0b
  13898. +
  13899. +/* Hub features */
  13900. +#define UHF_C_HUB_LOCAL_POWER 0
  13901. +#define UHF_C_HUB_OVER_CURRENT 1
  13902. +#define UHF_PORT_CONNECTION 0
  13903. +#define UHF_PORT_ENABLE 1
  13904. +#define UHF_PORT_SUSPEND 2
  13905. +#define UHF_PORT_OVER_CURRENT 3
  13906. +#define UHF_PORT_RESET 4
  13907. +#define UHF_PORT_L1 5
  13908. +#define UHF_PORT_POWER 8
  13909. +#define UHF_PORT_LOW_SPEED 9
  13910. +#define UHF_PORT_HIGH_SPEED 10
  13911. +#define UHF_C_PORT_CONNECTION 16
  13912. +#define UHF_C_PORT_ENABLE 17
  13913. +#define UHF_C_PORT_SUSPEND 18
  13914. +#define UHF_C_PORT_OVER_CURRENT 19
  13915. +#define UHF_C_PORT_RESET 20
  13916. +#define UHF_C_PORT_L1 23
  13917. +#define UHF_PORT_TEST 21
  13918. +#define UHF_PORT_INDICATOR 22
  13919. +
  13920. +typedef struct {
  13921. + uByte bDescLength;
  13922. + uByte bDescriptorType;
  13923. + uByte bNbrPorts;
  13924. + uWord wHubCharacteristics;
  13925. +#define UHD_PWR 0x0003
  13926. +#define UHD_PWR_GANGED 0x0000
  13927. +#define UHD_PWR_INDIVIDUAL 0x0001
  13928. +#define UHD_PWR_NO_SWITCH 0x0002
  13929. +#define UHD_COMPOUND 0x0004
  13930. +#define UHD_OC 0x0018
  13931. +#define UHD_OC_GLOBAL 0x0000
  13932. +#define UHD_OC_INDIVIDUAL 0x0008
  13933. +#define UHD_OC_NONE 0x0010
  13934. +#define UHD_TT_THINK 0x0060
  13935. +#define UHD_TT_THINK_8 0x0000
  13936. +#define UHD_TT_THINK_16 0x0020
  13937. +#define UHD_TT_THINK_24 0x0040
  13938. +#define UHD_TT_THINK_32 0x0060
  13939. +#define UHD_PORT_IND 0x0080
  13940. + uByte bPwrOn2PwrGood; /* delay in 2 ms units */
  13941. +#define UHD_PWRON_FACTOR 2
  13942. + uByte bHubContrCurrent;
  13943. + uByte DeviceRemovable[32]; /* max 255 ports */
  13944. +#define UHD_NOT_REMOV(desc, i) \
  13945. + (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1)
  13946. + /* deprecated */ uByte PortPowerCtrlMask[1];
  13947. +} UPACKED usb_hub_descriptor_t;
  13948. +#define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */
  13949. +
  13950. +typedef struct {
  13951. + uByte bLength;
  13952. + uByte bDescriptorType;
  13953. + uWord bcdUSB;
  13954. + uByte bDeviceClass;
  13955. + uByte bDeviceSubClass;
  13956. + uByte bDeviceProtocol;
  13957. + uByte bMaxPacketSize0;
  13958. + uByte bNumConfigurations;
  13959. + uByte bReserved;
  13960. +} UPACKED usb_device_qualifier_t;
  13961. +#define USB_DEVICE_QUALIFIER_SIZE 10
  13962. +
  13963. +typedef struct {
  13964. + uByte bLength;
  13965. + uByte bDescriptorType;
  13966. + uByte bmAttributes;
  13967. +#define UOTG_SRP 0x01
  13968. +#define UOTG_HNP 0x02
  13969. +} UPACKED usb_otg_descriptor_t;
  13970. +
  13971. +/* OTG feature selectors */
  13972. +#define UOTG_B_HNP_ENABLE 3
  13973. +#define UOTG_A_HNP_SUPPORT 4
  13974. +#define UOTG_A_ALT_HNP_SUPPORT 5
  13975. +
  13976. +typedef struct {
  13977. + uWord wStatus;
  13978. +/* Device status flags */
  13979. +#define UDS_SELF_POWERED 0x0001
  13980. +#define UDS_REMOTE_WAKEUP 0x0002
  13981. +/* Endpoint status flags */
  13982. +#define UES_HALT 0x0001
  13983. +} UPACKED usb_status_t;
  13984. +
  13985. +typedef struct {
  13986. + uWord wHubStatus;
  13987. +#define UHS_LOCAL_POWER 0x0001
  13988. +#define UHS_OVER_CURRENT 0x0002
  13989. + uWord wHubChange;
  13990. +} UPACKED usb_hub_status_t;
  13991. +
  13992. +typedef struct {
  13993. + uWord wPortStatus;
  13994. +#define UPS_CURRENT_CONNECT_STATUS 0x0001
  13995. +#define UPS_PORT_ENABLED 0x0002
  13996. +#define UPS_SUSPEND 0x0004
  13997. +#define UPS_OVERCURRENT_INDICATOR 0x0008
  13998. +#define UPS_RESET 0x0010
  13999. +#define UPS_PORT_POWER 0x0100
  14000. +#define UPS_LOW_SPEED 0x0200
  14001. +#define UPS_HIGH_SPEED 0x0400
  14002. +#define UPS_PORT_TEST 0x0800
  14003. +#define UPS_PORT_INDICATOR 0x1000
  14004. + uWord wPortChange;
  14005. +#define UPS_C_CONNECT_STATUS 0x0001
  14006. +#define UPS_C_PORT_ENABLED 0x0002
  14007. +#define UPS_C_SUSPEND 0x0004
  14008. +#define UPS_C_OVERCURRENT_INDICATOR 0x0008
  14009. +#define UPS_C_PORT_RESET 0x0010
  14010. +} UPACKED usb_port_status_t;
  14011. +
  14012. +#ifdef _MSC_VER
  14013. +#include <poppack.h>
  14014. +#endif
  14015. +
  14016. +/* Device class codes */
  14017. +#define UDCLASS_IN_INTERFACE 0x00
  14018. +#define UDCLASS_COMM 0x02
  14019. +#define UDCLASS_HUB 0x09
  14020. +#define UDSUBCLASS_HUB 0x00
  14021. +#define UDPROTO_FSHUB 0x00
  14022. +#define UDPROTO_HSHUBSTT 0x01
  14023. +#define UDPROTO_HSHUBMTT 0x02
  14024. +#define UDCLASS_DIAGNOSTIC 0xdc
  14025. +#define UDCLASS_WIRELESS 0xe0
  14026. +#define UDSUBCLASS_RF 0x01
  14027. +#define UDPROTO_BLUETOOTH 0x01
  14028. +#define UDCLASS_VENDOR 0xff
  14029. +
  14030. +/* Interface class codes */
  14031. +#define UICLASS_UNSPEC 0x00
  14032. +
  14033. +#define UICLASS_AUDIO 0x01
  14034. +#define UISUBCLASS_AUDIOCONTROL 1
  14035. +#define UISUBCLASS_AUDIOSTREAM 2
  14036. +#define UISUBCLASS_MIDISTREAM 3
  14037. +
  14038. +#define UICLASS_CDC 0x02 /* communication */
  14039. +#define UISUBCLASS_DIRECT_LINE_CONTROL_MODEL 1
  14040. +#define UISUBCLASS_ABSTRACT_CONTROL_MODEL 2
  14041. +#define UISUBCLASS_TELEPHONE_CONTROL_MODEL 3
  14042. +#define UISUBCLASS_MULTICHANNEL_CONTROL_MODEL 4
  14043. +#define UISUBCLASS_CAPI_CONTROLMODEL 5
  14044. +#define UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6
  14045. +#define UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7
  14046. +#define UIPROTO_CDC_AT 1
  14047. +
  14048. +#define UICLASS_HID 0x03
  14049. +#define UISUBCLASS_BOOT 1
  14050. +#define UIPROTO_BOOT_KEYBOARD 1
  14051. +
  14052. +#define UICLASS_PHYSICAL 0x05
  14053. +
  14054. +#define UICLASS_IMAGE 0x06
  14055. +
  14056. +#define UICLASS_PRINTER 0x07
  14057. +#define UISUBCLASS_PRINTER 1
  14058. +#define UIPROTO_PRINTER_UNI 1
  14059. +#define UIPROTO_PRINTER_BI 2
  14060. +#define UIPROTO_PRINTER_1284 3
  14061. +
  14062. +#define UICLASS_MASS 0x08
  14063. +#define UISUBCLASS_RBC 1
  14064. +#define UISUBCLASS_SFF8020I 2
  14065. +#define UISUBCLASS_QIC157 3
  14066. +#define UISUBCLASS_UFI 4
  14067. +#define UISUBCLASS_SFF8070I 5
  14068. +#define UISUBCLASS_SCSI 6
  14069. +#define UIPROTO_MASS_CBI_I 0
  14070. +#define UIPROTO_MASS_CBI 1
  14071. +#define UIPROTO_MASS_BBB_OLD 2 /* Not in the spec anymore */
  14072. +#define UIPROTO_MASS_BBB 80 /* 'P' for the Iomega Zip drive */
  14073. +
  14074. +#define UICLASS_HUB 0x09
  14075. +#define UISUBCLASS_HUB 0
  14076. +#define UIPROTO_FSHUB 0
  14077. +#define UIPROTO_HSHUBSTT 0 /* Yes, same as previous */
  14078. +#define UIPROTO_HSHUBMTT 1
  14079. +
  14080. +#define UICLASS_CDC_DATA 0x0a
  14081. +#define UISUBCLASS_DATA 0
  14082. +#define UIPROTO_DATA_ISDNBRI 0x30 /* Physical iface */
  14083. +#define UIPROTO_DATA_HDLC 0x31 /* HDLC */
  14084. +#define UIPROTO_DATA_TRANSPARENT 0x32 /* Transparent */
  14085. +#define UIPROTO_DATA_Q921M 0x50 /* Management for Q921 */
  14086. +#define UIPROTO_DATA_Q921 0x51 /* Data for Q921 */
  14087. +#define UIPROTO_DATA_Q921TM 0x52 /* TEI multiplexer for Q921 */
  14088. +#define UIPROTO_DATA_V42BIS 0x90 /* Data compression */
  14089. +#define UIPROTO_DATA_Q931 0x91 /* Euro-ISDN */
  14090. +#define UIPROTO_DATA_V120 0x92 /* V.24 rate adaption */
  14091. +#define UIPROTO_DATA_CAPI 0x93 /* CAPI 2.0 commands */
  14092. +#define UIPROTO_DATA_HOST_BASED 0xfd /* Host based driver */
  14093. +#define UIPROTO_DATA_PUF 0xfe /* see Prot. Unit Func. Desc.*/
  14094. +#define UIPROTO_DATA_VENDOR 0xff /* Vendor specific */
  14095. +
  14096. +#define UICLASS_SMARTCARD 0x0b
  14097. +
  14098. +/*#define UICLASS_FIRM_UPD 0x0c*/
  14099. +
  14100. +#define UICLASS_SECURITY 0x0d
  14101. +
  14102. +#define UICLASS_DIAGNOSTIC 0xdc
  14103. +
  14104. +#define UICLASS_WIRELESS 0xe0
  14105. +#define UISUBCLASS_RF 0x01
  14106. +#define UIPROTO_BLUETOOTH 0x01
  14107. +
  14108. +#define UICLASS_APPL_SPEC 0xfe
  14109. +#define UISUBCLASS_FIRMWARE_DOWNLOAD 1
  14110. +#define UISUBCLASS_IRDA 2
  14111. +#define UIPROTO_IRDA 0
  14112. +
  14113. +#define UICLASS_VENDOR 0xff
  14114. +
  14115. +#define USB_HUB_MAX_DEPTH 5
  14116. +
  14117. +/*
  14118. + * Minimum time a device needs to be powered down to go through
  14119. + * a power cycle. XXX Are these time in the spec?
  14120. + */
  14121. +#define USB_POWER_DOWN_TIME 200 /* ms */
  14122. +#define USB_PORT_POWER_DOWN_TIME 100 /* ms */
  14123. +
  14124. +#if 0
  14125. +/* These are the values from the spec. */
  14126. +#define USB_PORT_RESET_DELAY 10 /* ms */
  14127. +#define USB_PORT_ROOT_RESET_DELAY 50 /* ms */
  14128. +#define USB_PORT_RESET_RECOVERY 10 /* ms */
  14129. +#define USB_PORT_POWERUP_DELAY 100 /* ms */
  14130. +#define USB_SET_ADDRESS_SETTLE 2 /* ms */
  14131. +#define USB_RESUME_DELAY (20*5) /* ms */
  14132. +#define USB_RESUME_WAIT 10 /* ms */
  14133. +#define USB_RESUME_RECOVERY 10 /* ms */
  14134. +#define USB_EXTRA_POWER_UP_TIME 0 /* ms */
  14135. +#else
  14136. +/* Allow for marginal (i.e. non-conforming) devices. */
  14137. +#define USB_PORT_RESET_DELAY 50 /* ms */
  14138. +#define USB_PORT_ROOT_RESET_DELAY 250 /* ms */
  14139. +#define USB_PORT_RESET_RECOVERY 250 /* ms */
  14140. +#define USB_PORT_POWERUP_DELAY 300 /* ms */
  14141. +#define USB_SET_ADDRESS_SETTLE 10 /* ms */
  14142. +#define USB_RESUME_DELAY (50*5) /* ms */
  14143. +#define USB_RESUME_WAIT 50 /* ms */
  14144. +#define USB_RESUME_RECOVERY 50 /* ms */
  14145. +#define USB_EXTRA_POWER_UP_TIME 20 /* ms */
  14146. +#endif
  14147. +
  14148. +#define USB_MIN_POWER 100 /* mA */
  14149. +#define USB_MAX_POWER 500 /* mA */
  14150. +
  14151. +#define USB_BUS_RESET_DELAY 100 /* ms XXX?*/
  14152. +
  14153. +#define USB_UNCONFIG_NO 0
  14154. +#define USB_UNCONFIG_INDEX (-1)
  14155. +
  14156. +/*** ioctl() related stuff ***/
  14157. +
  14158. +struct usb_ctl_request {
  14159. + int ucr_addr;
  14160. + usb_device_request_t ucr_request;
  14161. + void *ucr_data;
  14162. + int ucr_flags;
  14163. +#define USBD_SHORT_XFER_OK 0x04 /* allow short reads */
  14164. + int ucr_actlen; /* actual length transferred */
  14165. +};
  14166. +
  14167. +struct usb_alt_interface {
  14168. + int uai_config_index;
  14169. + int uai_interface_index;
  14170. + int uai_alt_no;
  14171. +};
  14172. +
  14173. +#define USB_CURRENT_CONFIG_INDEX (-1)
  14174. +#define USB_CURRENT_ALT_INDEX (-1)
  14175. +
  14176. +struct usb_config_desc {
  14177. + int ucd_config_index;
  14178. + usb_config_descriptor_t ucd_desc;
  14179. +};
  14180. +
  14181. +struct usb_interface_desc {
  14182. + int uid_config_index;
  14183. + int uid_interface_index;
  14184. + int uid_alt_index;
  14185. + usb_interface_descriptor_t uid_desc;
  14186. +};
  14187. +
  14188. +struct usb_endpoint_desc {
  14189. + int ued_config_index;
  14190. + int ued_interface_index;
  14191. + int ued_alt_index;
  14192. + int ued_endpoint_index;
  14193. + usb_endpoint_descriptor_t ued_desc;
  14194. +};
  14195. +
  14196. +struct usb_full_desc {
  14197. + int ufd_config_index;
  14198. + u_int ufd_size;
  14199. + u_char *ufd_data;
  14200. +};
  14201. +
  14202. +struct usb_string_desc {
  14203. + int usd_string_index;
  14204. + int usd_language_id;
  14205. + usb_string_descriptor_t usd_desc;
  14206. +};
  14207. +
  14208. +struct usb_ctl_report_desc {
  14209. + int ucrd_size;
  14210. + u_char ucrd_data[1024]; /* filled data size will vary */
  14211. +};
  14212. +
  14213. +typedef struct { u_int32_t cookie; } usb_event_cookie_t;
  14214. +
  14215. +#define USB_MAX_DEVNAMES 4
  14216. +#define USB_MAX_DEVNAMELEN 16
  14217. +struct usb_device_info {
  14218. + u_int8_t udi_bus;
  14219. + u_int8_t udi_addr; /* device address */
  14220. + usb_event_cookie_t udi_cookie;
  14221. + char udi_product[USB_MAX_STRING_LEN];
  14222. + char udi_vendor[USB_MAX_STRING_LEN];
  14223. + char udi_release[8];
  14224. + u_int16_t udi_productNo;
  14225. + u_int16_t udi_vendorNo;
  14226. + u_int16_t udi_releaseNo;
  14227. + u_int8_t udi_class;
  14228. + u_int8_t udi_subclass;
  14229. + u_int8_t udi_protocol;
  14230. + u_int8_t udi_config;
  14231. + u_int8_t udi_speed;
  14232. +#define USB_SPEED_UNKNOWN 0
  14233. +#define USB_SPEED_LOW 1
  14234. +#define USB_SPEED_FULL 2
  14235. +#define USB_SPEED_HIGH 3
  14236. +#define USB_SPEED_VARIABLE 4
  14237. +#define USB_SPEED_SUPER 5
  14238. + int udi_power; /* power consumption in mA, 0 if selfpowered */
  14239. + int udi_nports;
  14240. + char udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN];
  14241. + u_int8_t udi_ports[16];/* hub only: addresses of devices on ports */
  14242. +#define USB_PORT_ENABLED 0xff
  14243. +#define USB_PORT_SUSPENDED 0xfe
  14244. +#define USB_PORT_POWERED 0xfd
  14245. +#define USB_PORT_DISABLED 0xfc
  14246. +};
  14247. +
  14248. +struct usb_ctl_report {
  14249. + int ucr_report;
  14250. + u_char ucr_data[1024]; /* filled data size will vary */
  14251. +};
  14252. +
  14253. +struct usb_device_stats {
  14254. + u_long uds_requests[4]; /* indexed by transfer type UE_* */
  14255. +};
  14256. +
  14257. +#define WUSB_MIN_IE 0x80
  14258. +#define WUSB_WCTA_IE 0x80
  14259. +#define WUSB_WCONNECTACK_IE 0x81
  14260. +#define WUSB_WHOSTINFO_IE 0x82
  14261. +#define WUHI_GET_CA(_bmAttributes_) ((_bmAttributes_) & 0x3)
  14262. +#define WUHI_CA_RECONN 0x00
  14263. +#define WUHI_CA_LIMITED 0x01
  14264. +#define WUHI_CA_ALL 0x03
  14265. +#define WUHI_GET_MLSI(_bmAttributes_) (((_bmAttributes_) & 0x38) >> 3)
  14266. +#define WUSB_WCHCHANGEANNOUNCE_IE 0x83
  14267. +#define WUSB_WDEV_DISCONNECT_IE 0x84
  14268. +#define WUSB_WHOST_DISCONNECT_IE 0x85
  14269. +#define WUSB_WRELEASE_CHANNEL_IE 0x86
  14270. +#define WUSB_WWORK_IE 0x87
  14271. +#define WUSB_WCHANNEL_STOP_IE 0x88
  14272. +#define WUSB_WDEV_KEEPALIVE_IE 0x89
  14273. +#define WUSB_WISOCH_DISCARD_IE 0x8A
  14274. +#define WUSB_WRESETDEVICE_IE 0x8B
  14275. +#define WUSB_WXMIT_PACKET_ADJUST_IE 0x8C
  14276. +#define WUSB_MAX_IE 0x8C
  14277. +
  14278. +/* Device Notification Types */
  14279. +
  14280. +#define WUSB_DN_MIN 0x01
  14281. +#define WUSB_DN_CONNECT 0x01
  14282. +# define WUSB_DA_OLDCONN 0x00
  14283. +# define WUSB_DA_NEWCONN 0x01
  14284. +# define WUSB_DA_SELF_BEACON 0x02
  14285. +# define WUSB_DA_DIR_BEACON 0x04
  14286. +# define WUSB_DA_NO_BEACON 0x06
  14287. +#define WUSB_DN_DISCONNECT 0x02
  14288. +#define WUSB_DN_EPRDY 0x03
  14289. +#define WUSB_DN_MASAVAILCHANGED 0x04
  14290. +#define WUSB_DN_REMOTEWAKEUP 0x05
  14291. +#define WUSB_DN_SLEEP 0x06
  14292. +#define WUSB_DN_ALIVE 0x07
  14293. +#define WUSB_DN_MAX 0x07
  14294. +
  14295. +#ifdef _MSC_VER
  14296. +#include <pshpack1.h>
  14297. +#endif
  14298. +
  14299. +/* WUSB Handshake Data. Used during the SET/GET HANDSHAKE requests */
  14300. +typedef struct wusb_hndshk_data {
  14301. + uByte bMessageNumber;
  14302. + uByte bStatus;
  14303. + uByte tTKID[3];
  14304. + uByte bReserved;
  14305. + uByte CDID[16];
  14306. + uByte Nonce[16];
  14307. + uByte MIC[8];
  14308. +} UPACKED wusb_hndshk_data_t;
  14309. +#define WUSB_HANDSHAKE_LEN_FOR_MIC 38
  14310. +
  14311. +/* WUSB Connection Context */
  14312. +typedef struct wusb_conn_context {
  14313. + uByte CHID [16];
  14314. + uByte CDID [16];
  14315. + uByte CK [16];
  14316. +} UPACKED wusb_conn_context_t;
  14317. +
  14318. +/* WUSB Security Descriptor */
  14319. +typedef struct wusb_security_desc {
  14320. + uByte bLength;
  14321. + uByte bDescriptorType;
  14322. + uWord wTotalLength;
  14323. + uByte bNumEncryptionTypes;
  14324. +} UPACKED wusb_security_desc_t;
  14325. +
  14326. +/* WUSB Encryption Type Descriptor */
  14327. +typedef struct wusb_encrypt_type_desc {
  14328. + uByte bLength;
  14329. + uByte bDescriptorType;
  14330. +
  14331. + uByte bEncryptionType;
  14332. +#define WUETD_UNSECURE 0
  14333. +#define WUETD_WIRED 1
  14334. +#define WUETD_CCM_1 2
  14335. +#define WUETD_RSA_1 3
  14336. +
  14337. + uByte bEncryptionValue;
  14338. + uByte bAuthKeyIndex;
  14339. +} UPACKED wusb_encrypt_type_desc_t;
  14340. +
  14341. +/* WUSB Key Descriptor */
  14342. +typedef struct wusb_key_desc {
  14343. + uByte bLength;
  14344. + uByte bDescriptorType;
  14345. + uByte tTKID[3];
  14346. + uByte bReserved;
  14347. + uByte KeyData[1]; /* variable length */
  14348. +} UPACKED wusb_key_desc_t;
  14349. +
  14350. +/* WUSB BOS Descriptor (Binary device Object Store) */
  14351. +typedef struct wusb_bos_desc {
  14352. + uByte bLength;
  14353. + uByte bDescriptorType;
  14354. + uWord wTotalLength;
  14355. + uByte bNumDeviceCaps;
  14356. +} UPACKED wusb_bos_desc_t;
  14357. +
  14358. +#define USB_DEVICE_CAPABILITY_20_EXTENSION 0x02
  14359. +typedef struct usb_dev_cap_20_ext_desc {
  14360. + uByte bLength;
  14361. + uByte bDescriptorType;
  14362. + uByte bDevCapabilityType;
  14363. +#define USB_20_EXT_LPM 0x02
  14364. + uDWord bmAttributes;
  14365. +} UPACKED usb_dev_cap_20_ext_desc_t;
  14366. +
  14367. +#define USB_DEVICE_CAPABILITY_SS_USB 0x03
  14368. +typedef struct usb_dev_cap_ss_usb {
  14369. + uByte bLength;
  14370. + uByte bDescriptorType;
  14371. + uByte bDevCapabilityType;
  14372. +#define USB_DC_SS_USB_LTM_CAPABLE 0x02
  14373. + uByte bmAttributes;
  14374. +#define USB_DC_SS_USB_SPEED_SUPPORT_LOW 0x01
  14375. +#define USB_DC_SS_USB_SPEED_SUPPORT_FULL 0x02
  14376. +#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH 0x04
  14377. +#define USB_DC_SS_USB_SPEED_SUPPORT_SS 0x08
  14378. + uWord wSpeedsSupported;
  14379. + uByte bFunctionalitySupport;
  14380. + uByte bU1DevExitLat;
  14381. + uWord wU2DevExitLat;
  14382. +} UPACKED usb_dev_cap_ss_usb_t;
  14383. +
  14384. +#define USB_DEVICE_CAPABILITY_CONTAINER_ID 0x04
  14385. +typedef struct usb_dev_cap_container_id {
  14386. + uByte bLength;
  14387. + uByte bDescriptorType;
  14388. + uByte bDevCapabilityType;
  14389. + uByte bReserved;
  14390. + uByte containerID[16];
  14391. +} UPACKED usb_dev_cap_container_id_t;
  14392. +
  14393. +/* Device Capability Type Codes */
  14394. +#define WUSB_DEVICE_CAPABILITY_WIRELESS_USB 0x01
  14395. +
  14396. +/* Device Capability Descriptor */
  14397. +typedef struct wusb_dev_cap_desc {
  14398. + uByte bLength;
  14399. + uByte bDescriptorType;
  14400. + uByte bDevCapabilityType;
  14401. + uByte caps[1]; /* Variable length */
  14402. +} UPACKED wusb_dev_cap_desc_t;
  14403. +
  14404. +/* Device Capability Descriptor */
  14405. +typedef struct wusb_dev_cap_uwb_desc {
  14406. + uByte bLength;
  14407. + uByte bDescriptorType;
  14408. + uByte bDevCapabilityType;
  14409. + uByte bmAttributes;
  14410. + uWord wPHYRates; /* Bitmap */
  14411. + uByte bmTFITXPowerInfo;
  14412. + uByte bmFFITXPowerInfo;
  14413. + uWord bmBandGroup;
  14414. + uByte bReserved;
  14415. +} UPACKED wusb_dev_cap_uwb_desc_t;
  14416. +
  14417. +/* Wireless USB Endpoint Companion Descriptor */
  14418. +typedef struct wusb_endpoint_companion_desc {
  14419. + uByte bLength;
  14420. + uByte bDescriptorType;
  14421. + uByte bMaxBurst;
  14422. + uByte bMaxSequence;
  14423. + uWord wMaxStreamDelay;
  14424. + uWord wOverTheAirPacketSize;
  14425. + uByte bOverTheAirInterval;
  14426. + uByte bmCompAttributes;
  14427. +} UPACKED wusb_endpoint_companion_desc_t;
  14428. +
  14429. +/* Wireless USB Numeric Association M1 Data Structure */
  14430. +typedef struct wusb_m1_data {
  14431. + uByte version;
  14432. + uWord langId;
  14433. + uByte deviceFriendlyNameLength;
  14434. + uByte sha_256_m3[32];
  14435. + uByte deviceFriendlyName[256];
  14436. +} UPACKED wusb_m1_data_t;
  14437. +
  14438. +typedef struct wusb_m2_data {
  14439. + uByte version;
  14440. + uWord langId;
  14441. + uByte hostFriendlyNameLength;
  14442. + uByte pkh[384];
  14443. + uByte hostFriendlyName[256];
  14444. +} UPACKED wusb_m2_data_t;
  14445. +
  14446. +typedef struct wusb_m3_data {
  14447. + uByte pkd[384];
  14448. + uByte nd;
  14449. +} UPACKED wusb_m3_data_t;
  14450. +
  14451. +typedef struct wusb_m4_data {
  14452. + uDWord _attributeTypeIdAndLength_1;
  14453. + uWord associationTypeId;
  14454. +
  14455. + uDWord _attributeTypeIdAndLength_2;
  14456. + uWord associationSubTypeId;
  14457. +
  14458. + uDWord _attributeTypeIdAndLength_3;
  14459. + uDWord length;
  14460. +
  14461. + uDWord _attributeTypeIdAndLength_4;
  14462. + uDWord associationStatus;
  14463. +
  14464. + uDWord _attributeTypeIdAndLength_5;
  14465. + uByte chid[16];
  14466. +
  14467. + uDWord _attributeTypeIdAndLength_6;
  14468. + uByte cdid[16];
  14469. +
  14470. + uDWord _attributeTypeIdAndLength_7;
  14471. + uByte bandGroups[2];
  14472. +} UPACKED wusb_m4_data_t;
  14473. +
  14474. +#ifdef _MSC_VER
  14475. +#include <poppack.h>
  14476. +#endif
  14477. +
  14478. +#ifdef __cplusplus
  14479. +}
  14480. +#endif
  14481. +
  14482. +#endif /* _USB_H_ */
  14483. --- /dev/null
  14484. +++ b/drivers/usb/host/dwc_otg/Makefile
  14485. @@ -0,0 +1,80 @@
  14486. +#
  14487. +# Makefile for DWC_otg Highspeed USB controller driver
  14488. +#
  14489. +
  14490. +ifneq ($(KERNELRELEASE),)
  14491. +
  14492. +# Use the BUS_INTERFACE variable to compile the software for either
  14493. +# PCI(PCI_INTERFACE) or LM(LM_INTERFACE) bus.
  14494. +ifeq ($(BUS_INTERFACE),)
  14495. +# BUS_INTERFACE = -DPCI_INTERFACE
  14496. +# BUS_INTERFACE = -DLM_INTERFACE
  14497. + BUS_INTERFACE = -DPLATFORM_INTERFACE
  14498. +endif
  14499. +
  14500. +#ccflags-y += -DDEBUG
  14501. +#ccflags-y += -DDWC_OTG_DEBUGLEV=1 # reduce common debug msgs
  14502. +
  14503. +# Use one of the following flags to compile the software in host-only or
  14504. +# device-only mode.
  14505. +#ccflags-y += -DDWC_HOST_ONLY
  14506. +#ccflags-y += -DDWC_DEVICE_ONLY
  14507. +
  14508. +ccflags-y += -Dlinux -DDWC_HS_ELECT_TST
  14509. +#ccflags-y += -DDWC_EN_ISOC
  14510. +ccflags-y += -I$(obj)/../dwc_common_port
  14511. +#ccflags-y += -I$(PORTLIB)
  14512. +ccflags-y += -DDWC_LINUX
  14513. +ccflags-y += $(CFI)
  14514. +ccflags-y += $(BUS_INTERFACE)
  14515. +#ccflags-y += -DDWC_DEV_SRPCAP
  14516. +
  14517. +obj-$(CONFIG_USB_DWCOTG) += dwc_otg.o
  14518. +
  14519. +dwc_otg-objs := dwc_otg_driver.o dwc_otg_attr.o
  14520. +dwc_otg-objs += dwc_otg_cil.o dwc_otg_cil_intr.o
  14521. +dwc_otg-objs += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o
  14522. +dwc_otg-objs += dwc_otg_hcd.o dwc_otg_hcd_linux.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o dwc_otg_hcd_ddma.o
  14523. +dwc_otg-objs += dwc_otg_adp.o
  14524. +ifneq ($(CFI),)
  14525. +dwc_otg-objs += dwc_otg_cfi.o
  14526. +endif
  14527. +
  14528. +kernrelwd := $(subst ., ,$(KERNELRELEASE))
  14529. +kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))
  14530. +
  14531. +ifneq ($(kernrel3),2.6.20)
  14532. +ccflags-y += $(CPPFLAGS)
  14533. +endif
  14534. +
  14535. +else
  14536. +
  14537. +PWD := $(shell pwd)
  14538. +PORTLIB := $(PWD)/../dwc_common_port
  14539. +
  14540. +# Command paths
  14541. +CTAGS := $(CTAGS)
  14542. +DOXYGEN := $(DOXYGEN)
  14543. +
  14544. +default: portlib
  14545. + $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
  14546. +
  14547. +install: default
  14548. + $(MAKE) -C$(KDIR) M=$(PORTLIB) modules_install
  14549. + $(MAKE) -C$(KDIR) M=$(PWD) modules_install
  14550. +
  14551. +portlib:
  14552. + $(MAKE) -C$(KDIR) M=$(PORTLIB) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
  14553. + cp $(PORTLIB)/Module.symvers $(PWD)/
  14554. +
  14555. +docs: $(wildcard *.[hc]) doc/doxygen.cfg
  14556. + $(DOXYGEN) doc/doxygen.cfg
  14557. +
  14558. +tags: $(wildcard *.[hc])
  14559. + $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h)
  14560. +
  14561. +
  14562. +clean:
  14563. + rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers
  14564. +
  14565. +endif
  14566. --- /dev/null
  14567. +++ b/drivers/usb/host/dwc_otg/doc/doxygen.cfg
  14568. @@ -0,0 +1,224 @@
  14569. +# Doxyfile 1.3.9.1
  14570. +
  14571. +#---------------------------------------------------------------------------
  14572. +# Project related configuration options
  14573. +#---------------------------------------------------------------------------
  14574. +PROJECT_NAME = "DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver"
  14575. +PROJECT_NUMBER = v3.00a
  14576. +OUTPUT_DIRECTORY = ./doc/
  14577. +CREATE_SUBDIRS = NO
  14578. +OUTPUT_LANGUAGE = English
  14579. +BRIEF_MEMBER_DESC = YES
  14580. +REPEAT_BRIEF = YES
  14581. +ABBREVIATE_BRIEF = "The $name class" \
  14582. + "The $name widget" \
  14583. + "The $name file" \
  14584. + is \
  14585. + provides \
  14586. + specifies \
  14587. + contains \
  14588. + represents \
  14589. + a \
  14590. + an \
  14591. + the
  14592. +ALWAYS_DETAILED_SEC = NO
  14593. +INLINE_INHERITED_MEMB = NO
  14594. +FULL_PATH_NAMES = NO
  14595. +STRIP_FROM_PATH =
  14596. +STRIP_FROM_INC_PATH =
  14597. +SHORT_NAMES = NO
  14598. +JAVADOC_AUTOBRIEF = YES
  14599. +MULTILINE_CPP_IS_BRIEF = NO
  14600. +INHERIT_DOCS = YES
  14601. +DISTRIBUTE_GROUP_DOC = NO
  14602. +TAB_SIZE = 8
  14603. +ALIASES =
  14604. +OPTIMIZE_OUTPUT_FOR_C = YES
  14605. +OPTIMIZE_OUTPUT_JAVA = NO
  14606. +SUBGROUPING = YES
  14607. +#---------------------------------------------------------------------------
  14608. +# Build related configuration options
  14609. +#---------------------------------------------------------------------------
  14610. +EXTRACT_ALL = NO
  14611. +EXTRACT_PRIVATE = YES
  14612. +EXTRACT_STATIC = YES
  14613. +EXTRACT_LOCAL_CLASSES = YES
  14614. +EXTRACT_LOCAL_METHODS = NO
  14615. +HIDE_UNDOC_MEMBERS = NO
  14616. +HIDE_UNDOC_CLASSES = NO
  14617. +HIDE_FRIEND_COMPOUNDS = NO
  14618. +HIDE_IN_BODY_DOCS = NO
  14619. +INTERNAL_DOCS = NO
  14620. +CASE_SENSE_NAMES = NO
  14621. +HIDE_SCOPE_NAMES = NO
  14622. +SHOW_INCLUDE_FILES = YES
  14623. +INLINE_INFO = YES
  14624. +SORT_MEMBER_DOCS = NO
  14625. +SORT_BRIEF_DOCS = NO
  14626. +SORT_BY_SCOPE_NAME = NO
  14627. +GENERATE_TODOLIST = YES
  14628. +GENERATE_TESTLIST = YES
  14629. +GENERATE_BUGLIST = YES
  14630. +GENERATE_DEPRECATEDLIST= YES
  14631. +ENABLED_SECTIONS =
  14632. +MAX_INITIALIZER_LINES = 30
  14633. +SHOW_USED_FILES = YES
  14634. +SHOW_DIRECTORIES = YES
  14635. +#---------------------------------------------------------------------------
  14636. +# configuration options related to warning and progress messages
  14637. +#---------------------------------------------------------------------------
  14638. +QUIET = YES
  14639. +WARNINGS = YES
  14640. +WARN_IF_UNDOCUMENTED = NO
  14641. +WARN_IF_DOC_ERROR = YES
  14642. +WARN_FORMAT = "$file:$line: $text"
  14643. +WARN_LOGFILE =
  14644. +#---------------------------------------------------------------------------
  14645. +# configuration options related to the input files
  14646. +#---------------------------------------------------------------------------
  14647. +INPUT = .
  14648. +FILE_PATTERNS = *.c \
  14649. + *.h \
  14650. + ./linux/*.c \
  14651. + ./linux/*.h
  14652. +RECURSIVE = NO
  14653. +EXCLUDE = ./test/ \
  14654. + ./dwc_otg/.AppleDouble/
  14655. +EXCLUDE_SYMLINKS = YES
  14656. +EXCLUDE_PATTERNS = *.mod.*
  14657. +EXAMPLE_PATH =
  14658. +EXAMPLE_PATTERNS = *
  14659. +EXAMPLE_RECURSIVE = NO
  14660. +IMAGE_PATH =
  14661. +INPUT_FILTER =
  14662. +FILTER_PATTERNS =
  14663. +FILTER_SOURCE_FILES = NO
  14664. +#---------------------------------------------------------------------------
  14665. +# configuration options related to source browsing
  14666. +#---------------------------------------------------------------------------
  14667. +SOURCE_BROWSER = YES
  14668. +INLINE_SOURCES = NO
  14669. +STRIP_CODE_COMMENTS = YES
  14670. +REFERENCED_BY_RELATION = NO
  14671. +REFERENCES_RELATION = NO
  14672. +VERBATIM_HEADERS = NO
  14673. +#---------------------------------------------------------------------------
  14674. +# configuration options related to the alphabetical class index
  14675. +#---------------------------------------------------------------------------
  14676. +ALPHABETICAL_INDEX = NO
  14677. +COLS_IN_ALPHA_INDEX = 5
  14678. +IGNORE_PREFIX =
  14679. +#---------------------------------------------------------------------------
  14680. +# configuration options related to the HTML output
  14681. +#---------------------------------------------------------------------------
  14682. +GENERATE_HTML = YES
  14683. +HTML_OUTPUT = html
  14684. +HTML_FILE_EXTENSION = .html
  14685. +HTML_HEADER =
  14686. +HTML_FOOTER =
  14687. +HTML_STYLESHEET =
  14688. +HTML_ALIGN_MEMBERS = YES
  14689. +GENERATE_HTMLHELP = NO
  14690. +CHM_FILE =
  14691. +HHC_LOCATION =
  14692. +GENERATE_CHI = NO
  14693. +BINARY_TOC = NO
  14694. +TOC_EXPAND = NO
  14695. +DISABLE_INDEX = NO
  14696. +ENUM_VALUES_PER_LINE = 4
  14697. +GENERATE_TREEVIEW = YES
  14698. +TREEVIEW_WIDTH = 250
  14699. +#---------------------------------------------------------------------------
  14700. +# configuration options related to the LaTeX output
  14701. +#---------------------------------------------------------------------------
  14702. +GENERATE_LATEX = NO
  14703. +LATEX_OUTPUT = latex
  14704. +LATEX_CMD_NAME = latex
  14705. +MAKEINDEX_CMD_NAME = makeindex
  14706. +COMPACT_LATEX = NO
  14707. +PAPER_TYPE = a4wide
  14708. +EXTRA_PACKAGES =
  14709. +LATEX_HEADER =
  14710. +PDF_HYPERLINKS = NO
  14711. +USE_PDFLATEX = NO
  14712. +LATEX_BATCHMODE = NO
  14713. +LATEX_HIDE_INDICES = NO
  14714. +#---------------------------------------------------------------------------
  14715. +# configuration options related to the RTF output
  14716. +#---------------------------------------------------------------------------
  14717. +GENERATE_RTF = NO
  14718. +RTF_OUTPUT = rtf
  14719. +COMPACT_RTF = NO
  14720. +RTF_HYPERLINKS = NO
  14721. +RTF_STYLESHEET_FILE =
  14722. +RTF_EXTENSIONS_FILE =
  14723. +#---------------------------------------------------------------------------
  14724. +# configuration options related to the man page output
  14725. +#---------------------------------------------------------------------------
  14726. +GENERATE_MAN = NO
  14727. +MAN_OUTPUT = man
  14728. +MAN_EXTENSION = .3
  14729. +MAN_LINKS = NO
  14730. +#---------------------------------------------------------------------------
  14731. +# configuration options related to the XML output
  14732. +#---------------------------------------------------------------------------
  14733. +GENERATE_XML = NO
  14734. +XML_OUTPUT = xml
  14735. +XML_SCHEMA =
  14736. +XML_DTD =
  14737. +XML_PROGRAMLISTING = YES
  14738. +#---------------------------------------------------------------------------
  14739. +# configuration options for the AutoGen Definitions output
  14740. +#---------------------------------------------------------------------------
  14741. +GENERATE_AUTOGEN_DEF = NO
  14742. +#---------------------------------------------------------------------------
  14743. +# configuration options related to the Perl module output
  14744. +#---------------------------------------------------------------------------
  14745. +GENERATE_PERLMOD = NO
  14746. +PERLMOD_LATEX = NO
  14747. +PERLMOD_PRETTY = YES
  14748. +PERLMOD_MAKEVAR_PREFIX =
  14749. +#---------------------------------------------------------------------------
  14750. +# Configuration options related to the preprocessor
  14751. +#---------------------------------------------------------------------------
  14752. +ENABLE_PREPROCESSING = YES
  14753. +MACRO_EXPANSION = YES
  14754. +EXPAND_ONLY_PREDEF = YES
  14755. +SEARCH_INCLUDES = YES
  14756. +INCLUDE_PATH =
  14757. +INCLUDE_FILE_PATTERNS =
  14758. +PREDEFINED = DEVICE_ATTR DWC_EN_ISOC
  14759. +EXPAND_AS_DEFINED = DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW DWC_OTG_DEVICE_ATTR_BITFIELD_STORE DWC_OTG_DEVICE_ATTR_BITFIELD_RW DWC_OTG_DEVICE_ATTR_BITFIELD_RO DWC_OTG_DEVICE_ATTR_REG_SHOW DWC_OTG_DEVICE_ATTR_REG_STORE DWC_OTG_DEVICE_ATTR_REG32_RW DWC_OTG_DEVICE_ATTR_REG32_RO DWC_EN_ISOC
  14760. +SKIP_FUNCTION_MACROS = NO
  14761. +#---------------------------------------------------------------------------
  14762. +# Configuration::additions related to external references
  14763. +#---------------------------------------------------------------------------
  14764. +TAGFILES =
  14765. +GENERATE_TAGFILE =
  14766. +ALLEXTERNALS = NO
  14767. +EXTERNAL_GROUPS = YES
  14768. +PERL_PATH = /usr/bin/perl
  14769. +#---------------------------------------------------------------------------
  14770. +# Configuration options related to the dot tool
  14771. +#---------------------------------------------------------------------------
  14772. +CLASS_DIAGRAMS = YES
  14773. +HIDE_UNDOC_RELATIONS = YES
  14774. +HAVE_DOT = NO
  14775. +CLASS_GRAPH = YES
  14776. +COLLABORATION_GRAPH = YES
  14777. +UML_LOOK = NO
  14778. +TEMPLATE_RELATIONS = NO
  14779. +INCLUDE_GRAPH = YES
  14780. +INCLUDED_BY_GRAPH = YES
  14781. +CALL_GRAPH = NO
  14782. +GRAPHICAL_HIERARCHY = YES
  14783. +DOT_IMAGE_FORMAT = png
  14784. +DOT_PATH =
  14785. +DOTFILE_DIRS =
  14786. +MAX_DOT_GRAPH_DEPTH = 1000
  14787. +GENERATE_LEGEND = YES
  14788. +DOT_CLEANUP = YES
  14789. +#---------------------------------------------------------------------------
  14790. +# Configuration::additions related to the search engine
  14791. +#---------------------------------------------------------------------------
  14792. +SEARCHENGINE = NO
  14793. --- /dev/null
  14794. +++ b/drivers/usb/host/dwc_otg/dummy_audio.c
  14795. @@ -0,0 +1,1575 @@
  14796. +/*
  14797. + * zero.c -- Gadget Zero, for USB development
  14798. + *
  14799. + * Copyright (C) 2003-2004 David Brownell
  14800. + * All rights reserved.
  14801. + *
  14802. + * Redistribution and use in source and binary forms, with or without
  14803. + * modification, are permitted provided that the following conditions
  14804. + * are met:
  14805. + * 1. Redistributions of source code must retain the above copyright
  14806. + * notice, this list of conditions, and the following disclaimer,
  14807. + * without modification.
  14808. + * 2. Redistributions in binary form must reproduce the above copyright
  14809. + * notice, this list of conditions and the following disclaimer in the
  14810. + * documentation and/or other materials provided with the distribution.
  14811. + * 3. The names of the above-listed copyright holders may not be used
  14812. + * to endorse or promote products derived from this software without
  14813. + * specific prior written permission.
  14814. + *
  14815. + * ALTERNATIVELY, this software may be distributed under the terms of the
  14816. + * GNU General Public License ("GPL") as published by the Free Software
  14817. + * Foundation, either version 2 of that License or (at your option) any
  14818. + * later version.
  14819. + *
  14820. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  14821. + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  14822. + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  14823. + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  14824. + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  14825. + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  14826. + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  14827. + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  14828. + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  14829. + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  14830. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14831. + */
  14832. +
  14833. +
  14834. +/*
  14835. + * Gadget Zero only needs two bulk endpoints, and is an example of how you
  14836. + * can write a hardware-agnostic gadget driver running inside a USB device.
  14837. + *
  14838. + * Hardware details are visible (see CONFIG_USB_ZERO_* below) but don't
  14839. + * affect most of the driver.
  14840. + *
  14841. + * Use it with the Linux host/master side "usbtest" driver to get a basic
  14842. + * functional test of your device-side usb stack, or with "usb-skeleton".
  14843. + *
  14844. + * It supports two similar configurations. One sinks whatever the usb host
  14845. + * writes, and in return sources zeroes. The other loops whatever the host
  14846. + * writes back, so the host can read it. Module options include:
  14847. + *
  14848. + * buflen=N default N=4096, buffer size used
  14849. + * qlen=N default N=32, how many buffers in the loopback queue
  14850. + * loopdefault default false, list loopback config first
  14851. + *
  14852. + * Many drivers will only have one configuration, letting them be much
  14853. + * simpler if they also don't support high speed operation (like this
  14854. + * driver does).
  14855. + */
  14856. +
  14857. +#include <linux/config.h>
  14858. +#include <linux/module.h>
  14859. +#include <linux/kernel.h>
  14860. +#include <linux/delay.h>
  14861. +#include <linux/ioport.h>
  14862. +#include <linux/sched.h>
  14863. +#include <linux/slab.h>
  14864. +#include <linux/smp_lock.h>
  14865. +#include <linux/errno.h>
  14866. +#include <linux/init.h>
  14867. +#include <linux/timer.h>
  14868. +#include <linux/list.h>
  14869. +#include <linux/interrupt.h>
  14870. +#include <linux/uts.h>
  14871. +#include <linux/version.h>
  14872. +#include <linux/device.h>
  14873. +#include <linux/moduleparam.h>
  14874. +#include <linux/proc_fs.h>
  14875. +
  14876. +#include <asm/byteorder.h>
  14877. +#include <asm/io.h>
  14878. +#include <asm/irq.h>
  14879. +#include <asm/system.h>
  14880. +#include <asm/unaligned.h>
  14881. +
  14882. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
  14883. +# include <linux/usb/ch9.h>
  14884. +#else
  14885. +# include <linux/usb_ch9.h>
  14886. +#endif
  14887. +
  14888. +#include <linux/usb_gadget.h>
  14889. +
  14890. +
  14891. +/*-------------------------------------------------------------------------*/
  14892. +/*-------------------------------------------------------------------------*/
  14893. +
  14894. +
  14895. +static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len)
  14896. +{
  14897. + int count = 0;
  14898. + u8 c;
  14899. + u16 uchar;
  14900. +
  14901. + /* this insists on correct encodings, though not minimal ones.
  14902. + * BUT it currently rejects legit 4-byte UTF-8 code points,
  14903. + * which need surrogate pairs. (Unicode 3.1 can use them.)
  14904. + */
  14905. + while (len != 0 && (c = (u8) *s++) != 0) {
  14906. + if (unlikely(c & 0x80)) {
  14907. + // 2-byte sequence:
  14908. + // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
  14909. + if ((c & 0xe0) == 0xc0) {
  14910. + uchar = (c & 0x1f) << 6;
  14911. +
  14912. + c = (u8) *s++;
  14913. + if ((c & 0xc0) != 0xc0)
  14914. + goto fail;
  14915. + c &= 0x3f;
  14916. + uchar |= c;
  14917. +
  14918. + // 3-byte sequence (most CJKV characters):
  14919. + // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
  14920. + } else if ((c & 0xf0) == 0xe0) {
  14921. + uchar = (c & 0x0f) << 12;
  14922. +
  14923. + c = (u8) *s++;
  14924. + if ((c & 0xc0) != 0xc0)
  14925. + goto fail;
  14926. + c &= 0x3f;
  14927. + uchar |= c << 6;
  14928. +
  14929. + c = (u8) *s++;
  14930. + if ((c & 0xc0) != 0xc0)
  14931. + goto fail;
  14932. + c &= 0x3f;
  14933. + uchar |= c;
  14934. +
  14935. + /* no bogus surrogates */
  14936. + if (0xd800 <= uchar && uchar <= 0xdfff)
  14937. + goto fail;
  14938. +
  14939. + // 4-byte sequence (surrogate pairs, currently rare):
  14940. + // 11101110wwwwzzzzyy + 110111yyyyxxxxxx
  14941. + // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
  14942. + // (uuuuu = wwww + 1)
  14943. + // FIXME accept the surrogate code points (only)
  14944. +
  14945. + } else
  14946. + goto fail;
  14947. + } else
  14948. + uchar = c;
  14949. + put_unaligned (cpu_to_le16 (uchar), cp++);
  14950. + count++;
  14951. + len--;
  14952. + }
  14953. + return count;
  14954. +fail:
  14955. + return -1;
  14956. +}
  14957. +
  14958. +
  14959. +/**
  14960. + * usb_gadget_get_string - fill out a string descriptor
  14961. + * @table: of c strings encoded using UTF-8
  14962. + * @id: string id, from low byte of wValue in get string descriptor
  14963. + * @buf: at least 256 bytes
  14964. + *
  14965. + * Finds the UTF-8 string matching the ID, and converts it into a
  14966. + * string descriptor in utf16-le.
  14967. + * Returns length of descriptor (always even) or negative errno
  14968. + *
  14969. + * If your driver needs stings in multiple languages, you'll probably
  14970. + * "switch (wIndex) { ... }" in your ep0 string descriptor logic,
  14971. + * using this routine after choosing which set of UTF-8 strings to use.
  14972. + * Note that US-ASCII is a strict subset of UTF-8; any string bytes with
  14973. + * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1
  14974. + * characters (which are also widely used in C strings).
  14975. + */
  14976. +int
  14977. +usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
  14978. +{
  14979. + struct usb_string *s;
  14980. + int len;
  14981. +
  14982. + /* descriptor 0 has the language id */
  14983. + if (id == 0) {
  14984. + buf [0] = 4;
  14985. + buf [1] = USB_DT_STRING;
  14986. + buf [2] = (u8) table->language;
  14987. + buf [3] = (u8) (table->language >> 8);
  14988. + return 4;
  14989. + }
  14990. + for (s = table->strings; s && s->s; s++)
  14991. + if (s->id == id)
  14992. + break;
  14993. +
  14994. + /* unrecognized: stall. */
  14995. + if (!s || !s->s)
  14996. + return -EINVAL;
  14997. +
  14998. + /* string descriptors have length, tag, then UTF16-LE text */
  14999. + len = min ((size_t) 126, strlen (s->s));
  15000. + memset (buf + 2, 0, 2 * len); /* zero all the bytes */
  15001. + len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len);
  15002. + if (len < 0)
  15003. + return -EINVAL;
  15004. + buf [0] = (len + 1) * 2;
  15005. + buf [1] = USB_DT_STRING;
  15006. + return buf [0];
  15007. +}
  15008. +
  15009. +
  15010. +/*-------------------------------------------------------------------------*/
  15011. +/*-------------------------------------------------------------------------*/
  15012. +
  15013. +
  15014. +/**
  15015. + * usb_descriptor_fillbuf - fill buffer with descriptors
  15016. + * @buf: Buffer to be filled
  15017. + * @buflen: Size of buf
  15018. + * @src: Array of descriptor pointers, terminated by null pointer.
  15019. + *
  15020. + * Copies descriptors into the buffer, returning the length or a
  15021. + * negative error code if they can't all be copied. Useful when
  15022. + * assembling descriptors for an associated set of interfaces used
  15023. + * as part of configuring a composite device; or in other cases where
  15024. + * sets of descriptors need to be marshaled.
  15025. + */
  15026. +int
  15027. +usb_descriptor_fillbuf(void *buf, unsigned buflen,
  15028. + const struct usb_descriptor_header **src)
  15029. +{
  15030. + u8 *dest = buf;
  15031. +
  15032. + if (!src)
  15033. + return -EINVAL;
  15034. +
  15035. + /* fill buffer from src[] until null descriptor ptr */
  15036. + for (; 0 != *src; src++) {
  15037. + unsigned len = (*src)->bLength;
  15038. +
  15039. + if (len > buflen)
  15040. + return -EINVAL;
  15041. + memcpy(dest, *src, len);
  15042. + buflen -= len;
  15043. + dest += len;
  15044. + }
  15045. + return dest - (u8 *)buf;
  15046. +}
  15047. +
  15048. +
  15049. +/**
  15050. + * usb_gadget_config_buf - builts a complete configuration descriptor
  15051. + * @config: Header for the descriptor, including characteristics such
  15052. + * as power requirements and number of interfaces.
  15053. + * @desc: Null-terminated vector of pointers to the descriptors (interface,
  15054. + * endpoint, etc) defining all functions in this device configuration.
  15055. + * @buf: Buffer for the resulting configuration descriptor.
  15056. + * @length: Length of buffer. If this is not big enough to hold the
  15057. + * entire configuration descriptor, an error code will be returned.
  15058. + *
  15059. + * This copies descriptors into the response buffer, building a descriptor
  15060. + * for that configuration. It returns the buffer length or a negative
  15061. + * status code. The config.wTotalLength field is set to match the length
  15062. + * of the result, but other descriptor fields (including power usage and
  15063. + * interface count) must be set by the caller.
  15064. + *
  15065. + * Gadget drivers could use this when constructing a config descriptor
  15066. + * in response to USB_REQ_GET_DESCRIPTOR. They will need to patch the
  15067. + * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.
  15068. + */
  15069. +int usb_gadget_config_buf(
  15070. + const struct usb_config_descriptor *config,
  15071. + void *buf,
  15072. + unsigned length,
  15073. + const struct usb_descriptor_header **desc
  15074. +)
  15075. +{
  15076. + struct usb_config_descriptor *cp = buf;
  15077. + int len;
  15078. +
  15079. + /* config descriptor first */
  15080. + if (length < USB_DT_CONFIG_SIZE || !desc)
  15081. + return -EINVAL;
  15082. + *cp = *config;
  15083. +
  15084. + /* then interface/endpoint/class/vendor/... */
  15085. + len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
  15086. + length - USB_DT_CONFIG_SIZE, desc);
  15087. + if (len < 0)
  15088. + return len;
  15089. + len += USB_DT_CONFIG_SIZE;
  15090. + if (len > 0xffff)
  15091. + return -EINVAL;
  15092. +
  15093. + /* patch up the config descriptor */
  15094. + cp->bLength = USB_DT_CONFIG_SIZE;
  15095. + cp->bDescriptorType = USB_DT_CONFIG;
  15096. + cp->wTotalLength = cpu_to_le16(len);
  15097. + cp->bmAttributes |= USB_CONFIG_ATT_ONE;
  15098. + return len;
  15099. +}
  15100. +
  15101. +/*-------------------------------------------------------------------------*/
  15102. +/*-------------------------------------------------------------------------*/
  15103. +
  15104. +
  15105. +#define RBUF_LEN (1024*1024)
  15106. +static int rbuf_start;
  15107. +static int rbuf_len;
  15108. +static __u8 rbuf[RBUF_LEN];
  15109. +
  15110. +/*-------------------------------------------------------------------------*/
  15111. +
  15112. +#define DRIVER_VERSION "St Patrick's Day 2004"
  15113. +
  15114. +static const char shortname [] = "zero";
  15115. +static const char longname [] = "YAMAHA YST-MS35D USB Speaker ";
  15116. +
  15117. +static const char source_sink [] = "source and sink data";
  15118. +static const char loopback [] = "loop input to output";
  15119. +
  15120. +/*-------------------------------------------------------------------------*/
  15121. +
  15122. +/*
  15123. + * driver assumes self-powered hardware, and
  15124. + * has no way for users to trigger remote wakeup.
  15125. + *
  15126. + * this version autoconfigures as much as possible,
  15127. + * which is reasonable for most "bulk-only" drivers.
  15128. + */
  15129. +static const char *EP_IN_NAME; /* source */
  15130. +static const char *EP_OUT_NAME; /* sink */
  15131. +
  15132. +/*-------------------------------------------------------------------------*/
  15133. +
  15134. +/* big enough to hold our biggest descriptor */
  15135. +#define USB_BUFSIZ 512
  15136. +
  15137. +struct zero_dev {
  15138. + spinlock_t lock;
  15139. + struct usb_gadget *gadget;
  15140. + struct usb_request *req; /* for control responses */
  15141. +
  15142. + /* when configured, we have one of two configs:
  15143. + * - source data (in to host) and sink it (out from host)
  15144. + * - or loop it back (out from host back in to host)
  15145. + */
  15146. + u8 config;
  15147. + struct usb_ep *in_ep, *out_ep;
  15148. +
  15149. + /* autoresume timer */
  15150. + struct timer_list resume;
  15151. +};
  15152. +
  15153. +#define xprintk(d,level,fmt,args...) \
  15154. + dev_printk(level , &(d)->gadget->dev , fmt , ## args)
  15155. +
  15156. +#ifdef DEBUG
  15157. +#define DBG(dev,fmt,args...) \
  15158. + xprintk(dev , KERN_DEBUG , fmt , ## args)
  15159. +#else
  15160. +#define DBG(dev,fmt,args...) \
  15161. + do { } while (0)
  15162. +#endif /* DEBUG */
  15163. +
  15164. +#ifdef VERBOSE
  15165. +#define VDBG DBG
  15166. +#else
  15167. +#define VDBG(dev,fmt,args...) \
  15168. + do { } while (0)
  15169. +#endif /* VERBOSE */
  15170. +
  15171. +#define ERROR(dev,fmt,args...) \
  15172. + xprintk(dev , KERN_ERR , fmt , ## args)
  15173. +#define WARN(dev,fmt,args...) \
  15174. + xprintk(dev , KERN_WARNING , fmt , ## args)
  15175. +#define INFO(dev,fmt,args...) \
  15176. + xprintk(dev , KERN_INFO , fmt , ## args)
  15177. +
  15178. +/*-------------------------------------------------------------------------*/
  15179. +
  15180. +static unsigned buflen = 4096;
  15181. +static unsigned qlen = 32;
  15182. +static unsigned pattern = 0;
  15183. +
  15184. +module_param (buflen, uint, S_IRUGO|S_IWUSR);
  15185. +module_param (qlen, uint, S_IRUGO|S_IWUSR);
  15186. +module_param (pattern, uint, S_IRUGO|S_IWUSR);
  15187. +
  15188. +/*
  15189. + * if it's nonzero, autoresume says how many seconds to wait
  15190. + * before trying to wake up the host after suspend.
  15191. + */
  15192. +static unsigned autoresume = 0;
  15193. +module_param (autoresume, uint, 0);
  15194. +
  15195. +/*
  15196. + * Normally the "loopback" configuration is second (index 1) so
  15197. + * it's not the default. Here's where to change that order, to
  15198. + * work better with hosts where config changes are problematic.
  15199. + * Or controllers (like superh) that only support one config.
  15200. + */
  15201. +static int loopdefault = 0;
  15202. +
  15203. +module_param (loopdefault, bool, S_IRUGO|S_IWUSR);
  15204. +
  15205. +/*-------------------------------------------------------------------------*/
  15206. +
  15207. +/* Thanks to NetChip Technologies for donating this product ID.
  15208. + *
  15209. + * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
  15210. + * Instead: allocate your own, using normal USB-IF procedures.
  15211. + */
  15212. +#ifndef CONFIG_USB_ZERO_HNPTEST
  15213. +#define DRIVER_VENDOR_NUM 0x0525 /* NetChip */
  15214. +#define DRIVER_PRODUCT_NUM 0xa4a0 /* Linux-USB "Gadget Zero" */
  15215. +#else
  15216. +#define DRIVER_VENDOR_NUM 0x1a0a /* OTG test device IDs */
  15217. +#define DRIVER_PRODUCT_NUM 0xbadd
  15218. +#endif
  15219. +
  15220. +/*-------------------------------------------------------------------------*/
  15221. +
  15222. +/*
  15223. + * DESCRIPTORS ... most are static, but strings and (full)
  15224. + * configuration descriptors are built on demand.
  15225. + */
  15226. +
  15227. +/*
  15228. +#define STRING_MANUFACTURER 25
  15229. +#define STRING_PRODUCT 42
  15230. +#define STRING_SERIAL 101
  15231. +*/
  15232. +#define STRING_MANUFACTURER 1
  15233. +#define STRING_PRODUCT 2
  15234. +#define STRING_SERIAL 3
  15235. +
  15236. +#define STRING_SOURCE_SINK 250
  15237. +#define STRING_LOOPBACK 251
  15238. +
  15239. +/*
  15240. + * This device advertises two configurations; these numbers work
  15241. + * on a pxa250 as well as more flexible hardware.
  15242. + */
  15243. +#define CONFIG_SOURCE_SINK 3
  15244. +#define CONFIG_LOOPBACK 2
  15245. +
  15246. +/*
  15247. +static struct usb_device_descriptor
  15248. +device_desc = {
  15249. + .bLength = sizeof device_desc,
  15250. + .bDescriptorType = USB_DT_DEVICE,
  15251. +
  15252. + .bcdUSB = __constant_cpu_to_le16 (0x0200),
  15253. + .bDeviceClass = USB_CLASS_VENDOR_SPEC,
  15254. +
  15255. + .idVendor = __constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
  15256. + .idProduct = __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
  15257. + .iManufacturer = STRING_MANUFACTURER,
  15258. + .iProduct = STRING_PRODUCT,
  15259. + .iSerialNumber = STRING_SERIAL,
  15260. + .bNumConfigurations = 2,
  15261. +};
  15262. +*/
  15263. +static struct usb_device_descriptor
  15264. +device_desc = {
  15265. + .bLength = sizeof device_desc,
  15266. + .bDescriptorType = USB_DT_DEVICE,
  15267. + .bcdUSB = __constant_cpu_to_le16 (0x0100),
  15268. + .bDeviceClass = USB_CLASS_PER_INTERFACE,
  15269. + .bDeviceSubClass = 0,
  15270. + .bDeviceProtocol = 0,
  15271. + .bMaxPacketSize0 = 64,
  15272. + .bcdDevice = __constant_cpu_to_le16 (0x0100),
  15273. + .idVendor = __constant_cpu_to_le16 (0x0499),
  15274. + .idProduct = __constant_cpu_to_le16 (0x3002),
  15275. + .iManufacturer = STRING_MANUFACTURER,
  15276. + .iProduct = STRING_PRODUCT,
  15277. + .iSerialNumber = STRING_SERIAL,
  15278. + .bNumConfigurations = 1,
  15279. +};
  15280. +
  15281. +static struct usb_config_descriptor
  15282. +z_config = {
  15283. + .bLength = sizeof z_config,
  15284. + .bDescriptorType = USB_DT_CONFIG,
  15285. +
  15286. + /* compute wTotalLength on the fly */
  15287. + .bNumInterfaces = 2,
  15288. + .bConfigurationValue = 1,
  15289. + .iConfiguration = 0,
  15290. + .bmAttributes = 0x40,
  15291. + .bMaxPower = 0, /* self-powered */
  15292. +};
  15293. +
  15294. +
  15295. +static struct usb_otg_descriptor
  15296. +otg_descriptor = {
  15297. + .bLength = sizeof otg_descriptor,
  15298. + .bDescriptorType = USB_DT_OTG,
  15299. +
  15300. + .bmAttributes = USB_OTG_SRP,
  15301. +};
  15302. +
  15303. +/* one interface in each configuration */
  15304. +#ifdef CONFIG_USB_GADGET_DUALSPEED
  15305. +
  15306. +/*
  15307. + * usb 2.0 devices need to expose both high speed and full speed
  15308. + * descriptors, unless they only run at full speed.
  15309. + *
  15310. + * that means alternate endpoint descriptors (bigger packets)
  15311. + * and a "device qualifier" ... plus more construction options
  15312. + * for the config descriptor.
  15313. + */
  15314. +
  15315. +static struct usb_qualifier_descriptor
  15316. +dev_qualifier = {
  15317. + .bLength = sizeof dev_qualifier,
  15318. + .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
  15319. +
  15320. + .bcdUSB = __constant_cpu_to_le16 (0x0200),
  15321. + .bDeviceClass = USB_CLASS_VENDOR_SPEC,
  15322. +
  15323. + .bNumConfigurations = 2,
  15324. +};
  15325. +
  15326. +
  15327. +struct usb_cs_as_general_descriptor {
  15328. + __u8 bLength;
  15329. + __u8 bDescriptorType;
  15330. +
  15331. + __u8 bDescriptorSubType;
  15332. + __u8 bTerminalLink;
  15333. + __u8 bDelay;
  15334. + __u16 wFormatTag;
  15335. +} __attribute__ ((packed));
  15336. +
  15337. +struct usb_cs_as_format_descriptor {
  15338. + __u8 bLength;
  15339. + __u8 bDescriptorType;
  15340. +
  15341. + __u8 bDescriptorSubType;
  15342. + __u8 bFormatType;
  15343. + __u8 bNrChannels;
  15344. + __u8 bSubframeSize;
  15345. + __u8 bBitResolution;
  15346. + __u8 bSamfreqType;
  15347. + __u8 tLowerSamFreq[3];
  15348. + __u8 tUpperSamFreq[3];
  15349. +} __attribute__ ((packed));
  15350. +
  15351. +static const struct usb_interface_descriptor
  15352. +z_audio_control_if_desc = {
  15353. + .bLength = sizeof z_audio_control_if_desc,
  15354. + .bDescriptorType = USB_DT_INTERFACE,
  15355. + .bInterfaceNumber = 0,
  15356. + .bAlternateSetting = 0,
  15357. + .bNumEndpoints = 0,
  15358. + .bInterfaceClass = USB_CLASS_AUDIO,
  15359. + .bInterfaceSubClass = 0x1,
  15360. + .bInterfaceProtocol = 0,
  15361. + .iInterface = 0,
  15362. +};
  15363. +
  15364. +static const struct usb_interface_descriptor
  15365. +z_audio_if_desc = {
  15366. + .bLength = sizeof z_audio_if_desc,
  15367. + .bDescriptorType = USB_DT_INTERFACE,
  15368. + .bInterfaceNumber = 1,
  15369. + .bAlternateSetting = 0,
  15370. + .bNumEndpoints = 0,
  15371. + .bInterfaceClass = USB_CLASS_AUDIO,
  15372. + .bInterfaceSubClass = 0x2,
  15373. + .bInterfaceProtocol = 0,
  15374. + .iInterface = 0,
  15375. +};
  15376. +
  15377. +static const struct usb_interface_descriptor
  15378. +z_audio_if_desc2 = {
  15379. + .bLength = sizeof z_audio_if_desc,
  15380. + .bDescriptorType = USB_DT_INTERFACE,
  15381. + .bInterfaceNumber = 1,
  15382. + .bAlternateSetting = 1,
  15383. + .bNumEndpoints = 1,
  15384. + .bInterfaceClass = USB_CLASS_AUDIO,
  15385. + .bInterfaceSubClass = 0x2,
  15386. + .bInterfaceProtocol = 0,
  15387. + .iInterface = 0,
  15388. +};
  15389. +
  15390. +static const struct usb_cs_as_general_descriptor
  15391. +z_audio_cs_as_if_desc = {
  15392. + .bLength = 7,
  15393. + .bDescriptorType = 0x24,
  15394. +
  15395. + .bDescriptorSubType = 0x01,
  15396. + .bTerminalLink = 0x01,
  15397. + .bDelay = 0x0,
  15398. + .wFormatTag = __constant_cpu_to_le16 (0x0001)
  15399. +};
  15400. +
  15401. +
  15402. +static const struct usb_cs_as_format_descriptor
  15403. +z_audio_cs_as_format_desc = {
  15404. + .bLength = 0xe,
  15405. + .bDescriptorType = 0x24,
  15406. +
  15407. + .bDescriptorSubType = 2,
  15408. + .bFormatType = 1,
  15409. + .bNrChannels = 1,
  15410. + .bSubframeSize = 1,
  15411. + .bBitResolution = 8,
  15412. + .bSamfreqType = 0,
  15413. + .tLowerSamFreq = {0x7e, 0x13, 0x00},
  15414. + .tUpperSamFreq = {0xe2, 0xd6, 0x00},
  15415. +};
  15416. +
  15417. +static const struct usb_endpoint_descriptor
  15418. +z_iso_ep = {
  15419. + .bLength = 0x09,
  15420. + .bDescriptorType = 0x05,
  15421. + .bEndpointAddress = 0x04,
  15422. + .bmAttributes = 0x09,
  15423. + .wMaxPacketSize = 0x0038,
  15424. + .bInterval = 0x01,
  15425. + .bRefresh = 0x00,
  15426. + .bSynchAddress = 0x00,
  15427. +};
  15428. +
  15429. +static char z_iso_ep2[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
  15430. +
  15431. +// 9 bytes
  15432. +static char z_ac_interface_header_desc[] =
  15433. +{ 0x09, 0x24, 0x01, 0x00, 0x01, 0x2b, 0x00, 0x01, 0x01 };
  15434. +
  15435. +// 12 bytes
  15436. +static char z_0[] = {0x0c, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02,
  15437. + 0x03, 0x00, 0x00, 0x00};
  15438. +// 13 bytes
  15439. +static char z_1[] = {0x0d, 0x24, 0x06, 0x02, 0x01, 0x02, 0x15, 0x00,
  15440. + 0x02, 0x00, 0x02, 0x00, 0x00};
  15441. +// 9 bytes
  15442. +static char z_2[] = {0x09, 0x24, 0x03, 0x03, 0x01, 0x03, 0x00, 0x02,
  15443. + 0x00};
  15444. +
  15445. +static char za_0[] = {0x09, 0x04, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00,
  15446. + 0x00};
  15447. +
  15448. +static char za_1[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
  15449. +
  15450. +static char za_2[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x01, 0x08, 0x00,
  15451. + 0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
  15452. +
  15453. +static char za_3[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00,
  15454. + 0x00};
  15455. +
  15456. +static char za_4[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
  15457. +
  15458. +static char za_5[] = {0x09, 0x04, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00,
  15459. + 0x00};
  15460. +
  15461. +static char za_6[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
  15462. +
  15463. +static char za_7[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x02, 0x10, 0x00,
  15464. + 0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
  15465. +
  15466. +static char za_8[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00,
  15467. + 0x00};
  15468. +
  15469. +static char za_9[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
  15470. +
  15471. +static char za_10[] = {0x09, 0x04, 0x01, 0x04, 0x01, 0x01, 0x02, 0x00,
  15472. + 0x00};
  15473. +
  15474. +static char za_11[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
  15475. +
  15476. +static char za_12[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x00,
  15477. + 0x73, 0x13, 0x00, 0xe2, 0xd6, 0x00};
  15478. +
  15479. +static char za_13[] = {0x09, 0x05, 0x04, 0x09, 0xe0, 0x00, 0x01, 0x00,
  15480. + 0x00};
  15481. +
  15482. +static char za_14[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
  15483. +
  15484. +static char za_15[] = {0x09, 0x04, 0x01, 0x05, 0x01, 0x01, 0x02, 0x00,
  15485. + 0x00};
  15486. +
  15487. +static char za_16[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
  15488. +
  15489. +static char za_17[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x03, 0x14, 0x00,
  15490. + 0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
  15491. +
  15492. +static char za_18[] = {0x09, 0x05, 0x04, 0x09, 0xa8, 0x00, 0x01, 0x00,
  15493. + 0x00};
  15494. +
  15495. +static char za_19[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
  15496. +
  15497. +static char za_20[] = {0x09, 0x04, 0x01, 0x06, 0x01, 0x01, 0x02, 0x00,
  15498. + 0x00};
  15499. +
  15500. +static char za_21[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00};
  15501. +
  15502. +static char za_22[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x03, 0x14, 0x00,
  15503. + 0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00};
  15504. +
  15505. +static char za_23[] = {0x09, 0x05, 0x04, 0x09, 0x50, 0x01, 0x01, 0x00,
  15506. + 0x00};
  15507. +
  15508. +static char za_24[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02};
  15509. +
  15510. +
  15511. +
  15512. +static const struct usb_descriptor_header *z_function [] = {
  15513. + (struct usb_descriptor_header *) &z_audio_control_if_desc,
  15514. + (struct usb_descriptor_header *) &z_ac_interface_header_desc,
  15515. + (struct usb_descriptor_header *) &z_0,
  15516. + (struct usb_descriptor_header *) &z_1,
  15517. + (struct usb_descriptor_header *) &z_2,
  15518. + (struct usb_descriptor_header *) &z_audio_if_desc,
  15519. + (struct usb_descriptor_header *) &z_audio_if_desc2,
  15520. + (struct usb_descriptor_header *) &z_audio_cs_as_if_desc,
  15521. + (struct usb_descriptor_header *) &z_audio_cs_as_format_desc,
  15522. + (struct usb_descriptor_header *) &z_iso_ep,
  15523. + (struct usb_descriptor_header *) &z_iso_ep2,
  15524. + (struct usb_descriptor_header *) &za_0,
  15525. + (struct usb_descriptor_header *) &za_1,
  15526. + (struct usb_descriptor_header *) &za_2,
  15527. + (struct usb_descriptor_header *) &za_3,
  15528. + (struct usb_descriptor_header *) &za_4,
  15529. + (struct usb_descriptor_header *) &za_5,
  15530. + (struct usb_descriptor_header *) &za_6,
  15531. + (struct usb_descriptor_header *) &za_7,
  15532. + (struct usb_descriptor_header *) &za_8,
  15533. + (struct usb_descriptor_header *) &za_9,
  15534. + (struct usb_descriptor_header *) &za_10,
  15535. + (struct usb_descriptor_header *) &za_11,
  15536. + (struct usb_descriptor_header *) &za_12,
  15537. + (struct usb_descriptor_header *) &za_13,
  15538. + (struct usb_descriptor_header *) &za_14,
  15539. + (struct usb_descriptor_header *) &za_15,
  15540. + (struct usb_descriptor_header *) &za_16,
  15541. + (struct usb_descriptor_header *) &za_17,
  15542. + (struct usb_descriptor_header *) &za_18,
  15543. + (struct usb_descriptor_header *) &za_19,
  15544. + (struct usb_descriptor_header *) &za_20,
  15545. + (struct usb_descriptor_header *) &za_21,
  15546. + (struct usb_descriptor_header *) &za_22,
  15547. + (struct usb_descriptor_header *) &za_23,
  15548. + (struct usb_descriptor_header *) &za_24,
  15549. + NULL,
  15550. +};
  15551. +
  15552. +/* maxpacket and other transfer characteristics vary by speed. */
  15553. +#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
  15554. +
  15555. +#else
  15556. +
  15557. +/* if there's no high speed support, maxpacket doesn't change. */
  15558. +#define ep_desc(g,hs,fs) fs
  15559. +
  15560. +#endif /* !CONFIG_USB_GADGET_DUALSPEED */
  15561. +
  15562. +static char manufacturer [40];
  15563. +//static char serial [40];
  15564. +static char serial [] = "Ser 00 em";
  15565. +
  15566. +/* static strings, in UTF-8 */
  15567. +static struct usb_string strings [] = {
  15568. + { STRING_MANUFACTURER, manufacturer, },
  15569. + { STRING_PRODUCT, longname, },
  15570. + { STRING_SERIAL, serial, },
  15571. + { STRING_LOOPBACK, loopback, },
  15572. + { STRING_SOURCE_SINK, source_sink, },
  15573. + { } /* end of list */
  15574. +};
  15575. +
  15576. +static struct usb_gadget_strings stringtab = {
  15577. + .language = 0x0409, /* en-us */
  15578. + .strings = strings,
  15579. +};
  15580. +
  15581. +/*
  15582. + * config descriptors are also handcrafted. these must agree with code
  15583. + * that sets configurations, and with code managing interfaces and their
  15584. + * altsettings. other complexity may come from:
  15585. + *
  15586. + * - high speed support, including "other speed config" rules
  15587. + * - multiple configurations
  15588. + * - interfaces with alternate settings
  15589. + * - embedded class or vendor-specific descriptors
  15590. + *
  15591. + * this handles high speed, and has a second config that could as easily
  15592. + * have been an alternate interface setting (on most hardware).
  15593. + *
  15594. + * NOTE: to demonstrate (and test) more USB capabilities, this driver
  15595. + * should include an altsetting to test interrupt transfers, including
  15596. + * high bandwidth modes at high speed. (Maybe work like Intel's test
  15597. + * device?)
  15598. + */
  15599. +static int
  15600. +config_buf (struct usb_gadget *gadget, u8 *buf, u8 type, unsigned index)
  15601. +{
  15602. + int len;
  15603. + const struct usb_descriptor_header **function;
  15604. +
  15605. + function = z_function;
  15606. + len = usb_gadget_config_buf (&z_config, buf, USB_BUFSIZ, function);
  15607. + if (len < 0)
  15608. + return len;
  15609. + ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
  15610. + return len;
  15611. +}
  15612. +
  15613. +/*-------------------------------------------------------------------------*/
  15614. +
  15615. +static struct usb_request *
  15616. +alloc_ep_req (struct usb_ep *ep, unsigned length)
  15617. +{
  15618. + struct usb_request *req;
  15619. +
  15620. + req = usb_ep_alloc_request (ep, GFP_ATOMIC);
  15621. + if (req) {
  15622. + req->length = length;
  15623. + req->buf = usb_ep_alloc_buffer (ep, length,
  15624. + &req->dma, GFP_ATOMIC);
  15625. + if (!req->buf) {
  15626. + usb_ep_free_request (ep, req);
  15627. + req = NULL;
  15628. + }
  15629. + }
  15630. + return req;
  15631. +}
  15632. +
  15633. +static void free_ep_req (struct usb_ep *ep, struct usb_request *req)
  15634. +{
  15635. + if (req->buf)
  15636. + usb_ep_free_buffer (ep, req->buf, req->dma, req->length);
  15637. + usb_ep_free_request (ep, req);
  15638. +}
  15639. +
  15640. +/*-------------------------------------------------------------------------*/
  15641. +
  15642. +/* optionally require specific source/sink data patterns */
  15643. +
  15644. +static int
  15645. +check_read_data (
  15646. + struct zero_dev *dev,
  15647. + struct usb_ep *ep,
  15648. + struct usb_request *req
  15649. +)
  15650. +{
  15651. + unsigned i;
  15652. + u8 *buf = req->buf;
  15653. +
  15654. + for (i = 0; i < req->actual; i++, buf++) {
  15655. + switch (pattern) {
  15656. + /* all-zeroes has no synchronization issues */
  15657. + case 0:
  15658. + if (*buf == 0)
  15659. + continue;
  15660. + break;
  15661. + /* mod63 stays in sync with short-terminated transfers,
  15662. + * or otherwise when host and gadget agree on how large
  15663. + * each usb transfer request should be. resync is done
  15664. + * with set_interface or set_config.
  15665. + */
  15666. + case 1:
  15667. + if (*buf == (u8)(i % 63))
  15668. + continue;
  15669. + break;
  15670. + }
  15671. + ERROR (dev, "bad OUT byte, buf [%d] = %d\n", i, *buf);
  15672. + usb_ep_set_halt (ep);
  15673. + return -EINVAL;
  15674. + }
  15675. + return 0;
  15676. +}
  15677. +
  15678. +/*-------------------------------------------------------------------------*/
  15679. +
  15680. +static void zero_reset_config (struct zero_dev *dev)
  15681. +{
  15682. + if (dev->config == 0)
  15683. + return;
  15684. +
  15685. + DBG (dev, "reset config\n");
  15686. +
  15687. + /* just disable endpoints, forcing completion of pending i/o.
  15688. + * all our completion handlers free their requests in this case.
  15689. + */
  15690. + if (dev->in_ep) {
  15691. + usb_ep_disable (dev->in_ep);
  15692. + dev->in_ep = NULL;
  15693. + }
  15694. + if (dev->out_ep) {
  15695. + usb_ep_disable (dev->out_ep);
  15696. + dev->out_ep = NULL;
  15697. + }
  15698. + dev->config = 0;
  15699. + del_timer (&dev->resume);
  15700. +}
  15701. +
  15702. +#define _write(f, buf, sz) (f->f_op->write(f, buf, sz, &f->f_pos))
  15703. +
  15704. +static void
  15705. +zero_isoc_complete (struct usb_ep *ep, struct usb_request *req)
  15706. +{
  15707. + struct zero_dev *dev = ep->driver_data;
  15708. + int status = req->status;
  15709. + int i, j;
  15710. +
  15711. + switch (status) {
  15712. +
  15713. + case 0: /* normal completion? */
  15714. + //printk ("\nzero ---------------> isoc normal completion %d bytes\n", req->actual);
  15715. + for (i=0, j=rbuf_start; i<req->actual; i++) {
  15716. + //printk ("%02x ", ((__u8*)req->buf)[i]);
  15717. + rbuf[j] = ((__u8*)req->buf)[i];
  15718. + j++;
  15719. + if (j >= RBUF_LEN) j=0;
  15720. + }
  15721. + rbuf_start = j;
  15722. + //printk ("\n\n");
  15723. +
  15724. + if (rbuf_len < RBUF_LEN) {
  15725. + rbuf_len += req->actual;
  15726. + if (rbuf_len > RBUF_LEN) {
  15727. + rbuf_len = RBUF_LEN;
  15728. + }
  15729. + }
  15730. +
  15731. + break;
  15732. +
  15733. + /* this endpoint is normally active while we're configured */
  15734. + case -ECONNABORTED: /* hardware forced ep reset */
  15735. + case -ECONNRESET: /* request dequeued */
  15736. + case -ESHUTDOWN: /* disconnect from host */
  15737. + VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status,
  15738. + req->actual, req->length);
  15739. + if (ep == dev->out_ep)
  15740. + check_read_data (dev, ep, req);
  15741. + free_ep_req (ep, req);
  15742. + return;
  15743. +
  15744. + case -EOVERFLOW: /* buffer overrun on read means that
  15745. + * we didn't provide a big enough
  15746. + * buffer.
  15747. + */
  15748. + default:
  15749. +#if 1
  15750. + DBG (dev, "%s complete --> %d, %d/%d\n", ep->name,
  15751. + status, req->actual, req->length);
  15752. +#endif
  15753. + case -EREMOTEIO: /* short read */
  15754. + break;
  15755. + }
  15756. +
  15757. + status = usb_ep_queue (ep, req, GFP_ATOMIC);
  15758. + if (status) {
  15759. + ERROR (dev, "kill %s: resubmit %d bytes --> %d\n",
  15760. + ep->name, req->length, status);
  15761. + usb_ep_set_halt (ep);
  15762. + /* FIXME recover later ... somehow */
  15763. + }
  15764. +}
  15765. +
  15766. +static struct usb_request *
  15767. +zero_start_isoc_ep (struct usb_ep *ep, int gfp_flags)
  15768. +{
  15769. + struct usb_request *req;
  15770. + int status;
  15771. +
  15772. + req = alloc_ep_req (ep, 512);
  15773. + if (!req)
  15774. + return NULL;
  15775. +
  15776. + req->complete = zero_isoc_complete;
  15777. +
  15778. + status = usb_ep_queue (ep, req, gfp_flags);
  15779. + if (status) {
  15780. + struct zero_dev *dev = ep->driver_data;
  15781. +
  15782. + ERROR (dev, "start %s --> %d\n", ep->name, status);
  15783. + free_ep_req (ep, req);
  15784. + req = NULL;
  15785. + }
  15786. +
  15787. + return req;
  15788. +}
  15789. +
  15790. +/* change our operational config. this code must agree with the code
  15791. + * that returns config descriptors, and altsetting code.
  15792. + *
  15793. + * it's also responsible for power management interactions. some
  15794. + * configurations might not work with our current power sources.
  15795. + *
  15796. + * note that some device controller hardware will constrain what this
  15797. + * code can do, perhaps by disallowing more than one configuration or
  15798. + * by limiting configuration choices (like the pxa2xx).
  15799. + */
  15800. +static int
  15801. +zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags)
  15802. +{
  15803. + int result = 0;
  15804. + struct usb_gadget *gadget = dev->gadget;
  15805. + const struct usb_endpoint_descriptor *d;
  15806. + struct usb_ep *ep;
  15807. +
  15808. + if (number == dev->config)
  15809. + return 0;
  15810. +
  15811. + zero_reset_config (dev);
  15812. +
  15813. + gadget_for_each_ep (ep, gadget) {
  15814. +
  15815. + if (strcmp (ep->name, "ep4") == 0) {
  15816. +
  15817. + d = (struct usb_endpoint_descripter *)&za_23; // isoc ep desc for audio i/f alt setting 6
  15818. + result = usb_ep_enable (ep, d);
  15819. +
  15820. + if (result == 0) {
  15821. + ep->driver_data = dev;
  15822. + dev->in_ep = ep;
  15823. +
  15824. + if (zero_start_isoc_ep (ep, gfp_flags) != 0) {
  15825. +
  15826. + dev->in_ep = ep;
  15827. + continue;
  15828. + }
  15829. +
  15830. + usb_ep_disable (ep);
  15831. + result = -EIO;
  15832. + }
  15833. + }
  15834. +
  15835. + }
  15836. +
  15837. + dev->config = number;
  15838. + return result;
  15839. +}
  15840. +
  15841. +/*-------------------------------------------------------------------------*/
  15842. +
  15843. +static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req)
  15844. +{
  15845. + if (req->status || req->actual != req->length)
  15846. + DBG ((struct zero_dev *) ep->driver_data,
  15847. + "setup complete --> %d, %d/%d\n",
  15848. + req->status, req->actual, req->length);
  15849. +}
  15850. +
  15851. +/*
  15852. + * The setup() callback implements all the ep0 functionality that's
  15853. + * not handled lower down, in hardware or the hardware driver (like
  15854. + * device and endpoint feature flags, and their status). It's all
  15855. + * housekeeping for the gadget function we're implementing. Most of
  15856. + * the work is in config-specific setup.
  15857. + */
  15858. +static int
  15859. +zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
  15860. +{
  15861. + struct zero_dev *dev = get_gadget_data (gadget);
  15862. + struct usb_request *req = dev->req;
  15863. + int value = -EOPNOTSUPP;
  15864. +
  15865. + /* usually this stores reply data in the pre-allocated ep0 buffer,
  15866. + * but config change events will reconfigure hardware.
  15867. + */
  15868. + req->zero = 0;
  15869. + switch (ctrl->bRequest) {
  15870. +
  15871. + case USB_REQ_GET_DESCRIPTOR:
  15872. +
  15873. + switch (ctrl->wValue >> 8) {
  15874. +
  15875. + case USB_DT_DEVICE:
  15876. + value = min (ctrl->wLength, (u16) sizeof device_desc);
  15877. + memcpy (req->buf, &device_desc, value);
  15878. + break;
  15879. +#ifdef CONFIG_USB_GADGET_DUALSPEED
  15880. + case USB_DT_DEVICE_QUALIFIER:
  15881. + if (!gadget->is_dualspeed)
  15882. + break;
  15883. + value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
  15884. + memcpy (req->buf, &dev_qualifier, value);
  15885. + break;
  15886. +
  15887. + case USB_DT_OTHER_SPEED_CONFIG:
  15888. + if (!gadget->is_dualspeed)
  15889. + break;
  15890. + // FALLTHROUGH
  15891. +#endif /* CONFIG_USB_GADGET_DUALSPEED */
  15892. + case USB_DT_CONFIG:
  15893. + value = config_buf (gadget, req->buf,
  15894. + ctrl->wValue >> 8,
  15895. + ctrl->wValue & 0xff);
  15896. + if (value >= 0)
  15897. + value = min (ctrl->wLength, (u16) value);
  15898. + break;
  15899. +
  15900. + case USB_DT_STRING:
  15901. + /* wIndex == language code.
  15902. + * this driver only handles one language, you can
  15903. + * add string tables for other languages, using
  15904. + * any UTF-8 characters
  15905. + */
  15906. + value = usb_gadget_get_string (&stringtab,
  15907. + ctrl->wValue & 0xff, req->buf);
  15908. + if (value >= 0) {
  15909. + value = min (ctrl->wLength, (u16) value);
  15910. + }
  15911. + break;
  15912. + }
  15913. + break;
  15914. +
  15915. + /* currently two configs, two speeds */
  15916. + case USB_REQ_SET_CONFIGURATION:
  15917. + if (ctrl->bRequestType != 0)
  15918. + goto unknown;
  15919. +
  15920. + spin_lock (&dev->lock);
  15921. + value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC);
  15922. + spin_unlock (&dev->lock);
  15923. + break;
  15924. + case USB_REQ_GET_CONFIGURATION:
  15925. + if (ctrl->bRequestType != USB_DIR_IN)
  15926. + goto unknown;
  15927. + *(u8 *)req->buf = dev->config;
  15928. + value = min (ctrl->wLength, (u16) 1);
  15929. + break;
  15930. +
  15931. + /* until we add altsetting support, or other interfaces,
  15932. + * only 0/0 are possible. pxa2xx only supports 0/0 (poorly)
  15933. + * and already killed pending endpoint I/O.
  15934. + */
  15935. + case USB_REQ_SET_INTERFACE:
  15936. +
  15937. + if (ctrl->bRequestType != USB_RECIP_INTERFACE)
  15938. + goto unknown;
  15939. + spin_lock (&dev->lock);
  15940. + if (dev->config) {
  15941. + u8 config = dev->config;
  15942. +
  15943. + /* resets interface configuration, forgets about
  15944. + * previous transaction state (queued bufs, etc)
  15945. + * and re-inits endpoint state (toggle etc)
  15946. + * no response queued, just zero status == success.
  15947. + * if we had more than one interface we couldn't
  15948. + * use this "reset the config" shortcut.
  15949. + */
  15950. + zero_reset_config (dev);
  15951. + zero_set_config (dev, config, GFP_ATOMIC);
  15952. + value = 0;
  15953. + }
  15954. + spin_unlock (&dev->lock);
  15955. + break;
  15956. + case USB_REQ_GET_INTERFACE:
  15957. + if ((ctrl->bRequestType == 0x21) && (ctrl->wIndex == 0x02)) {
  15958. + value = ctrl->wLength;
  15959. + break;
  15960. + }
  15961. + else {
  15962. + if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
  15963. + goto unknown;
  15964. + if (!dev->config)
  15965. + break;
  15966. + if (ctrl->wIndex != 0) {
  15967. + value = -EDOM;
  15968. + break;
  15969. + }
  15970. + *(u8 *)req->buf = 0;
  15971. + value = min (ctrl->wLength, (u16) 1);
  15972. + }
  15973. + break;
  15974. +
  15975. + /*
  15976. + * These are the same vendor-specific requests supported by
  15977. + * Intel's USB 2.0 compliance test devices. We exceed that
  15978. + * device spec by allowing multiple-packet requests.
  15979. + */
  15980. + case 0x5b: /* control WRITE test -- fill the buffer */
  15981. + if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
  15982. + goto unknown;
  15983. + if (ctrl->wValue || ctrl->wIndex)
  15984. + break;
  15985. + /* just read that many bytes into the buffer */
  15986. + if (ctrl->wLength > USB_BUFSIZ)
  15987. + break;
  15988. + value = ctrl->wLength;
  15989. + break;
  15990. + case 0x5c: /* control READ test -- return the buffer */
  15991. + if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
  15992. + goto unknown;
  15993. + if (ctrl->wValue || ctrl->wIndex)
  15994. + break;
  15995. + /* expect those bytes are still in the buffer; send back */
  15996. + if (ctrl->wLength > USB_BUFSIZ
  15997. + || ctrl->wLength != req->length)
  15998. + break;
  15999. + value = ctrl->wLength;
  16000. + break;
  16001. +
  16002. + case 0x01: // SET_CUR
  16003. + case 0x02:
  16004. + case 0x03:
  16005. + case 0x04:
  16006. + case 0x05:
  16007. + value = ctrl->wLength;
  16008. + break;
  16009. + case 0x81:
  16010. + switch (ctrl->wValue) {
  16011. + case 0x0201:
  16012. + case 0x0202:
  16013. + ((u8*)req->buf)[0] = 0x00;
  16014. + ((u8*)req->buf)[1] = 0xe3;
  16015. + break;
  16016. + case 0x0300:
  16017. + case 0x0500:
  16018. + ((u8*)req->buf)[0] = 0x00;
  16019. + break;
  16020. + }
  16021. + //((u8*)req->buf)[0] = 0x81;
  16022. + //((u8*)req->buf)[1] = 0x81;
  16023. + value = ctrl->wLength;
  16024. + break;
  16025. + case 0x82:
  16026. + switch (ctrl->wValue) {
  16027. + case 0x0201:
  16028. + case 0x0202:
  16029. + ((u8*)req->buf)[0] = 0x00;
  16030. + ((u8*)req->buf)[1] = 0xc3;
  16031. + break;
  16032. + case 0x0300:
  16033. + case 0x0500:
  16034. + ((u8*)req->buf)[0] = 0x00;
  16035. + break;
  16036. + }
  16037. + //((u8*)req->buf)[0] = 0x82;
  16038. + //((u8*)req->buf)[1] = 0x82;
  16039. + value = ctrl->wLength;
  16040. + break;
  16041. + case 0x83:
  16042. + switch (ctrl->wValue) {
  16043. + case 0x0201:
  16044. + case 0x0202:
  16045. + ((u8*)req->buf)[0] = 0x00;
  16046. + ((u8*)req->buf)[1] = 0x00;
  16047. + break;
  16048. + case 0x0300:
  16049. + ((u8*)req->buf)[0] = 0x60;
  16050. + break;
  16051. + case 0x0500:
  16052. + ((u8*)req->buf)[0] = 0x18;
  16053. + break;
  16054. + }
  16055. + //((u8*)req->buf)[0] = 0x83;
  16056. + //((u8*)req->buf)[1] = 0x83;
  16057. + value = ctrl->wLength;
  16058. + break;
  16059. + case 0x84:
  16060. + switch (ctrl->wValue) {
  16061. + case 0x0201:
  16062. + case 0x0202:
  16063. + ((u8*)req->buf)[0] = 0x00;
  16064. + ((u8*)req->buf)[1] = 0x01;
  16065. + break;
  16066. + case 0x0300:
  16067. + case 0x0500:
  16068. + ((u8*)req->buf)[0] = 0x08;
  16069. + break;
  16070. + }
  16071. + //((u8*)req->buf)[0] = 0x84;
  16072. + //((u8*)req->buf)[1] = 0x84;
  16073. + value = ctrl->wLength;
  16074. + break;
  16075. + case 0x85:
  16076. + ((u8*)req->buf)[0] = 0x85;
  16077. + ((u8*)req->buf)[1] = 0x85;
  16078. + value = ctrl->wLength;
  16079. + break;
  16080. +
  16081. +
  16082. + default:
  16083. +unknown:
  16084. + printk("unknown control req%02x.%02x v%04x i%04x l%d\n",
  16085. + ctrl->bRequestType, ctrl->bRequest,
  16086. + ctrl->wValue, ctrl->wIndex, ctrl->wLength);
  16087. + }
  16088. +
  16089. + /* respond with data transfer before status phase? */
  16090. + if (value >= 0) {
  16091. + req->length = value;
  16092. + req->zero = value < ctrl->wLength
  16093. + && (value % gadget->ep0->maxpacket) == 0;
  16094. + value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
  16095. + if (value < 0) {
  16096. + DBG (dev, "ep_queue < 0 --> %d\n", value);
  16097. + req->status = 0;
  16098. + zero_setup_complete (gadget->ep0, req);
  16099. + }
  16100. + }
  16101. +
  16102. + /* device either stalls (value < 0) or reports success */
  16103. + return value;
  16104. +}
  16105. +
  16106. +static void
  16107. +zero_disconnect (struct usb_gadget *gadget)
  16108. +{
  16109. + struct zero_dev *dev = get_gadget_data (gadget);
  16110. + unsigned long flags;
  16111. +
  16112. + spin_lock_irqsave (&dev->lock, flags);
  16113. + zero_reset_config (dev);
  16114. +
  16115. + /* a more significant application might have some non-usb
  16116. + * activities to quiesce here, saving resources like power
  16117. + * or pushing the notification up a network stack.
  16118. + */
  16119. + spin_unlock_irqrestore (&dev->lock, flags);
  16120. +
  16121. + /* next we may get setup() calls to enumerate new connections;
  16122. + * or an unbind() during shutdown (including removing module).
  16123. + */
  16124. +}
  16125. +
  16126. +static void
  16127. +zero_autoresume (unsigned long _dev)
  16128. +{
  16129. + struct zero_dev *dev = (struct zero_dev *) _dev;
  16130. + int status;
  16131. +
  16132. + /* normally the host would be woken up for something
  16133. + * more significant than just a timer firing...
  16134. + */
  16135. + if (dev->gadget->speed != USB_SPEED_UNKNOWN) {
  16136. + status = usb_gadget_wakeup (dev->gadget);
  16137. + DBG (dev, "wakeup --> %d\n", status);
  16138. + }
  16139. +}
  16140. +
  16141. +/*-------------------------------------------------------------------------*/
  16142. +
  16143. +static void
  16144. +zero_unbind (struct usb_gadget *gadget)
  16145. +{
  16146. + struct zero_dev *dev = get_gadget_data (gadget);
  16147. +
  16148. + DBG (dev, "unbind\n");
  16149. +
  16150. + /* we've already been disconnected ... no i/o is active */
  16151. + if (dev->req)
  16152. + free_ep_req (gadget->ep0, dev->req);
  16153. + del_timer_sync (&dev->resume);
  16154. + kfree (dev);
  16155. + set_gadget_data (gadget, NULL);
  16156. +}
  16157. +
  16158. +static int
  16159. +zero_bind (struct usb_gadget *gadget)
  16160. +{
  16161. + struct zero_dev *dev;
  16162. + //struct usb_ep *ep;
  16163. +
  16164. + printk("binding\n");
  16165. + /*
  16166. + * DRIVER POLICY CHOICE: you may want to do this differently.
  16167. + * One thing to avoid is reusing a bcdDevice revision code
  16168. + * with different host-visible configurations or behavior
  16169. + * restrictions -- using ep1in/ep2out vs ep1out/ep3in, etc
  16170. + */
  16171. + //device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);
  16172. +
  16173. +
  16174. + /* ok, we made sense of the hardware ... */
  16175. + dev = kmalloc (sizeof *dev, SLAB_KERNEL);
  16176. + if (!dev)
  16177. + return -ENOMEM;
  16178. + memset (dev, 0, sizeof *dev);
  16179. + spin_lock_init (&dev->lock);
  16180. + dev->gadget = gadget;
  16181. + set_gadget_data (gadget, dev);
  16182. +
  16183. + /* preallocate control response and buffer */
  16184. + dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
  16185. + if (!dev->req)
  16186. + goto enomem;
  16187. + dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
  16188. + &dev->req->dma, GFP_KERNEL);
  16189. + if (!dev->req->buf)
  16190. + goto enomem;
  16191. +
  16192. + dev->req->complete = zero_setup_complete;
  16193. +
  16194. + device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
  16195. +
  16196. +#ifdef CONFIG_USB_GADGET_DUALSPEED
  16197. + /* assume ep0 uses the same value for both speeds ... */
  16198. + dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
  16199. +
  16200. + /* and that all endpoints are dual-speed */
  16201. + //hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
  16202. + //hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
  16203. +#endif
  16204. +
  16205. + usb_gadget_set_selfpowered (gadget);
  16206. +
  16207. + init_timer (&dev->resume);
  16208. + dev->resume.function = zero_autoresume;
  16209. + dev->resume.data = (unsigned long) dev;
  16210. +
  16211. + gadget->ep0->driver_data = dev;
  16212. +
  16213. + INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);
  16214. + INFO (dev, "using %s, OUT %s IN %s\n", gadget->name,
  16215. + EP_OUT_NAME, EP_IN_NAME);
  16216. +
  16217. + snprintf (manufacturer, sizeof manufacturer,
  16218. + UTS_SYSNAME " " UTS_RELEASE " with %s",
  16219. + gadget->name);
  16220. +
  16221. + return 0;
  16222. +
  16223. +enomem:
  16224. + zero_unbind (gadget);
  16225. + return -ENOMEM;
  16226. +}
  16227. +
  16228. +/*-------------------------------------------------------------------------*/
  16229. +
  16230. +static void
  16231. +zero_suspend (struct usb_gadget *gadget)
  16232. +{
  16233. + struct zero_dev *dev = get_gadget_data (gadget);
  16234. +
  16235. + if (gadget->speed == USB_SPEED_UNKNOWN)
  16236. + return;
  16237. +
  16238. + if (autoresume) {
  16239. + mod_timer (&dev->resume, jiffies + (HZ * autoresume));
  16240. + DBG (dev, "suspend, wakeup in %d seconds\n", autoresume);
  16241. + } else
  16242. + DBG (dev, "suspend\n");
  16243. +}
  16244. +
  16245. +static void
  16246. +zero_resume (struct usb_gadget *gadget)
  16247. +{
  16248. + struct zero_dev *dev = get_gadget_data (gadget);
  16249. +
  16250. + DBG (dev, "resume\n");
  16251. + del_timer (&dev->resume);
  16252. +}
  16253. +
  16254. +
  16255. +/*-------------------------------------------------------------------------*/
  16256. +
  16257. +static struct usb_gadget_driver zero_driver = {
  16258. +#ifdef CONFIG_USB_GADGET_DUALSPEED
  16259. + .speed = USB_SPEED_HIGH,
  16260. +#else
  16261. + .speed = USB_SPEED_FULL,
  16262. +#endif
  16263. + .function = (char *) longname,
  16264. + .bind = zero_bind,
  16265. + .unbind = zero_unbind,
  16266. +
  16267. + .setup = zero_setup,
  16268. + .disconnect = zero_disconnect,
  16269. +
  16270. + .suspend = zero_suspend,
  16271. + .resume = zero_resume,
  16272. +
  16273. + .driver = {
  16274. + .name = (char *) shortname,
  16275. + // .shutdown = ...
  16276. + // .suspend = ...
  16277. + // .resume = ...
  16278. + },
  16279. +};
  16280. +
  16281. +MODULE_AUTHOR ("David Brownell");
  16282. +MODULE_LICENSE ("Dual BSD/GPL");
  16283. +
  16284. +static struct proc_dir_entry *pdir, *pfile;
  16285. +
  16286. +static int isoc_read_data (char *page, char **start,
  16287. + off_t off, int count,
  16288. + int *eof, void *data)
  16289. +{
  16290. + int i;
  16291. + static int c = 0;
  16292. + static int done = 0;
  16293. + static int s = 0;
  16294. +
  16295. +/*
  16296. + printk ("\ncount: %d\n", count);
  16297. + printk ("rbuf_start: %d\n", rbuf_start);
  16298. + printk ("rbuf_len: %d\n", rbuf_len);
  16299. + printk ("off: %d\n", off);
  16300. + printk ("start: %p\n\n", *start);
  16301. +*/
  16302. + if (done) {
  16303. + c = 0;
  16304. + done = 0;
  16305. + *eof = 1;
  16306. + return 0;
  16307. + }
  16308. +
  16309. + if (c == 0) {
  16310. + if (rbuf_len == RBUF_LEN)
  16311. + s = rbuf_start;
  16312. + else s = 0;
  16313. + }
  16314. +
  16315. + for (i=0; i<count && c<rbuf_len; i++, c++) {
  16316. + page[i] = rbuf[(c+s) % RBUF_LEN];
  16317. + }
  16318. + *start = page;
  16319. +
  16320. + if (c >= rbuf_len) {
  16321. + *eof = 1;
  16322. + done = 1;
  16323. + }
  16324. +
  16325. +
  16326. + return i;
  16327. +}
  16328. +
  16329. +static int __init init (void)
  16330. +{
  16331. +
  16332. + int retval = 0;
  16333. +
  16334. + pdir = proc_mkdir("isoc_test", NULL);
  16335. + if(pdir == NULL) {
  16336. + retval = -ENOMEM;
  16337. + printk("Error creating dir\n");
  16338. + goto done;
  16339. + }
  16340. + pdir->owner = THIS_MODULE;
  16341. +
  16342. + pfile = create_proc_read_entry("isoc_data",
  16343. + 0444, pdir,
  16344. + isoc_read_data,
  16345. + NULL);
  16346. + if (pfile == NULL) {
  16347. + retval = -ENOMEM;
  16348. + printk("Error creating file\n");
  16349. + goto no_file;
  16350. + }
  16351. + pfile->owner = THIS_MODULE;
  16352. +
  16353. + return usb_gadget_register_driver (&zero_driver);
  16354. +
  16355. + no_file:
  16356. + remove_proc_entry("isoc_data", NULL);
  16357. + done:
  16358. + return retval;
  16359. +}
  16360. +module_init (init);
  16361. +
  16362. +static void __exit cleanup (void)
  16363. +{
  16364. +
  16365. + usb_gadget_unregister_driver (&zero_driver);
  16366. +
  16367. + remove_proc_entry("isoc_data", pdir);
  16368. + remove_proc_entry("isoc_test", NULL);
  16369. +}
  16370. +module_exit (cleanup);
  16371. --- /dev/null
  16372. +++ b/drivers/usb/host/dwc_otg/dwc_cfi_common.h
  16373. @@ -0,0 +1,142 @@
  16374. +/* ==========================================================================
  16375. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  16376. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  16377. + * otherwise expressly agreed to in writing between Synopsys and you.
  16378. + *
  16379. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  16380. + * any End User Software License Agreement or Agreement for Licensed Product
  16381. + * with Synopsys or any supplement thereto. You are permitted to use and
  16382. + * redistribute this Software in source and binary forms, with or without
  16383. + * modification, provided that redistributions of source code must retain this
  16384. + * notice. You may not view, use, disclose, copy or distribute this file or
  16385. + * any information contained herein except pursuant to this license grant from
  16386. + * Synopsys. If you do not agree with this notice, including the disclaimer
  16387. + * below, then you are not authorized to use the Software.
  16388. + *
  16389. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  16390. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16391. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16392. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  16393. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  16394. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  16395. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  16396. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  16397. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  16398. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  16399. + * DAMAGE.
  16400. + * ========================================================================== */
  16401. +
  16402. +#if !defined(__DWC_CFI_COMMON_H__)
  16403. +#define __DWC_CFI_COMMON_H__
  16404. +
  16405. +//#include <linux/types.h>
  16406. +
  16407. +/**
  16408. + * @file
  16409. + *
  16410. + * This file contains the CFI specific common constants, interfaces
  16411. + * (functions and macros) and structures for Linux. No PCD specific
  16412. + * data structure or definition is to be included in this file.
  16413. + *
  16414. + */
  16415. +
  16416. +/** This is a request for all Core Features */
  16417. +#define VEN_CORE_GET_FEATURES 0xB1
  16418. +
  16419. +/** This is a request to get the value of a specific Core Feature */
  16420. +#define VEN_CORE_GET_FEATURE 0xB2
  16421. +
  16422. +/** This command allows the host to set the value of a specific Core Feature */
  16423. +#define VEN_CORE_SET_FEATURE 0xB3
  16424. +
  16425. +/** This command allows the host to set the default values of
  16426. + * either all or any specific Core Feature
  16427. + */
  16428. +#define VEN_CORE_RESET_FEATURES 0xB4
  16429. +
  16430. +/** This command forces the PCD to write the deferred values of a Core Features */
  16431. +#define VEN_CORE_ACTIVATE_FEATURES 0xB5
  16432. +
  16433. +/** This request reads a DWORD value from a register at the specified offset */
  16434. +#define VEN_CORE_READ_REGISTER 0xB6
  16435. +
  16436. +/** This request writes a DWORD value into a register at the specified offset */
  16437. +#define VEN_CORE_WRITE_REGISTER 0xB7
  16438. +
  16439. +/** This structure is the header of the Core Features dataset returned to
  16440. + * the Host
  16441. + */
  16442. +struct cfi_all_features_header {
  16443. +/** The features header structure length is */
  16444. +#define CFI_ALL_FEATURES_HDR_LEN 8
  16445. + /**
  16446. + * The total length of the features dataset returned to the Host
  16447. + */
  16448. + uint16_t wTotalLen;
  16449. +
  16450. + /**
  16451. + * CFI version number inBinary-Coded Decimal (i.e., 1.00 is 100H).
  16452. + * This field identifies the version of the CFI Specification with which
  16453. + * the device is compliant.
  16454. + */
  16455. + uint16_t wVersion;
  16456. +
  16457. + /** The ID of the Core */
  16458. + uint16_t wCoreID;
  16459. +#define CFI_CORE_ID_UDC 1
  16460. +#define CFI_CORE_ID_OTG 2
  16461. +#define CFI_CORE_ID_WUDEV 3
  16462. +
  16463. + /** Number of features returned by VEN_CORE_GET_FEATURES request */
  16464. + uint16_t wNumFeatures;
  16465. +} UPACKED;
  16466. +
  16467. +typedef struct cfi_all_features_header cfi_all_features_header_t;
  16468. +
  16469. +/** This structure is a header of the Core Feature descriptor dataset returned to
  16470. + * the Host after the VEN_CORE_GET_FEATURES request
  16471. + */
  16472. +struct cfi_feature_desc_header {
  16473. +#define CFI_FEATURE_DESC_HDR_LEN 8
  16474. +
  16475. + /** The feature ID */
  16476. + uint16_t wFeatureID;
  16477. +
  16478. + /** Length of this feature descriptor in bytes - including the
  16479. + * length of the feature name string
  16480. + */
  16481. + uint16_t wLength;
  16482. +
  16483. + /** The data length of this feature in bytes */
  16484. + uint16_t wDataLength;
  16485. +
  16486. + /**
  16487. + * Attributes of this features
  16488. + * D0: Access rights
  16489. + * 0 - Read/Write
  16490. + * 1 - Read only
  16491. + */
  16492. + uint8_t bmAttributes;
  16493. +#define CFI_FEATURE_ATTR_RO 1
  16494. +#define CFI_FEATURE_ATTR_RW 0
  16495. +
  16496. + /** Length of the feature name in bytes */
  16497. + uint8_t bNameLen;
  16498. +
  16499. + /** The feature name buffer */
  16500. + //uint8_t *name;
  16501. +} UPACKED;
  16502. +
  16503. +typedef struct cfi_feature_desc_header cfi_feature_desc_header_t;
  16504. +
  16505. +/**
  16506. + * This structure describes a NULL terminated string referenced by its id field.
  16507. + * It is very similar to usb_string structure but has the id field type set to 16-bit.
  16508. + */
  16509. +struct cfi_string {
  16510. + uint16_t id;
  16511. + const uint8_t *s;
  16512. +};
  16513. +typedef struct cfi_string cfi_string_t;
  16514. +
  16515. +#endif
  16516. --- /dev/null
  16517. +++ b/drivers/usb/host/dwc_otg/dwc_otg_adp.c
  16518. @@ -0,0 +1,854 @@
  16519. +/* ==========================================================================
  16520. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $
  16521. + * $Revision: #12 $
  16522. + * $Date: 2011/10/26 $
  16523. + * $Change: 1873028 $
  16524. + *
  16525. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  16526. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  16527. + * otherwise expressly agreed to in writing between Synopsys and you.
  16528. + *
  16529. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  16530. + * any End User Software License Agreement or Agreement for Licensed Product
  16531. + * with Synopsys or any supplement thereto. You are permitted to use and
  16532. + * redistribute this Software in source and binary forms, with or without
  16533. + * modification, provided that redistributions of source code must retain this
  16534. + * notice. You may not view, use, disclose, copy or distribute this file or
  16535. + * any information contained herein except pursuant to this license grant from
  16536. + * Synopsys. If you do not agree with this notice, including the disclaimer
  16537. + * below, then you are not authorized to use the Software.
  16538. + *
  16539. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  16540. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16541. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16542. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  16543. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  16544. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  16545. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  16546. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  16547. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  16548. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  16549. + * DAMAGE.
  16550. + * ========================================================================== */
  16551. +
  16552. +#include "dwc_os.h"
  16553. +#include "dwc_otg_regs.h"
  16554. +#include "dwc_otg_cil.h"
  16555. +#include "dwc_otg_adp.h"
  16556. +
  16557. +/** @file
  16558. + *
  16559. + * This file contains the most of the Attach Detect Protocol implementation for
  16560. + * the driver to support OTG Rev2.0.
  16561. + *
  16562. + */
  16563. +
  16564. +void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value)
  16565. +{
  16566. + adpctl_data_t adpctl;
  16567. +
  16568. + adpctl.d32 = value;
  16569. + adpctl.b.ar = 0x2;
  16570. +
  16571. + DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
  16572. +
  16573. + while (adpctl.b.ar) {
  16574. + adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
  16575. + }
  16576. +
  16577. +}
  16578. +
  16579. +/**
  16580. + * Function is called to read ADP registers
  16581. + */
  16582. +uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if)
  16583. +{
  16584. + adpctl_data_t adpctl;
  16585. +
  16586. + adpctl.d32 = 0;
  16587. + adpctl.b.ar = 0x1;
  16588. +
  16589. + DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32);
  16590. +
  16591. + while (adpctl.b.ar) {
  16592. + adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl);
  16593. + }
  16594. +
  16595. + return adpctl.d32;
  16596. +}
  16597. +
  16598. +/**
  16599. + * Function is called to read ADPCTL register and filter Write-clear bits
  16600. + */
  16601. +uint32_t dwc_otg_adp_read_reg_filter(dwc_otg_core_if_t * core_if)
  16602. +{
  16603. + adpctl_data_t adpctl;
  16604. +
  16605. + adpctl.d32 = dwc_otg_adp_read_reg(core_if);
  16606. + adpctl.b.adp_tmout_int = 0;
  16607. + adpctl.b.adp_prb_int = 0;
  16608. + adpctl.b.adp_tmout_int = 0;
  16609. +
  16610. + return adpctl.d32;
  16611. +}
  16612. +
  16613. +/**
  16614. + * Function is called to write ADP registers
  16615. + */
  16616. +void dwc_otg_adp_modify_reg(dwc_otg_core_if_t * core_if, uint32_t clr,
  16617. + uint32_t set)
  16618. +{
  16619. + dwc_otg_adp_write_reg(core_if,
  16620. + (dwc_otg_adp_read_reg(core_if) & (~clr)) | set);
  16621. +}
  16622. +
  16623. +static void adp_sense_timeout(void *ptr)
  16624. +{
  16625. + dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
  16626. + core_if->adp.sense_timer_started = 0;
  16627. + DWC_PRINTF("ADP SENSE TIMEOUT\n");
  16628. + if (core_if->adp_enable) {
  16629. + dwc_otg_adp_sense_stop(core_if);
  16630. + dwc_otg_adp_probe_start(core_if);
  16631. + }
  16632. +}
  16633. +
  16634. +/**
  16635. + * This function is called when the ADP vbus timer expires. Timeout is 1.1s.
  16636. + */
  16637. +static void adp_vbuson_timeout(void *ptr)
  16638. +{
  16639. + gpwrdn_data_t gpwrdn;
  16640. + dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
  16641. + hprt0_data_t hprt0 = {.d32 = 0 };
  16642. + pcgcctl_data_t pcgcctl = {.d32 = 0 };
  16643. + DWC_PRINTF("%s: 1.1 seconds expire after turning on VBUS\n",__FUNCTION__);
  16644. + if (core_if) {
  16645. + core_if->adp.vbuson_timer_started = 0;
  16646. + /* Turn off vbus */
  16647. + hprt0.b.prtpwr = 1;
  16648. + DWC_MODIFY_REG32(core_if->host_if->hprt0, hprt0.d32, 0);
  16649. + gpwrdn.d32 = 0;
  16650. +
  16651. + /* Power off the core */
  16652. + if (core_if->power_down == 2) {
  16653. + /* Enable Wakeup Logic */
  16654. +// gpwrdn.b.wkupactiv = 1;
  16655. + gpwrdn.b.pmuactv = 0;
  16656. + gpwrdn.b.pwrdnrstn = 1;
  16657. + gpwrdn.b.pwrdnclmp = 1;
  16658. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
  16659. + gpwrdn.d32);
  16660. +
  16661. + /* Suspend the Phy Clock */
  16662. + pcgcctl.b.stoppclk = 1;
  16663. + DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
  16664. +
  16665. + /* Switch on VDD */
  16666. +// gpwrdn.b.wkupactiv = 1;
  16667. + gpwrdn.b.pmuactv = 1;
  16668. + gpwrdn.b.pwrdnrstn = 1;
  16669. + gpwrdn.b.pwrdnclmp = 1;
  16670. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
  16671. + gpwrdn.d32);
  16672. + } else {
  16673. + /* Enable Power Down Logic */
  16674. + gpwrdn.b.pmuintsel = 1;
  16675. + gpwrdn.b.pmuactv = 1;
  16676. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
  16677. + }
  16678. +
  16679. + /* Power off the core */
  16680. + if (core_if->power_down == 2) {
  16681. + gpwrdn.d32 = 0;
  16682. + gpwrdn.b.pwrdnswtch = 1;
  16683. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn,
  16684. + gpwrdn.d32, 0);
  16685. + }
  16686. +
  16687. + /* Unmask SRP detected interrupt from Power Down Logic */
  16688. + gpwrdn.d32 = 0;
  16689. + gpwrdn.b.srp_det_msk = 1;
  16690. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
  16691. +
  16692. + dwc_otg_adp_probe_start(core_if);
  16693. + dwc_otg_dump_global_registers(core_if);
  16694. + dwc_otg_dump_host_registers(core_if);
  16695. + }
  16696. +
  16697. +}
  16698. +
  16699. +/**
  16700. + * Start the ADP Initial Probe timer to detect if Port Connected interrupt is
  16701. + * not asserted within 1.1 seconds.
  16702. + *
  16703. + * @param core_if the pointer to core_if strucure.
  16704. + */
  16705. +void dwc_otg_adp_vbuson_timer_start(dwc_otg_core_if_t * core_if)
  16706. +{
  16707. + core_if->adp.vbuson_timer_started = 1;
  16708. + if (core_if->adp.vbuson_timer)
  16709. + {
  16710. + DWC_PRINTF("SCHEDULING VBUSON TIMER\n");
  16711. + /* 1.1 secs + 60ms necessary for cil_hcd_start*/
  16712. + DWC_TIMER_SCHEDULE(core_if->adp.vbuson_timer, 1160);
  16713. + } else {
  16714. + DWC_WARN("VBUSON_TIMER = %p\n",core_if->adp.vbuson_timer);
  16715. + }
  16716. +}
  16717. +
  16718. +#if 0
  16719. +/**
  16720. + * Masks all DWC OTG core interrupts
  16721. + *
  16722. + */
  16723. +static void mask_all_interrupts(dwc_otg_core_if_t * core_if)
  16724. +{
  16725. + int i;
  16726. + gahbcfg_data_t ahbcfg = {.d32 = 0 };
  16727. +
  16728. + /* Mask Host Interrupts */
  16729. +
  16730. + /* Clear and disable HCINTs */
  16731. + for (i = 0; i < core_if->core_params->host_channels; i++) {
  16732. + DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, 0);
  16733. + DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcint, 0xFFFFFFFF);
  16734. +
  16735. + }
  16736. +
  16737. + /* Clear and disable HAINT */
  16738. + DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, 0x0000);
  16739. + DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haint, 0xFFFFFFFF);
  16740. +
  16741. + /* Mask Device Interrupts */
  16742. + if (!core_if->multiproc_int_enable) {
  16743. + /* Clear and disable IN Endpoint interrupts */
  16744. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, 0);
  16745. + for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
  16746. + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->
  16747. + diepint, 0xFFFFFFFF);
  16748. + }
  16749. +
  16750. + /* Clear and disable OUT Endpoint interrupts */
  16751. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, 0);
  16752. + for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
  16753. + DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->
  16754. + doepint, 0xFFFFFFFF);
  16755. + }
  16756. +
  16757. + /* Clear and disable DAINT */
  16758. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daint,
  16759. + 0xFFFFFFFF);
  16760. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, 0);
  16761. + } else {
  16762. + for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
  16763. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
  16764. + diepeachintmsk[i], 0);
  16765. + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->
  16766. + diepint, 0xFFFFFFFF);
  16767. + }
  16768. +
  16769. + for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
  16770. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
  16771. + doepeachintmsk[i], 0);
  16772. + DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->
  16773. + doepint, 0xFFFFFFFF);
  16774. + }
  16775. +
  16776. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,
  16777. + 0);
  16778. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachint,
  16779. + 0xFFFFFFFF);
  16780. +
  16781. + }
  16782. +
  16783. + /* Disable interrupts */
  16784. + ahbcfg.b.glblintrmsk = 1;
  16785. + DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
  16786. +
  16787. + /* Disable all interrupts. */
  16788. + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);
  16789. +
  16790. + /* Clear any pending interrupts */
  16791. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
  16792. +
  16793. + /* Clear any pending OTG Interrupts */
  16794. + DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, 0xFFFFFFFF);
  16795. +}
  16796. +
  16797. +/**
  16798. + * Unmask Port Connection Detected interrupt
  16799. + *
  16800. + */
  16801. +static void unmask_conn_det_intr(dwc_otg_core_if_t * core_if)
  16802. +{
  16803. + gintmsk_data_t gintmsk = {.d32 = 0,.b.portintr = 1 };
  16804. +
  16805. + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
  16806. +}
  16807. +#endif
  16808. +
  16809. +/**
  16810. + * Starts the ADP Probing
  16811. + *
  16812. + * @param core_if the pointer to core_if structure.
  16813. + */
  16814. +uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if)
  16815. +{
  16816. +
  16817. + adpctl_data_t adpctl = {.d32 = 0};
  16818. + gpwrdn_data_t gpwrdn;
  16819. +#if 0
  16820. + adpctl_data_t adpctl_int = {.d32 = 0, .b.adp_prb_int = 1,
  16821. + .b.adp_sns_int = 1, b.adp_tmout_int};
  16822. +#endif
  16823. + dwc_otg_disable_global_interrupts(core_if);
  16824. + DWC_PRINTF("ADP Probe Start\n");
  16825. + core_if->adp.probe_enabled = 1;
  16826. +
  16827. + adpctl.b.adpres = 1;
  16828. + dwc_otg_adp_write_reg(core_if, adpctl.d32);
  16829. +
  16830. + while (adpctl.b.adpres) {
  16831. + adpctl.d32 = dwc_otg_adp_read_reg(core_if);
  16832. + }
  16833. +
  16834. + adpctl.d32 = 0;
  16835. + gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
  16836. +
  16837. + /* In Host mode unmask SRP detected interrupt */
  16838. + gpwrdn.d32 = 0;
  16839. + gpwrdn.b.sts_chngint_msk = 1;
  16840. + if (!gpwrdn.b.idsts) {
  16841. + gpwrdn.b.srp_det_msk = 1;
  16842. + }
  16843. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
  16844. +
  16845. + adpctl.b.adp_tmout_int_msk = 1;
  16846. + adpctl.b.adp_prb_int_msk = 1;
  16847. + adpctl.b.prb_dschg = 1;
  16848. + adpctl.b.prb_delta = 1;
  16849. + adpctl.b.prb_per = 1;
  16850. + adpctl.b.adpen = 1;
  16851. + adpctl.b.enaprb = 1;
  16852. +
  16853. + dwc_otg_adp_write_reg(core_if, adpctl.d32);
  16854. + DWC_PRINTF("ADP Probe Finish\n");
  16855. + return 0;
  16856. +}
  16857. +
  16858. +/**
  16859. + * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted
  16860. + * within 3 seconds.
  16861. + *
  16862. + * @param core_if the pointer to core_if strucure.
  16863. + */
  16864. +void dwc_otg_adp_sense_timer_start(dwc_otg_core_if_t * core_if)
  16865. +{
  16866. + core_if->adp.sense_timer_started = 1;
  16867. + DWC_TIMER_SCHEDULE(core_if->adp.sense_timer, 3000 /* 3 secs */ );
  16868. +}
  16869. +
  16870. +/**
  16871. + * Starts the ADP Sense
  16872. + *
  16873. + * @param core_if the pointer to core_if strucure.
  16874. + */
  16875. +uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if)
  16876. +{
  16877. + adpctl_data_t adpctl;
  16878. +
  16879. + DWC_PRINTF("ADP Sense Start\n");
  16880. +
  16881. + /* Unmask ADP sense interrupt and mask all other from the core */
  16882. + adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
  16883. + adpctl.b.adp_sns_int_msk = 1;
  16884. + dwc_otg_adp_write_reg(core_if, adpctl.d32);
  16885. + dwc_otg_disable_global_interrupts(core_if); // vahrama
  16886. +
  16887. + /* Set ADP reset bit*/
  16888. + adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
  16889. + adpctl.b.adpres = 1;
  16890. + dwc_otg_adp_write_reg(core_if, adpctl.d32);
  16891. +
  16892. + while (adpctl.b.adpres) {
  16893. + adpctl.d32 = dwc_otg_adp_read_reg(core_if);
  16894. + }
  16895. +
  16896. + adpctl.b.adpres = 0;
  16897. + adpctl.b.adpen = 1;
  16898. + adpctl.b.enasns = 1;
  16899. + dwc_otg_adp_write_reg(core_if, adpctl.d32);
  16900. +
  16901. + dwc_otg_adp_sense_timer_start(core_if);
  16902. +
  16903. + return 0;
  16904. +}
  16905. +
  16906. +/**
  16907. + * Stops the ADP Probing
  16908. + *
  16909. + * @param core_if the pointer to core_if strucure.
  16910. + */
  16911. +uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if)
  16912. +{
  16913. +
  16914. + adpctl_data_t adpctl;
  16915. + DWC_PRINTF("Stop ADP probe\n");
  16916. + core_if->adp.probe_enabled = 0;
  16917. + core_if->adp.probe_counter = 0;
  16918. + adpctl.d32 = dwc_otg_adp_read_reg(core_if);
  16919. +
  16920. + adpctl.b.adpen = 0;
  16921. + adpctl.b.adp_prb_int = 1;
  16922. + adpctl.b.adp_tmout_int = 1;
  16923. + adpctl.b.adp_sns_int = 1;
  16924. + dwc_otg_adp_write_reg(core_if, adpctl.d32);
  16925. +
  16926. + return 0;
  16927. +}
  16928. +
  16929. +/**
  16930. + * Stops the ADP Sensing
  16931. + *
  16932. + * @param core_if the pointer to core_if strucure.
  16933. + */
  16934. +uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if)
  16935. +{
  16936. + adpctl_data_t adpctl;
  16937. +
  16938. + core_if->adp.sense_enabled = 0;
  16939. +
  16940. + adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if);
  16941. + adpctl.b.enasns = 0;
  16942. + adpctl.b.adp_sns_int = 1;
  16943. + dwc_otg_adp_write_reg(core_if, adpctl.d32);
  16944. +
  16945. + return 0;
  16946. +}
  16947. +
  16948. +/**
  16949. + * Called to turn on the VBUS after initial ADP probe in host mode.
  16950. + * If port power was already enabled in cil_hcd_start function then
  16951. + * only schedule a timer.
  16952. + *
  16953. + * @param core_if the pointer to core_if structure.
  16954. + */
  16955. +void dwc_otg_adp_turnon_vbus(dwc_otg_core_if_t * core_if)
  16956. +{
  16957. + hprt0_data_t hprt0 = {.d32 = 0 };
  16958. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  16959. + DWC_PRINTF("Turn on VBUS for 1.1s, port power is %d\n", hprt0.b.prtpwr);
  16960. +
  16961. + if (hprt0.b.prtpwr == 0) {
  16962. + hprt0.b.prtpwr = 1;
  16963. + //DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  16964. + }
  16965. +
  16966. + dwc_otg_adp_vbuson_timer_start(core_if);
  16967. +}
  16968. +
  16969. +/**
  16970. + * Called right after driver is loaded
  16971. + * to perform initial actions for ADP
  16972. + *
  16973. + * @param core_if the pointer to core_if structure.
  16974. + * @param is_host - flag for current mode of operation either from GINTSTS or GPWRDN
  16975. + */
  16976. +void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host)
  16977. +{
  16978. + gpwrdn_data_t gpwrdn;
  16979. +
  16980. + DWC_PRINTF("ADP Initial Start\n");
  16981. + core_if->adp.adp_started = 1;
  16982. +
  16983. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
  16984. + dwc_otg_disable_global_interrupts(core_if);
  16985. + if (is_host) {
  16986. + DWC_PRINTF("HOST MODE\n");
  16987. + /* Enable Power Down Logic Interrupt*/
  16988. + gpwrdn.d32 = 0;
  16989. + gpwrdn.b.pmuintsel = 1;
  16990. + gpwrdn.b.pmuactv = 1;
  16991. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
  16992. + /* Initialize first ADP probe to obtain Ramp Time value */
  16993. + core_if->adp.initial_probe = 1;
  16994. + dwc_otg_adp_probe_start(core_if);
  16995. + } else {
  16996. + gotgctl_data_t gotgctl;
  16997. + gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
  16998. + DWC_PRINTF("DEVICE MODE\n");
  16999. + if (gotgctl.b.bsesvld == 0) {
  17000. + /* Enable Power Down Logic Interrupt*/
  17001. + gpwrdn.d32 = 0;
  17002. + DWC_PRINTF("VBUS is not valid - start ADP probe\n");
  17003. + gpwrdn.b.pmuintsel = 1;
  17004. + gpwrdn.b.pmuactv = 1;
  17005. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
  17006. + core_if->adp.initial_probe = 1;
  17007. + dwc_otg_adp_probe_start(core_if);
  17008. + } else {
  17009. + DWC_PRINTF("VBUS is valid - initialize core as a Device\n");
  17010. + core_if->op_state = B_PERIPHERAL;
  17011. + dwc_otg_core_init(core_if);
  17012. + dwc_otg_enable_global_interrupts(core_if);
  17013. + cil_pcd_start(core_if);
  17014. + dwc_otg_dump_global_registers(core_if);
  17015. + dwc_otg_dump_dev_registers(core_if);
  17016. + }
  17017. + }
  17018. +}
  17019. +
  17020. +void dwc_otg_adp_init(dwc_otg_core_if_t * core_if)
  17021. +{
  17022. + core_if->adp.adp_started = 0;
  17023. + core_if->adp.initial_probe = 0;
  17024. + core_if->adp.probe_timer_values[0] = -1;
  17025. + core_if->adp.probe_timer_values[1] = -1;
  17026. + core_if->adp.probe_enabled = 0;
  17027. + core_if->adp.sense_enabled = 0;
  17028. + core_if->adp.sense_timer_started = 0;
  17029. + core_if->adp.vbuson_timer_started = 0;
  17030. + core_if->adp.probe_counter = 0;
  17031. + core_if->adp.gpwrdn = 0;
  17032. + core_if->adp.attached = DWC_OTG_ADP_UNKOWN;
  17033. + /* Initialize timers */
  17034. + core_if->adp.sense_timer =
  17035. + DWC_TIMER_ALLOC("ADP SENSE TIMER", adp_sense_timeout, core_if);
  17036. + core_if->adp.vbuson_timer =
  17037. + DWC_TIMER_ALLOC("ADP VBUS ON TIMER", adp_vbuson_timeout, core_if);
  17038. + if (!core_if->adp.sense_timer || !core_if->adp.vbuson_timer)
  17039. + {
  17040. + DWC_ERROR("Could not allocate memory for ADP timers\n");
  17041. + }
  17042. +}
  17043. +
  17044. +void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if)
  17045. +{
  17046. + gpwrdn_data_t gpwrdn = { .d32 = 0 };
  17047. + gpwrdn.b.pmuintsel = 1;
  17048. + gpwrdn.b.pmuactv = 1;
  17049. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  17050. +
  17051. + if (core_if->adp.probe_enabled)
  17052. + dwc_otg_adp_probe_stop(core_if);
  17053. + if (core_if->adp.sense_enabled)
  17054. + dwc_otg_adp_sense_stop(core_if);
  17055. + if (core_if->adp.sense_timer_started)
  17056. + DWC_TIMER_CANCEL(core_if->adp.sense_timer);
  17057. + if (core_if->adp.vbuson_timer_started)
  17058. + DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
  17059. + DWC_TIMER_FREE(core_if->adp.sense_timer);
  17060. + DWC_TIMER_FREE(core_if->adp.vbuson_timer);
  17061. +}
  17062. +
  17063. +/////////////////////////////////////////////////////////////////////
  17064. +////////////// ADP Interrupt Handlers ///////////////////////////////
  17065. +/////////////////////////////////////////////////////////////////////
  17066. +/**
  17067. + * This function sets Ramp Timer values
  17068. + */
  17069. +static uint32_t set_timer_value(dwc_otg_core_if_t * core_if, uint32_t val)
  17070. +{
  17071. + if (core_if->adp.probe_timer_values[0] == -1) {
  17072. + core_if->adp.probe_timer_values[0] = val;
  17073. + core_if->adp.probe_timer_values[1] = -1;
  17074. + return 1;
  17075. + } else {
  17076. + core_if->adp.probe_timer_values[1] =
  17077. + core_if->adp.probe_timer_values[0];
  17078. + core_if->adp.probe_timer_values[0] = val;
  17079. + return 0;
  17080. + }
  17081. +}
  17082. +
  17083. +/**
  17084. + * This function compares Ramp Timer values
  17085. + */
  17086. +static uint32_t compare_timer_values(dwc_otg_core_if_t * core_if)
  17087. +{
  17088. + uint32_t diff;
  17089. + if (core_if->adp.probe_timer_values[0]>=core_if->adp.probe_timer_values[1])
  17090. + diff = core_if->adp.probe_timer_values[0]-core_if->adp.probe_timer_values[1];
  17091. + else
  17092. + diff = core_if->adp.probe_timer_values[1]-core_if->adp.probe_timer_values[0];
  17093. + if(diff < 2) {
  17094. + return 0;
  17095. + } else {
  17096. + return 1;
  17097. + }
  17098. +}
  17099. +
  17100. +/**
  17101. + * This function handles ADP Probe Interrupts
  17102. + */
  17103. +static int32_t dwc_otg_adp_handle_prb_intr(dwc_otg_core_if_t * core_if,
  17104. + uint32_t val)
  17105. +{
  17106. + adpctl_data_t adpctl = {.d32 = 0 };
  17107. + gpwrdn_data_t gpwrdn, temp;
  17108. + adpctl.d32 = val;
  17109. +
  17110. + temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
  17111. + core_if->adp.probe_counter++;
  17112. + core_if->adp.gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
  17113. + if (adpctl.b.rtim == 0 && !temp.b.idsts){
  17114. + DWC_PRINTF("RTIM value is 0\n");
  17115. + goto exit;
  17116. + }
  17117. + if (set_timer_value(core_if, adpctl.b.rtim) &&
  17118. + core_if->adp.initial_probe) {
  17119. + core_if->adp.initial_probe = 0;
  17120. + dwc_otg_adp_probe_stop(core_if);
  17121. + gpwrdn.d32 = 0;
  17122. + gpwrdn.b.pmuactv = 1;
  17123. + gpwrdn.b.pmuintsel = 1;
  17124. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  17125. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
  17126. +
  17127. + /* check which value is for device mode and which for Host mode */
  17128. + if (!temp.b.idsts) { /* considered host mode value is 0 */
  17129. + /*
  17130. + * Turn on VBUS after initial ADP probe.
  17131. + */
  17132. + core_if->op_state = A_HOST;
  17133. + dwc_otg_enable_global_interrupts(core_if);
  17134. + DWC_SPINUNLOCK(core_if->lock);
  17135. + cil_hcd_start(core_if);
  17136. + dwc_otg_adp_turnon_vbus(core_if);
  17137. + DWC_SPINLOCK(core_if->lock);
  17138. + } else {
  17139. + /*
  17140. + * Initiate SRP after initial ADP probe.
  17141. + */
  17142. + dwc_otg_enable_global_interrupts(core_if);
  17143. + dwc_otg_initiate_srp(core_if);
  17144. + }
  17145. + } else if (core_if->adp.probe_counter > 2){
  17146. + gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
  17147. + if (compare_timer_values(core_if)) {
  17148. + DWC_PRINTF("Difference in timer values !!! \n");
  17149. +// core_if->adp.attached = DWC_OTG_ADP_ATTACHED;
  17150. + dwc_otg_adp_probe_stop(core_if);
  17151. +
  17152. + /* Power on the core */
  17153. + if (core_if->power_down == 2) {
  17154. + gpwrdn.b.pwrdnswtch = 1;
  17155. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  17156. + gpwrdn, 0, gpwrdn.d32);
  17157. + }
  17158. +
  17159. + /* check which value is for device mode and which for Host mode */
  17160. + if (!temp.b.idsts) { /* considered host mode value is 0 */
  17161. + /* Disable Interrupt from Power Down Logic */
  17162. + gpwrdn.d32 = 0;
  17163. + gpwrdn.b.pmuintsel = 1;
  17164. + gpwrdn.b.pmuactv = 1;
  17165. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  17166. + gpwrdn, gpwrdn.d32, 0);
  17167. +
  17168. + /*
  17169. + * Initialize the Core for Host mode.
  17170. + */
  17171. + core_if->op_state = A_HOST;
  17172. + dwc_otg_core_init(core_if);
  17173. + dwc_otg_enable_global_interrupts(core_if);
  17174. + cil_hcd_start(core_if);
  17175. + } else {
  17176. + gotgctl_data_t gotgctl;
  17177. + /* Mask SRP detected interrupt from Power Down Logic */
  17178. + gpwrdn.d32 = 0;
  17179. + gpwrdn.b.srp_det_msk = 1;
  17180. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  17181. + gpwrdn, gpwrdn.d32, 0);
  17182. +
  17183. + /* Disable Power Down Logic */
  17184. + gpwrdn.d32 = 0;
  17185. + gpwrdn.b.pmuintsel = 1;
  17186. + gpwrdn.b.pmuactv = 1;
  17187. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  17188. + gpwrdn, gpwrdn.d32, 0);
  17189. +
  17190. + /*
  17191. + * Initialize the Core for Device mode.
  17192. + */
  17193. + core_if->op_state = B_PERIPHERAL;
  17194. + dwc_otg_core_init(core_if);
  17195. + dwc_otg_enable_global_interrupts(core_if);
  17196. + cil_pcd_start(core_if);
  17197. +
  17198. + gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
  17199. + if (!gotgctl.b.bsesvld) {
  17200. + dwc_otg_initiate_srp(core_if);
  17201. + }
  17202. + }
  17203. + }
  17204. + if (core_if->power_down == 2) {
  17205. + if (gpwrdn.b.bsessvld) {
  17206. + /* Mask SRP detected interrupt from Power Down Logic */
  17207. + gpwrdn.d32 = 0;
  17208. + gpwrdn.b.srp_det_msk = 1;
  17209. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  17210. +
  17211. + /* Disable Power Down Logic */
  17212. + gpwrdn.d32 = 0;
  17213. + gpwrdn.b.pmuactv = 1;
  17214. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  17215. +
  17216. + /*
  17217. + * Initialize the Core for Device mode.
  17218. + */
  17219. + core_if->op_state = B_PERIPHERAL;
  17220. + dwc_otg_core_init(core_if);
  17221. + dwc_otg_enable_global_interrupts(core_if);
  17222. + cil_pcd_start(core_if);
  17223. + }
  17224. + }
  17225. + }
  17226. +exit:
  17227. + /* Clear interrupt */
  17228. + adpctl.d32 = dwc_otg_adp_read_reg(core_if);
  17229. + adpctl.b.adp_prb_int = 1;
  17230. + dwc_otg_adp_write_reg(core_if, adpctl.d32);
  17231. +
  17232. + return 0;
  17233. +}
  17234. +
  17235. +/**
  17236. + * This function hadles ADP Sense Interrupt
  17237. + */
  17238. +static int32_t dwc_otg_adp_handle_sns_intr(dwc_otg_core_if_t * core_if)
  17239. +{
  17240. + adpctl_data_t adpctl;
  17241. + /* Stop ADP Sense timer */
  17242. + DWC_TIMER_CANCEL(core_if->adp.sense_timer);
  17243. +
  17244. + /* Restart ADP Sense timer */
  17245. + dwc_otg_adp_sense_timer_start(core_if);
  17246. +
  17247. + /* Clear interrupt */
  17248. + adpctl.d32 = dwc_otg_adp_read_reg(core_if);
  17249. + adpctl.b.adp_sns_int = 1;
  17250. + dwc_otg_adp_write_reg(core_if, adpctl.d32);
  17251. +
  17252. + return 0;
  17253. +}
  17254. +
  17255. +/**
  17256. + * This function handles ADP Probe Interrupts
  17257. + */
  17258. +static int32_t dwc_otg_adp_handle_prb_tmout_intr(dwc_otg_core_if_t * core_if,
  17259. + uint32_t val)
  17260. +{
  17261. + adpctl_data_t adpctl = {.d32 = 0 };
  17262. + adpctl.d32 = val;
  17263. + set_timer_value(core_if, adpctl.b.rtim);
  17264. +
  17265. + /* Clear interrupt */
  17266. + adpctl.d32 = dwc_otg_adp_read_reg(core_if);
  17267. + adpctl.b.adp_tmout_int = 1;
  17268. + dwc_otg_adp_write_reg(core_if, adpctl.d32);
  17269. +
  17270. + return 0;
  17271. +}
  17272. +
  17273. +/**
  17274. + * ADP Interrupt handler.
  17275. + *
  17276. + */
  17277. +int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if)
  17278. +{
  17279. + int retval = 0;
  17280. + adpctl_data_t adpctl = {.d32 = 0};
  17281. +
  17282. + adpctl.d32 = dwc_otg_adp_read_reg(core_if);
  17283. + DWC_PRINTF("ADPCTL = %08x\n",adpctl.d32);
  17284. +
  17285. + if (adpctl.b.adp_sns_int & adpctl.b.adp_sns_int_msk) {
  17286. + DWC_PRINTF("ADP Sense interrupt\n");
  17287. + retval |= dwc_otg_adp_handle_sns_intr(core_if);
  17288. + }
  17289. + if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) {
  17290. + DWC_PRINTF("ADP timeout interrupt\n");
  17291. + retval |= dwc_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32);
  17292. + }
  17293. + if (adpctl.b.adp_prb_int & adpctl.b.adp_prb_int_msk) {
  17294. + DWC_PRINTF("ADP Probe interrupt\n");
  17295. + adpctl.b.adp_prb_int = 1;
  17296. + retval |= dwc_otg_adp_handle_prb_intr(core_if, adpctl.d32);
  17297. + }
  17298. +
  17299. +// dwc_otg_adp_modify_reg(core_if, adpctl.d32, 0);
  17300. + //dwc_otg_adp_write_reg(core_if, adpctl.d32);
  17301. + DWC_PRINTF("RETURN FROM ADP ISR\n");
  17302. +
  17303. + return retval;
  17304. +}
  17305. +
  17306. +/**
  17307. + *
  17308. + * @param core_if Programming view of DWC_otg controller.
  17309. + */
  17310. +int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if)
  17311. +{
  17312. +
  17313. +#ifndef DWC_HOST_ONLY
  17314. + hprt0_data_t hprt0;
  17315. + gpwrdn_data_t gpwrdn;
  17316. + DWC_DEBUGPL(DBG_ANY, "++ Power Down Logic Session Request Interrupt++\n");
  17317. +
  17318. + gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
  17319. + /* check which value is for device mode and which for Host mode */
  17320. + if (!gpwrdn.b.idsts) { /* considered host mode value is 0 */
  17321. + DWC_PRINTF("SRP: Host mode\n");
  17322. +
  17323. + if (core_if->adp_enable) {
  17324. + dwc_otg_adp_probe_stop(core_if);
  17325. +
  17326. + /* Power on the core */
  17327. + if (core_if->power_down == 2) {
  17328. + gpwrdn.b.pwrdnswtch = 1;
  17329. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  17330. + gpwrdn, 0, gpwrdn.d32);
  17331. + }
  17332. +
  17333. + core_if->op_state = A_HOST;
  17334. + dwc_otg_core_init(core_if);
  17335. + dwc_otg_enable_global_interrupts(core_if);
  17336. + cil_hcd_start(core_if);
  17337. + }
  17338. +
  17339. + /* Turn on the port power bit. */
  17340. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  17341. + hprt0.b.prtpwr = 1;
  17342. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  17343. +
  17344. + /* Start the Connection timer. So a message can be displayed
  17345. + * if connect does not occur within 10 seconds. */
  17346. + cil_hcd_session_start(core_if);
  17347. + } else {
  17348. + DWC_PRINTF("SRP: Device mode %s\n", __FUNCTION__);
  17349. + if (core_if->adp_enable) {
  17350. + dwc_otg_adp_probe_stop(core_if);
  17351. +
  17352. + /* Power on the core */
  17353. + if (core_if->power_down == 2) {
  17354. + gpwrdn.b.pwrdnswtch = 1;
  17355. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  17356. + gpwrdn, 0, gpwrdn.d32);
  17357. + }
  17358. +
  17359. + gpwrdn.d32 = 0;
  17360. + gpwrdn.b.pmuactv = 0;
  17361. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
  17362. + gpwrdn.d32);
  17363. +
  17364. + core_if->op_state = B_PERIPHERAL;
  17365. + dwc_otg_core_init(core_if);
  17366. + dwc_otg_enable_global_interrupts(core_if);
  17367. + cil_pcd_start(core_if);
  17368. + }
  17369. + }
  17370. +#endif
  17371. + return 1;
  17372. +}
  17373. --- /dev/null
  17374. +++ b/drivers/usb/host/dwc_otg/dwc_otg_adp.h
  17375. @@ -0,0 +1,80 @@
  17376. +/* ==========================================================================
  17377. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.h $
  17378. + * $Revision: #7 $
  17379. + * $Date: 2011/10/24 $
  17380. + * $Change: 1871159 $
  17381. + *
  17382. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  17383. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  17384. + * otherwise expressly agreed to in writing between Synopsys and you.
  17385. + *
  17386. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  17387. + * any End User Software License Agreement or Agreement for Licensed Product
  17388. + * with Synopsys or any supplement thereto. You are permitted to use and
  17389. + * redistribute this Software in source and binary forms, with or without
  17390. + * modification, provided that redistributions of source code must retain this
  17391. + * notice. You may not view, use, disclose, copy or distribute this file or
  17392. + * any information contained herein except pursuant to this license grant from
  17393. + * Synopsys. If you do not agree with this notice, including the disclaimer
  17394. + * below, then you are not authorized to use the Software.
  17395. + *
  17396. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  17397. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17398. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17399. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  17400. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  17401. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  17402. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  17403. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  17404. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  17405. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  17406. + * DAMAGE.
  17407. + * ========================================================================== */
  17408. +
  17409. +#ifndef __DWC_OTG_ADP_H__
  17410. +#define __DWC_OTG_ADP_H__
  17411. +
  17412. +/**
  17413. + * @file
  17414. + *
  17415. + * This file contains the Attach Detect Protocol interfaces and defines
  17416. + * (functions) and structures for Linux.
  17417. + *
  17418. + */
  17419. +
  17420. +#define DWC_OTG_ADP_UNATTACHED 0
  17421. +#define DWC_OTG_ADP_ATTACHED 1
  17422. +#define DWC_OTG_ADP_UNKOWN 2
  17423. +
  17424. +typedef struct dwc_otg_adp {
  17425. + uint32_t adp_started;
  17426. + uint32_t initial_probe;
  17427. + int32_t probe_timer_values[2];
  17428. + uint32_t probe_enabled;
  17429. + uint32_t sense_enabled;
  17430. + dwc_timer_t *sense_timer;
  17431. + uint32_t sense_timer_started;
  17432. + dwc_timer_t *vbuson_timer;
  17433. + uint32_t vbuson_timer_started;
  17434. + uint32_t attached;
  17435. + uint32_t probe_counter;
  17436. + uint32_t gpwrdn;
  17437. +} dwc_otg_adp_t;
  17438. +
  17439. +/**
  17440. + * Attach Detect Protocol functions
  17441. + */
  17442. +
  17443. +extern void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value);
  17444. +extern uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if);
  17445. +extern uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if);
  17446. +extern uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if);
  17447. +extern uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if);
  17448. +extern uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if);
  17449. +extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host);
  17450. +extern void dwc_otg_adp_init(dwc_otg_core_if_t * core_if);
  17451. +extern void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if);
  17452. +extern int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if);
  17453. +extern int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if);
  17454. +
  17455. +#endif //__DWC_OTG_ADP_H__
  17456. --- /dev/null
  17457. +++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.c
  17458. @@ -0,0 +1,1210 @@
  17459. +/* ==========================================================================
  17460. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.c $
  17461. + * $Revision: #44 $
  17462. + * $Date: 2010/11/29 $
  17463. + * $Change: 1636033 $
  17464. + *
  17465. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  17466. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  17467. + * otherwise expressly agreed to in writing between Synopsys and you.
  17468. + *
  17469. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  17470. + * any End User Software License Agreement or Agreement for Licensed Product
  17471. + * with Synopsys or any supplement thereto. You are permitted to use and
  17472. + * redistribute this Software in source and binary forms, with or without
  17473. + * modification, provided that redistributions of source code must retain this
  17474. + * notice. You may not view, use, disclose, copy or distribute this file or
  17475. + * any information contained herein except pursuant to this license grant from
  17476. + * Synopsys. If you do not agree with this notice, including the disclaimer
  17477. + * below, then you are not authorized to use the Software.
  17478. + *
  17479. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  17480. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17481. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17482. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  17483. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  17484. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  17485. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  17486. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  17487. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  17488. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  17489. + * DAMAGE.
  17490. + * ========================================================================== */
  17491. +
  17492. +/** @file
  17493. + *
  17494. + * The diagnostic interface will provide access to the controller for
  17495. + * bringing up the hardware and testing. The Linux driver attributes
  17496. + * feature will be used to provide the Linux Diagnostic
  17497. + * Interface. These attributes are accessed through sysfs.
  17498. + */
  17499. +
  17500. +/** @page "Linux Module Attributes"
  17501. + *
  17502. + * The Linux module attributes feature is used to provide the Linux
  17503. + * Diagnostic Interface. These attributes are accessed through sysfs.
  17504. + * The diagnostic interface will provide access to the controller for
  17505. + * bringing up the hardware and testing.
  17506. +
  17507. + The following table shows the attributes.
  17508. + <table>
  17509. + <tr>
  17510. + <td><b> Name</b></td>
  17511. + <td><b> Description</b></td>
  17512. + <td><b> Access</b></td>
  17513. + </tr>
  17514. +
  17515. + <tr>
  17516. + <td> mode </td>
  17517. + <td> Returns the current mode: 0 for device mode, 1 for host mode</td>
  17518. + <td> Read</td>
  17519. + </tr>
  17520. +
  17521. + <tr>
  17522. + <td> hnpcapable </td>
  17523. + <td> Gets or sets the "HNP-capable" bit in the Core USB Configuraton Register.
  17524. + Read returns the current value.</td>
  17525. + <td> Read/Write</td>
  17526. + </tr>
  17527. +
  17528. + <tr>
  17529. + <td> srpcapable </td>
  17530. + <td> Gets or sets the "SRP-capable" bit in the Core USB Configuraton Register.
  17531. + Read returns the current value.</td>
  17532. + <td> Read/Write</td>
  17533. + </tr>
  17534. +
  17535. + <tr>
  17536. + <td> hsic_connect </td>
  17537. + <td> Gets or sets the "HSIC-Connect" bit in the GLPMCFG Register.
  17538. + Read returns the current value.</td>
  17539. + <td> Read/Write</td>
  17540. + </tr>
  17541. +
  17542. + <tr>
  17543. + <td> inv_sel_hsic </td>
  17544. + <td> Gets or sets the "Invert Select HSIC" bit in the GLPMFG Register.
  17545. + Read returns the current value.</td>
  17546. + <td> Read/Write</td>
  17547. + </tr>
  17548. +
  17549. + <tr>
  17550. + <td> hnp </td>
  17551. + <td> Initiates the Host Negotiation Protocol. Read returns the status.</td>
  17552. + <td> Read/Write</td>
  17553. + </tr>
  17554. +
  17555. + <tr>
  17556. + <td> srp </td>
  17557. + <td> Initiates the Session Request Protocol. Read returns the status.</td>
  17558. + <td> Read/Write</td>
  17559. + </tr>
  17560. +
  17561. + <tr>
  17562. + <td> buspower </td>
  17563. + <td> Gets or sets the Power State of the bus (0 - Off or 1 - On)</td>
  17564. + <td> Read/Write</td>
  17565. + </tr>
  17566. +
  17567. + <tr>
  17568. + <td> bussuspend </td>
  17569. + <td> Suspends the USB bus.</td>
  17570. + <td> Read/Write</td>
  17571. + </tr>
  17572. +
  17573. + <tr>
  17574. + <td> busconnected </td>
  17575. + <td> Gets the connection status of the bus</td>
  17576. + <td> Read</td>
  17577. + </tr>
  17578. +
  17579. + <tr>
  17580. + <td> gotgctl </td>
  17581. + <td> Gets or sets the Core Control Status Register.</td>
  17582. + <td> Read/Write</td>
  17583. + </tr>
  17584. +
  17585. + <tr>
  17586. + <td> gusbcfg </td>
  17587. + <td> Gets or sets the Core USB Configuration Register</td>
  17588. + <td> Read/Write</td>
  17589. + </tr>
  17590. +
  17591. + <tr>
  17592. + <td> grxfsiz </td>
  17593. + <td> Gets or sets the Receive FIFO Size Register</td>
  17594. + <td> Read/Write</td>
  17595. + </tr>
  17596. +
  17597. + <tr>
  17598. + <td> gnptxfsiz </td>
  17599. + <td> Gets or sets the non-periodic Transmit Size Register</td>
  17600. + <td> Read/Write</td>
  17601. + </tr>
  17602. +
  17603. + <tr>
  17604. + <td> gpvndctl </td>
  17605. + <td> Gets or sets the PHY Vendor Control Register</td>
  17606. + <td> Read/Write</td>
  17607. + </tr>
  17608. +
  17609. + <tr>
  17610. + <td> ggpio </td>
  17611. + <td> Gets the value in the lower 16-bits of the General Purpose IO Register
  17612. + or sets the upper 16 bits.</td>
  17613. + <td> Read/Write</td>
  17614. + </tr>
  17615. +
  17616. + <tr>
  17617. + <td> guid </td>
  17618. + <td> Gets or sets the value of the User ID Register</td>
  17619. + <td> Read/Write</td>
  17620. + </tr>
  17621. +
  17622. + <tr>
  17623. + <td> gsnpsid </td>
  17624. + <td> Gets the value of the Synopsys ID Regester</td>
  17625. + <td> Read</td>
  17626. + </tr>
  17627. +
  17628. + <tr>
  17629. + <td> devspeed </td>
  17630. + <td> Gets or sets the device speed setting in the DCFG register</td>
  17631. + <td> Read/Write</td>
  17632. + </tr>
  17633. +
  17634. + <tr>
  17635. + <td> enumspeed </td>
  17636. + <td> Gets the device enumeration Speed.</td>
  17637. + <td> Read</td>
  17638. + </tr>
  17639. +
  17640. + <tr>
  17641. + <td> hptxfsiz </td>
  17642. + <td> Gets the value of the Host Periodic Transmit FIFO</td>
  17643. + <td> Read</td>
  17644. + </tr>
  17645. +
  17646. + <tr>
  17647. + <td> hprt0 </td>
  17648. + <td> Gets or sets the value in the Host Port Control and Status Register</td>
  17649. + <td> Read/Write</td>
  17650. + </tr>
  17651. +
  17652. + <tr>
  17653. + <td> regoffset </td>
  17654. + <td> Sets the register offset for the next Register Access</td>
  17655. + <td> Read/Write</td>
  17656. + </tr>
  17657. +
  17658. + <tr>
  17659. + <td> regvalue </td>
  17660. + <td> Gets or sets the value of the register at the offset in the regoffset attribute.</td>
  17661. + <td> Read/Write</td>
  17662. + </tr>
  17663. +
  17664. + <tr>
  17665. + <td> remote_wakeup </td>
  17666. + <td> On read, shows the status of Remote Wakeup. On write, initiates a remote
  17667. + wakeup of the host. When bit 0 is 1 and Remote Wakeup is enabled, the Remote
  17668. + Wakeup signalling bit in the Device Control Register is set for 1
  17669. + milli-second.</td>
  17670. + <td> Read/Write</td>
  17671. + </tr>
  17672. +
  17673. + <tr>
  17674. + <td> rem_wakeup_pwrdn </td>
  17675. + <td> On read, shows the status core - hibernated or not. On write, initiates
  17676. + a remote wakeup of the device from Hibernation. </td>
  17677. + <td> Read/Write</td>
  17678. + </tr>
  17679. +
  17680. + <tr>
  17681. + <td> mode_ch_tim_en </td>
  17682. + <td> This bit is used to enable or disable the host core to wait for 200 PHY
  17683. + clock cycles at the end of Resume to change the opmode signal to the PHY to 00
  17684. + after Suspend or LPM. </td>
  17685. + <td> Read/Write</td>
  17686. + </tr>
  17687. +
  17688. + <tr>
  17689. + <td> fr_interval </td>
  17690. + <td> On read, shows the value of HFIR Frame Interval. On write, dynamically
  17691. + reload HFIR register during runtime. The application can write a value to this
  17692. + register only after the Port Enable bit of the Host Port Control and Status
  17693. + register (HPRT.PrtEnaPort) has been set </td>
  17694. + <td> Read/Write</td>
  17695. + </tr>
  17696. +
  17697. + <tr>
  17698. + <td> disconnect_us </td>
  17699. + <td> On read, shows the status of disconnect_device_us. On write, sets disconnect_us
  17700. + which causes soft disconnect for 100us. Applicable only for device mode of operation.</td>
  17701. + <td> Read/Write</td>
  17702. + </tr>
  17703. +
  17704. + <tr>
  17705. + <td> regdump </td>
  17706. + <td> Dumps the contents of core registers.</td>
  17707. + <td> Read</td>
  17708. + </tr>
  17709. +
  17710. + <tr>
  17711. + <td> spramdump </td>
  17712. + <td> Dumps the contents of core registers.</td>
  17713. + <td> Read</td>
  17714. + </tr>
  17715. +
  17716. + <tr>
  17717. + <td> hcddump </td>
  17718. + <td> Dumps the current HCD state.</td>
  17719. + <td> Read</td>
  17720. + </tr>
  17721. +
  17722. + <tr>
  17723. + <td> hcd_frrem </td>
  17724. + <td> Shows the average value of the Frame Remaining
  17725. + field in the Host Frame Number/Frame Remaining register when an SOF interrupt
  17726. + occurs. This can be used to determine the average interrupt latency. Also
  17727. + shows the average Frame Remaining value for start_transfer and the "a" and
  17728. + "b" sample points. The "a" and "b" sample points may be used during debugging
  17729. + bto determine how long it takes to execute a section of the HCD code.</td>
  17730. + <td> Read</td>
  17731. + </tr>
  17732. +
  17733. + <tr>
  17734. + <td> rd_reg_test </td>
  17735. + <td> Displays the time required to read the GNPTXFSIZ register many times
  17736. + (the output shows the number of times the register is read).
  17737. + <td> Read</td>
  17738. + </tr>
  17739. +
  17740. + <tr>
  17741. + <td> wr_reg_test </td>
  17742. + <td> Displays the time required to write the GNPTXFSIZ register many times
  17743. + (the output shows the number of times the register is written).
  17744. + <td> Read</td>
  17745. + </tr>
  17746. +
  17747. + <tr>
  17748. + <td> lpm_response </td>
  17749. + <td> Gets or sets lpm_response mode. Applicable only in device mode.
  17750. + <td> Write</td>
  17751. + </tr>
  17752. +
  17753. + <tr>
  17754. + <td> sleep_status </td>
  17755. + <td> Shows sleep status of device.
  17756. + <td> Read</td>
  17757. + </tr>
  17758. +
  17759. + </table>
  17760. +
  17761. + Example usage:
  17762. + To get the current mode:
  17763. + cat /sys/devices/lm0/mode
  17764. +
  17765. + To power down the USB:
  17766. + echo 0 > /sys/devices/lm0/buspower
  17767. + */
  17768. +
  17769. +#include "dwc_otg_os_dep.h"
  17770. +#include "dwc_os.h"
  17771. +#include "dwc_otg_driver.h"
  17772. +#include "dwc_otg_attr.h"
  17773. +#include "dwc_otg_core_if.h"
  17774. +#include "dwc_otg_pcd_if.h"
  17775. +#include "dwc_otg_hcd_if.h"
  17776. +
  17777. +/*
  17778. + * MACROs for defining sysfs attribute
  17779. + */
  17780. +#ifdef LM_INTERFACE
  17781. +
  17782. +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
  17783. +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
  17784. +{ \
  17785. + struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
  17786. + dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
  17787. + uint32_t val; \
  17788. + val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
  17789. + return sprintf (buf, "%s = 0x%x\n", _string_, val); \
  17790. +}
  17791. +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
  17792. +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
  17793. + const char *buf, size_t count) \
  17794. +{ \
  17795. + struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
  17796. + dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
  17797. + uint32_t set = simple_strtoul(buf, NULL, 16); \
  17798. + dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
  17799. + return count; \
  17800. +}
  17801. +
  17802. +#elif defined(PCI_INTERFACE)
  17803. +
  17804. +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
  17805. +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
  17806. +{ \
  17807. + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \
  17808. + uint32_t val; \
  17809. + val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
  17810. + return sprintf (buf, "%s = 0x%x\n", _string_, val); \
  17811. +}
  17812. +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
  17813. +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
  17814. + const char *buf, size_t count) \
  17815. +{ \
  17816. + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \
  17817. + uint32_t set = simple_strtoul(buf, NULL, 16); \
  17818. + dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
  17819. + return count; \
  17820. +}
  17821. +
  17822. +#elif defined(PLATFORM_INTERFACE)
  17823. +
  17824. +#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
  17825. +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
  17826. +{ \
  17827. + struct platform_device *platform_dev = \
  17828. + container_of(_dev, struct platform_device, dev); \
  17829. + dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
  17830. + uint32_t val; \
  17831. + DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \
  17832. + __func__, _dev, platform_dev, otg_dev); \
  17833. + val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
  17834. + return sprintf (buf, "%s = 0x%x\n", _string_, val); \
  17835. +}
  17836. +#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
  17837. +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
  17838. + const char *buf, size_t count) \
  17839. +{ \
  17840. + struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
  17841. + dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
  17842. + uint32_t set = simple_strtoul(buf, NULL, 16); \
  17843. + dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\
  17844. + return count; \
  17845. +}
  17846. +#endif
  17847. +
  17848. +/*
  17849. + * MACROs for defining sysfs attribute for 32-bit registers
  17850. + */
  17851. +#ifdef LM_INTERFACE
  17852. +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
  17853. +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
  17854. +{ \
  17855. + struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
  17856. + dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
  17857. + uint32_t val; \
  17858. + val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
  17859. + return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
  17860. +}
  17861. +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
  17862. +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
  17863. + const char *buf, size_t count) \
  17864. +{ \
  17865. + struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \
  17866. + dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \
  17867. + uint32_t val = simple_strtoul(buf, NULL, 16); \
  17868. + dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
  17869. + return count; \
  17870. +}
  17871. +#elif defined(PCI_INTERFACE)
  17872. +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
  17873. +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
  17874. +{ \
  17875. + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \
  17876. + uint32_t val; \
  17877. + val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
  17878. + return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
  17879. +}
  17880. +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
  17881. +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
  17882. + const char *buf, size_t count) \
  17883. +{ \
  17884. + dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \
  17885. + uint32_t val = simple_strtoul(buf, NULL, 16); \
  17886. + dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
  17887. + return count; \
  17888. +}
  17889. +
  17890. +#elif defined(PLATFORM_INTERFACE)
  17891. +#include "dwc_otg_dbg.h"
  17892. +#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
  17893. +static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \
  17894. +{ \
  17895. + struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
  17896. + dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
  17897. + uint32_t val; \
  17898. + DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \
  17899. + __func__, _dev, platform_dev, otg_dev); \
  17900. + val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \
  17901. + return sprintf (buf, "%s = 0x%08x\n", _string_, val); \
  17902. +}
  17903. +#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
  17904. +static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \
  17905. + const char *buf, size_t count) \
  17906. +{ \
  17907. + struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \
  17908. + dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \
  17909. + uint32_t val = simple_strtoul(buf, NULL, 16); \
  17910. + dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \
  17911. + return count; \
  17912. +}
  17913. +
  17914. +#endif
  17915. +
  17916. +#define DWC_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_,_string_) \
  17917. +DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
  17918. +DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \
  17919. +DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
  17920. +
  17921. +#define DWC_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_,_string_) \
  17922. +DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \
  17923. +DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
  17924. +
  17925. +#define DWC_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_,_addr_,_string_) \
  17926. +DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
  17927. +DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \
  17928. +DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store);
  17929. +
  17930. +#define DWC_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_,_addr_,_string_) \
  17931. +DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \
  17932. +DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL);
  17933. +
  17934. +/** @name Functions for Show/Store of Attributes */
  17935. +/**@{*/
  17936. +
  17937. +/**
  17938. + * Helper function returning the otg_device structure of the given device
  17939. + */
  17940. +static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev)
  17941. +{
  17942. + dwc_otg_device_t *otg_dev;
  17943. + DWC_OTG_GETDRVDEV(otg_dev, _dev);
  17944. + return otg_dev;
  17945. +}
  17946. +
  17947. +/**
  17948. + * Show the register offset of the Register Access.
  17949. + */
  17950. +static ssize_t regoffset_show(struct device *_dev,
  17951. + struct device_attribute *attr, char *buf)
  17952. +{
  17953. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  17954. + return snprintf(buf, sizeof("0xFFFFFFFF\n") + 1, "0x%08x\n",
  17955. + otg_dev->os_dep.reg_offset);
  17956. +}
  17957. +
  17958. +/**
  17959. + * Set the register offset for the next Register Access Read/Write
  17960. + */
  17961. +static ssize_t regoffset_store(struct device *_dev,
  17962. + struct device_attribute *attr,
  17963. + const char *buf, size_t count)
  17964. +{
  17965. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  17966. + uint32_t offset = simple_strtoul(buf, NULL, 16);
  17967. +#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
  17968. + if (offset < SZ_256K) {
  17969. +#elif defined(PCI_INTERFACE)
  17970. + if (offset < 0x00040000) {
  17971. +#endif
  17972. + otg_dev->os_dep.reg_offset = offset;
  17973. + } else {
  17974. + dev_err(_dev, "invalid offset\n");
  17975. + }
  17976. +
  17977. + return count;
  17978. +}
  17979. +
  17980. +DEVICE_ATTR(regoffset, S_IRUGO | S_IWUSR, regoffset_show, regoffset_store);
  17981. +
  17982. +/**
  17983. + * Show the value of the register at the offset in the reg_offset
  17984. + * attribute.
  17985. + */
  17986. +static ssize_t regvalue_show(struct device *_dev,
  17987. + struct device_attribute *attr, char *buf)
  17988. +{
  17989. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  17990. + uint32_t val;
  17991. + volatile uint32_t *addr;
  17992. +
  17993. + if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) {
  17994. + /* Calculate the address */
  17995. + addr = (uint32_t *) (otg_dev->os_dep.reg_offset +
  17996. + (uint8_t *) otg_dev->os_dep.base);
  17997. + val = DWC_READ_REG32(addr);
  17998. + return snprintf(buf,
  17999. + sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n") + 1,
  18000. + "Reg@0x%06x = 0x%08x\n", otg_dev->os_dep.reg_offset,
  18001. + val);
  18002. + } else {
  18003. + dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->os_dep.reg_offset);
  18004. + return sprintf(buf, "invalid offset\n");
  18005. + }
  18006. +}
  18007. +
  18008. +/**
  18009. + * Store the value in the register at the offset in the reg_offset
  18010. + * attribute.
  18011. + *
  18012. + */
  18013. +static ssize_t regvalue_store(struct device *_dev,
  18014. + struct device_attribute *attr,
  18015. + const char *buf, size_t count)
  18016. +{
  18017. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18018. + volatile uint32_t *addr;
  18019. + uint32_t val = simple_strtoul(buf, NULL, 16);
  18020. + //dev_dbg(_dev, "Offset=0x%08x Val=0x%08x\n", otg_dev->reg_offset, val);
  18021. + if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) {
  18022. + /* Calculate the address */
  18023. + addr = (uint32_t *) (otg_dev->os_dep.reg_offset +
  18024. + (uint8_t *) otg_dev->os_dep.base);
  18025. + DWC_WRITE_REG32(addr, val);
  18026. + } else {
  18027. + dev_err(_dev, "Invalid Register Offset (0x%08x)\n",
  18028. + otg_dev->os_dep.reg_offset);
  18029. + }
  18030. + return count;
  18031. +}
  18032. +
  18033. +DEVICE_ATTR(regvalue, S_IRUGO | S_IWUSR, regvalue_show, regvalue_store);
  18034. +
  18035. +/*
  18036. + * Attributes
  18037. + */
  18038. +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode, "Mode");
  18039. +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable, "HNPCapable");
  18040. +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, "SRPCapable");
  18041. +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hsic_connect, "HSIC Connect");
  18042. +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(inv_sel_hsic, "Invert Select HSIC");
  18043. +
  18044. +//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(buspower,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
  18045. +//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(bussuspend,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode");
  18046. +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected, "Bus Connected");
  18047. +
  18048. +DWC_OTG_DEVICE_ATTR_REG32_RW(gotgctl, 0, "GOTGCTL");
  18049. +DWC_OTG_DEVICE_ATTR_REG32_RW(gusbcfg,
  18050. + &(otg_dev->core_if->core_global_regs->gusbcfg),
  18051. + "GUSBCFG");
  18052. +DWC_OTG_DEVICE_ATTR_REG32_RW(grxfsiz,
  18053. + &(otg_dev->core_if->core_global_regs->grxfsiz),
  18054. + "GRXFSIZ");
  18055. +DWC_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz,
  18056. + &(otg_dev->core_if->core_global_regs->gnptxfsiz),
  18057. + "GNPTXFSIZ");
  18058. +DWC_OTG_DEVICE_ATTR_REG32_RW(gpvndctl,
  18059. + &(otg_dev->core_if->core_global_regs->gpvndctl),
  18060. + "GPVNDCTL");
  18061. +DWC_OTG_DEVICE_ATTR_REG32_RW(ggpio,
  18062. + &(otg_dev->core_if->core_global_regs->ggpio),
  18063. + "GGPIO");
  18064. +DWC_OTG_DEVICE_ATTR_REG32_RW(guid, &(otg_dev->core_if->core_global_regs->guid),
  18065. + "GUID");
  18066. +DWC_OTG_DEVICE_ATTR_REG32_RO(gsnpsid,
  18067. + &(otg_dev->core_if->core_global_regs->gsnpsid),
  18068. + "GSNPSID");
  18069. +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed, "Device Speed");
  18070. +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed, "Device Enumeration Speed");
  18071. +
  18072. +DWC_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz,
  18073. + &(otg_dev->core_if->core_global_regs->hptxfsiz),
  18074. + "HPTXFSIZ");
  18075. +DWC_OTG_DEVICE_ATTR_REG32_RW(hprt0, otg_dev->core_if->host_if->hprt0, "HPRT0");
  18076. +
  18077. +/**
  18078. + * @todo Add code to initiate the HNP.
  18079. + */
  18080. +/**
  18081. + * Show the HNP status bit
  18082. + */
  18083. +static ssize_t hnp_show(struct device *_dev,
  18084. + struct device_attribute *attr, char *buf)
  18085. +{
  18086. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18087. + return sprintf(buf, "HstNegScs = 0x%x\n",
  18088. + dwc_otg_get_hnpstatus(otg_dev->core_if));
  18089. +}
  18090. +
  18091. +/**
  18092. + * Set the HNP Request bit
  18093. + */
  18094. +static ssize_t hnp_store(struct device *_dev,
  18095. + struct device_attribute *attr,
  18096. + const char *buf, size_t count)
  18097. +{
  18098. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18099. + uint32_t in = simple_strtoul(buf, NULL, 16);
  18100. + dwc_otg_set_hnpreq(otg_dev->core_if, in);
  18101. + return count;
  18102. +}
  18103. +
  18104. +DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store);
  18105. +
  18106. +/**
  18107. + * @todo Add code to initiate the SRP.
  18108. + */
  18109. +/**
  18110. + * Show the SRP status bit
  18111. + */
  18112. +static ssize_t srp_show(struct device *_dev,
  18113. + struct device_attribute *attr, char *buf)
  18114. +{
  18115. +#ifndef DWC_HOST_ONLY
  18116. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18117. + return sprintf(buf, "SesReqScs = 0x%x\n",
  18118. + dwc_otg_get_srpstatus(otg_dev->core_if));
  18119. +#else
  18120. + return sprintf(buf, "Host Only Mode!\n");
  18121. +#endif
  18122. +}
  18123. +
  18124. +/**
  18125. + * Set the SRP Request bit
  18126. + */
  18127. +static ssize_t srp_store(struct device *_dev,
  18128. + struct device_attribute *attr,
  18129. + const char *buf, size_t count)
  18130. +{
  18131. +#ifndef DWC_HOST_ONLY
  18132. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18133. + dwc_otg_pcd_initiate_srp(otg_dev->pcd);
  18134. +#endif
  18135. + return count;
  18136. +}
  18137. +
  18138. +DEVICE_ATTR(srp, 0644, srp_show, srp_store);
  18139. +
  18140. +/**
  18141. + * @todo Need to do more for power on/off?
  18142. + */
  18143. +/**
  18144. + * Show the Bus Power status
  18145. + */
  18146. +static ssize_t buspower_show(struct device *_dev,
  18147. + struct device_attribute *attr, char *buf)
  18148. +{
  18149. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18150. + return sprintf(buf, "Bus Power = 0x%x\n",
  18151. + dwc_otg_get_prtpower(otg_dev->core_if));
  18152. +}
  18153. +
  18154. +/**
  18155. + * Set the Bus Power status
  18156. + */
  18157. +static ssize_t buspower_store(struct device *_dev,
  18158. + struct device_attribute *attr,
  18159. + const char *buf, size_t count)
  18160. +{
  18161. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18162. + uint32_t on = simple_strtoul(buf, NULL, 16);
  18163. + dwc_otg_set_prtpower(otg_dev->core_if, on);
  18164. + return count;
  18165. +}
  18166. +
  18167. +DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store);
  18168. +
  18169. +/**
  18170. + * @todo Need to do more for suspend?
  18171. + */
  18172. +/**
  18173. + * Show the Bus Suspend status
  18174. + */
  18175. +static ssize_t bussuspend_show(struct device *_dev,
  18176. + struct device_attribute *attr, char *buf)
  18177. +{
  18178. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18179. + return sprintf(buf, "Bus Suspend = 0x%x\n",
  18180. + dwc_otg_get_prtsuspend(otg_dev->core_if));
  18181. +}
  18182. +
  18183. +/**
  18184. + * Set the Bus Suspend status
  18185. + */
  18186. +static ssize_t bussuspend_store(struct device *_dev,
  18187. + struct device_attribute *attr,
  18188. + const char *buf, size_t count)
  18189. +{
  18190. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18191. + uint32_t in = simple_strtoul(buf, NULL, 16);
  18192. + dwc_otg_set_prtsuspend(otg_dev->core_if, in);
  18193. + return count;
  18194. +}
  18195. +
  18196. +DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store);
  18197. +
  18198. +/**
  18199. + * Show the Mode Change Ready Timer status
  18200. + */
  18201. +static ssize_t mode_ch_tim_en_show(struct device *_dev,
  18202. + struct device_attribute *attr, char *buf)
  18203. +{
  18204. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18205. + return sprintf(buf, "Mode Change Ready Timer Enable = 0x%x\n",
  18206. + dwc_otg_get_mode_ch_tim(otg_dev->core_if));
  18207. +}
  18208. +
  18209. +/**
  18210. + * Set the Mode Change Ready Timer status
  18211. + */
  18212. +static ssize_t mode_ch_tim_en_store(struct device *_dev,
  18213. + struct device_attribute *attr,
  18214. + const char *buf, size_t count)
  18215. +{
  18216. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18217. + uint32_t in = simple_strtoul(buf, NULL, 16);
  18218. + dwc_otg_set_mode_ch_tim(otg_dev->core_if, in);
  18219. + return count;
  18220. +}
  18221. +
  18222. +DEVICE_ATTR(mode_ch_tim_en, 0644, mode_ch_tim_en_show, mode_ch_tim_en_store);
  18223. +
  18224. +/**
  18225. + * Show the value of HFIR Frame Interval bitfield
  18226. + */
  18227. +static ssize_t fr_interval_show(struct device *_dev,
  18228. + struct device_attribute *attr, char *buf)
  18229. +{
  18230. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18231. + return sprintf(buf, "Frame Interval = 0x%x\n",
  18232. + dwc_otg_get_fr_interval(otg_dev->core_if));
  18233. +}
  18234. +
  18235. +/**
  18236. + * Set the HFIR Frame Interval value
  18237. + */
  18238. +static ssize_t fr_interval_store(struct device *_dev,
  18239. + struct device_attribute *attr,
  18240. + const char *buf, size_t count)
  18241. +{
  18242. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18243. + uint32_t in = simple_strtoul(buf, NULL, 10);
  18244. + dwc_otg_set_fr_interval(otg_dev->core_if, in);
  18245. + return count;
  18246. +}
  18247. +
  18248. +DEVICE_ATTR(fr_interval, 0644, fr_interval_show, fr_interval_store);
  18249. +
  18250. +/**
  18251. + * Show the status of Remote Wakeup.
  18252. + */
  18253. +static ssize_t remote_wakeup_show(struct device *_dev,
  18254. + struct device_attribute *attr, char *buf)
  18255. +{
  18256. +#ifndef DWC_HOST_ONLY
  18257. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18258. +
  18259. + return sprintf(buf,
  18260. + "Remote Wakeup Sig = %d Enabled = %d LPM Remote Wakeup = %d\n",
  18261. + dwc_otg_get_remotewakesig(otg_dev->core_if),
  18262. + dwc_otg_pcd_get_rmwkup_enable(otg_dev->pcd),
  18263. + dwc_otg_get_lpm_remotewakeenabled(otg_dev->core_if));
  18264. +#else
  18265. + return sprintf(buf, "Host Only Mode!\n");
  18266. +#endif /* DWC_HOST_ONLY */
  18267. +}
  18268. +
  18269. +/**
  18270. + * Initiate a remote wakeup of the host. The Device control register
  18271. + * Remote Wakeup Signal bit is written if the PCD Remote wakeup enable
  18272. + * flag is set.
  18273. + *
  18274. + */
  18275. +static ssize_t remote_wakeup_store(struct device *_dev,
  18276. + struct device_attribute *attr,
  18277. + const char *buf, size_t count)
  18278. +{
  18279. +#ifndef DWC_HOST_ONLY
  18280. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18281. + uint32_t val = simple_strtoul(buf, NULL, 16);
  18282. +
  18283. + if (val & 1) {
  18284. + dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 1);
  18285. + } else {
  18286. + dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 0);
  18287. + }
  18288. +#endif /* DWC_HOST_ONLY */
  18289. + return count;
  18290. +}
  18291. +
  18292. +DEVICE_ATTR(remote_wakeup, S_IRUGO | S_IWUSR, remote_wakeup_show,
  18293. + remote_wakeup_store);
  18294. +
  18295. +/**
  18296. + * Show the whether core is hibernated or not.
  18297. + */
  18298. +static ssize_t rem_wakeup_pwrdn_show(struct device *_dev,
  18299. + struct device_attribute *attr, char *buf)
  18300. +{
  18301. +#ifndef DWC_HOST_ONLY
  18302. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18303. +
  18304. + if (dwc_otg_get_core_state(otg_dev->core_if)) {
  18305. + DWC_PRINTF("Core is in hibernation\n");
  18306. + } else {
  18307. + DWC_PRINTF("Core is not in hibernation\n");
  18308. + }
  18309. +#endif /* DWC_HOST_ONLY */
  18310. + return 0;
  18311. +}
  18312. +
  18313. +extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,
  18314. + int rem_wakeup, int reset);
  18315. +
  18316. +/**
  18317. + * Initiate a remote wakeup of the device to exit from hibernation.
  18318. + */
  18319. +static ssize_t rem_wakeup_pwrdn_store(struct device *_dev,
  18320. + struct device_attribute *attr,
  18321. + const char *buf, size_t count)
  18322. +{
  18323. +#ifndef DWC_HOST_ONLY
  18324. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18325. + dwc_otg_device_hibernation_restore(otg_dev->core_if, 1, 0);
  18326. +#endif
  18327. + return count;
  18328. +}
  18329. +
  18330. +DEVICE_ATTR(rem_wakeup_pwrdn, S_IRUGO | S_IWUSR, rem_wakeup_pwrdn_show,
  18331. + rem_wakeup_pwrdn_store);
  18332. +
  18333. +static ssize_t disconnect_us(struct device *_dev,
  18334. + struct device_attribute *attr,
  18335. + const char *buf, size_t count)
  18336. +{
  18337. +
  18338. +#ifndef DWC_HOST_ONLY
  18339. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18340. + uint32_t val = simple_strtoul(buf, NULL, 16);
  18341. + DWC_PRINTF("The Passed value is %04x\n", val);
  18342. +
  18343. + dwc_otg_pcd_disconnect_us(otg_dev->pcd, 50);
  18344. +
  18345. +#endif /* DWC_HOST_ONLY */
  18346. + return count;
  18347. +}
  18348. +
  18349. +DEVICE_ATTR(disconnect_us, S_IWUSR, 0, disconnect_us);
  18350. +
  18351. +/**
  18352. + * Dump global registers and either host or device registers (depending on the
  18353. + * current mode of the core).
  18354. + */
  18355. +static ssize_t regdump_show(struct device *_dev,
  18356. + struct device_attribute *attr, char *buf)
  18357. +{
  18358. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18359. +
  18360. + dwc_otg_dump_global_registers(otg_dev->core_if);
  18361. + if (dwc_otg_is_host_mode(otg_dev->core_if)) {
  18362. + dwc_otg_dump_host_registers(otg_dev->core_if);
  18363. + } else {
  18364. + dwc_otg_dump_dev_registers(otg_dev->core_if);
  18365. +
  18366. + }
  18367. + return sprintf(buf, "Register Dump\n");
  18368. +}
  18369. +
  18370. +DEVICE_ATTR(regdump, S_IRUGO | S_IWUSR, regdump_show, 0);
  18371. +
  18372. +/**
  18373. + * Dump global registers and either host or device registers (depending on the
  18374. + * current mode of the core).
  18375. + */
  18376. +static ssize_t spramdump_show(struct device *_dev,
  18377. + struct device_attribute *attr, char *buf)
  18378. +{
  18379. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18380. +
  18381. + dwc_otg_dump_spram(otg_dev->core_if);
  18382. +
  18383. + return sprintf(buf, "SPRAM Dump\n");
  18384. +}
  18385. +
  18386. +DEVICE_ATTR(spramdump, S_IRUGO | S_IWUSR, spramdump_show, 0);
  18387. +
  18388. +/**
  18389. + * Dump the current hcd state.
  18390. + */
  18391. +static ssize_t hcddump_show(struct device *_dev,
  18392. + struct device_attribute *attr, char *buf)
  18393. +{
  18394. +#ifndef DWC_DEVICE_ONLY
  18395. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18396. + dwc_otg_hcd_dump_state(otg_dev->hcd);
  18397. +#endif /* DWC_DEVICE_ONLY */
  18398. + return sprintf(buf, "HCD Dump\n");
  18399. +}
  18400. +
  18401. +DEVICE_ATTR(hcddump, S_IRUGO | S_IWUSR, hcddump_show, 0);
  18402. +
  18403. +/**
  18404. + * Dump the average frame remaining at SOF. This can be used to
  18405. + * determine average interrupt latency. Frame remaining is also shown for
  18406. + * start transfer and two additional sample points.
  18407. + */
  18408. +static ssize_t hcd_frrem_show(struct device *_dev,
  18409. + struct device_attribute *attr, char *buf)
  18410. +{
  18411. +#ifndef DWC_DEVICE_ONLY
  18412. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18413. +
  18414. + dwc_otg_hcd_dump_frrem(otg_dev->hcd);
  18415. +#endif /* DWC_DEVICE_ONLY */
  18416. + return sprintf(buf, "HCD Dump Frame Remaining\n");
  18417. +}
  18418. +
  18419. +DEVICE_ATTR(hcd_frrem, S_IRUGO | S_IWUSR, hcd_frrem_show, 0);
  18420. +
  18421. +/**
  18422. + * Displays the time required to read the GNPTXFSIZ register many times (the
  18423. + * output shows the number of times the register is read).
  18424. + */
  18425. +#define RW_REG_COUNT 10000000
  18426. +#define MSEC_PER_JIFFIE 1000/HZ
  18427. +static ssize_t rd_reg_test_show(struct device *_dev,
  18428. + struct device_attribute *attr, char *buf)
  18429. +{
  18430. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18431. + int i;
  18432. + int time;
  18433. + int start_jiffies;
  18434. +
  18435. + printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
  18436. + HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
  18437. + start_jiffies = jiffies;
  18438. + for (i = 0; i < RW_REG_COUNT; i++) {
  18439. + dwc_otg_get_gnptxfsiz(otg_dev->core_if);
  18440. + }
  18441. + time = jiffies - start_jiffies;
  18442. + return sprintf(buf,
  18443. + "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
  18444. + RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
  18445. +}
  18446. +
  18447. +DEVICE_ATTR(rd_reg_test, S_IRUGO | S_IWUSR, rd_reg_test_show, 0);
  18448. +
  18449. +/**
  18450. + * Displays the time required to write the GNPTXFSIZ register many times (the
  18451. + * output shows the number of times the register is written).
  18452. + */
  18453. +static ssize_t wr_reg_test_show(struct device *_dev,
  18454. + struct device_attribute *attr, char *buf)
  18455. +{
  18456. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18457. + uint32_t reg_val;
  18458. + int i;
  18459. + int time;
  18460. + int start_jiffies;
  18461. +
  18462. + printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n",
  18463. + HZ, MSEC_PER_JIFFIE, loops_per_jiffy);
  18464. + reg_val = dwc_otg_get_gnptxfsiz(otg_dev->core_if);
  18465. + start_jiffies = jiffies;
  18466. + for (i = 0; i < RW_REG_COUNT; i++) {
  18467. + dwc_otg_set_gnptxfsiz(otg_dev->core_if, reg_val);
  18468. + }
  18469. + time = jiffies - start_jiffies;
  18470. + return sprintf(buf,
  18471. + "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n",
  18472. + RW_REG_COUNT, time * MSEC_PER_JIFFIE, time);
  18473. +}
  18474. +
  18475. +DEVICE_ATTR(wr_reg_test, S_IRUGO | S_IWUSR, wr_reg_test_show, 0);
  18476. +
  18477. +#ifdef CONFIG_USB_DWC_OTG_LPM
  18478. +
  18479. +/**
  18480. +* Show the lpm_response attribute.
  18481. +*/
  18482. +static ssize_t lpmresp_show(struct device *_dev,
  18483. + struct device_attribute *attr, char *buf)
  18484. +{
  18485. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18486. +
  18487. + if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if))
  18488. + return sprintf(buf, "** LPM is DISABLED **\n");
  18489. +
  18490. + if (!dwc_otg_is_device_mode(otg_dev->core_if)) {
  18491. + return sprintf(buf, "** Current mode is not device mode\n");
  18492. + }
  18493. + return sprintf(buf, "lpm_response = %d\n",
  18494. + dwc_otg_get_lpmresponse(otg_dev->core_if));
  18495. +}
  18496. +
  18497. +/**
  18498. +* Store the lpm_response attribute.
  18499. +*/
  18500. +static ssize_t lpmresp_store(struct device *_dev,
  18501. + struct device_attribute *attr,
  18502. + const char *buf, size_t count)
  18503. +{
  18504. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18505. + uint32_t val = simple_strtoul(buf, NULL, 16);
  18506. +
  18507. + if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) {
  18508. + return 0;
  18509. + }
  18510. +
  18511. + if (!dwc_otg_is_device_mode(otg_dev->core_if)) {
  18512. + return 0;
  18513. + }
  18514. +
  18515. + dwc_otg_set_lpmresponse(otg_dev->core_if, val);
  18516. + return count;
  18517. +}
  18518. +
  18519. +DEVICE_ATTR(lpm_response, S_IRUGO | S_IWUSR, lpmresp_show, lpmresp_store);
  18520. +
  18521. +/**
  18522. +* Show the sleep_status attribute.
  18523. +*/
  18524. +static ssize_t sleepstatus_show(struct device *_dev,
  18525. + struct device_attribute *attr, char *buf)
  18526. +{
  18527. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18528. + return sprintf(buf, "Sleep Status = %d\n",
  18529. + dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if));
  18530. +}
  18531. +
  18532. +/**
  18533. + * Store the sleep_status attribure.
  18534. + */
  18535. +static ssize_t sleepstatus_store(struct device *_dev,
  18536. + struct device_attribute *attr,
  18537. + const char *buf, size_t count)
  18538. +{
  18539. + dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev);
  18540. + dwc_otg_core_if_t *core_if = otg_dev->core_if;
  18541. +
  18542. + if (dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)) {
  18543. + if (dwc_otg_is_host_mode(core_if)) {
  18544. +
  18545. + DWC_PRINTF("Host initiated resume\n");
  18546. + dwc_otg_set_prtresume(otg_dev->core_if, 1);
  18547. + }
  18548. + }
  18549. +
  18550. + return count;
  18551. +}
  18552. +
  18553. +DEVICE_ATTR(sleep_status, S_IRUGO | S_IWUSR, sleepstatus_show,
  18554. + sleepstatus_store);
  18555. +
  18556. +#endif /* CONFIG_USB_DWC_OTG_LPM_ENABLE */
  18557. +
  18558. +/**@}*/
  18559. +
  18560. +/**
  18561. + * Create the device files
  18562. + */
  18563. +void dwc_otg_attr_create(
  18564. +#ifdef LM_INTERFACE
  18565. + struct lm_device *dev
  18566. +#elif defined(PCI_INTERFACE)
  18567. + struct pci_dev *dev
  18568. +#elif defined(PLATFORM_INTERFACE)
  18569. + struct platform_device *dev
  18570. +#endif
  18571. + )
  18572. +{
  18573. + int error;
  18574. +
  18575. + error = device_create_file(&dev->dev, &dev_attr_regoffset);
  18576. + error = device_create_file(&dev->dev, &dev_attr_regvalue);
  18577. + error = device_create_file(&dev->dev, &dev_attr_mode);
  18578. + error = device_create_file(&dev->dev, &dev_attr_hnpcapable);
  18579. + error = device_create_file(&dev->dev, &dev_attr_srpcapable);
  18580. + error = device_create_file(&dev->dev, &dev_attr_hsic_connect);
  18581. + error = device_create_file(&dev->dev, &dev_attr_inv_sel_hsic);
  18582. + error = device_create_file(&dev->dev, &dev_attr_hnp);
  18583. + error = device_create_file(&dev->dev, &dev_attr_srp);
  18584. + error = device_create_file(&dev->dev, &dev_attr_buspower);
  18585. + error = device_create_file(&dev->dev, &dev_attr_bussuspend);
  18586. + error = device_create_file(&dev->dev, &dev_attr_mode_ch_tim_en);
  18587. + error = device_create_file(&dev->dev, &dev_attr_fr_interval);
  18588. + error = device_create_file(&dev->dev, &dev_attr_busconnected);
  18589. + error = device_create_file(&dev->dev, &dev_attr_gotgctl);
  18590. + error = device_create_file(&dev->dev, &dev_attr_gusbcfg);
  18591. + error = device_create_file(&dev->dev, &dev_attr_grxfsiz);
  18592. + error = device_create_file(&dev->dev, &dev_attr_gnptxfsiz);
  18593. + error = device_create_file(&dev->dev, &dev_attr_gpvndctl);
  18594. + error = device_create_file(&dev->dev, &dev_attr_ggpio);
  18595. + error = device_create_file(&dev->dev, &dev_attr_guid);
  18596. + error = device_create_file(&dev->dev, &dev_attr_gsnpsid);
  18597. + error = device_create_file(&dev->dev, &dev_attr_devspeed);
  18598. + error = device_create_file(&dev->dev, &dev_attr_enumspeed);
  18599. + error = device_create_file(&dev->dev, &dev_attr_hptxfsiz);
  18600. + error = device_create_file(&dev->dev, &dev_attr_hprt0);
  18601. + error = device_create_file(&dev->dev, &dev_attr_remote_wakeup);
  18602. + error = device_create_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn);
  18603. + error = device_create_file(&dev->dev, &dev_attr_disconnect_us);
  18604. + error = device_create_file(&dev->dev, &dev_attr_regdump);
  18605. + error = device_create_file(&dev->dev, &dev_attr_spramdump);
  18606. + error = device_create_file(&dev->dev, &dev_attr_hcddump);
  18607. + error = device_create_file(&dev->dev, &dev_attr_hcd_frrem);
  18608. + error = device_create_file(&dev->dev, &dev_attr_rd_reg_test);
  18609. + error = device_create_file(&dev->dev, &dev_attr_wr_reg_test);
  18610. +#ifdef CONFIG_USB_DWC_OTG_LPM
  18611. + error = device_create_file(&dev->dev, &dev_attr_lpm_response);
  18612. + error = device_create_file(&dev->dev, &dev_attr_sleep_status);
  18613. +#endif
  18614. +}
  18615. +
  18616. +/**
  18617. + * Remove the device files
  18618. + */
  18619. +void dwc_otg_attr_remove(
  18620. +#ifdef LM_INTERFACE
  18621. + struct lm_device *dev
  18622. +#elif defined(PCI_INTERFACE)
  18623. + struct pci_dev *dev
  18624. +#elif defined(PLATFORM_INTERFACE)
  18625. + struct platform_device *dev
  18626. +#endif
  18627. + )
  18628. +{
  18629. + device_remove_file(&dev->dev, &dev_attr_regoffset);
  18630. + device_remove_file(&dev->dev, &dev_attr_regvalue);
  18631. + device_remove_file(&dev->dev, &dev_attr_mode);
  18632. + device_remove_file(&dev->dev, &dev_attr_hnpcapable);
  18633. + device_remove_file(&dev->dev, &dev_attr_srpcapable);
  18634. + device_remove_file(&dev->dev, &dev_attr_hsic_connect);
  18635. + device_remove_file(&dev->dev, &dev_attr_inv_sel_hsic);
  18636. + device_remove_file(&dev->dev, &dev_attr_hnp);
  18637. + device_remove_file(&dev->dev, &dev_attr_srp);
  18638. + device_remove_file(&dev->dev, &dev_attr_buspower);
  18639. + device_remove_file(&dev->dev, &dev_attr_bussuspend);
  18640. + device_remove_file(&dev->dev, &dev_attr_mode_ch_tim_en);
  18641. + device_remove_file(&dev->dev, &dev_attr_fr_interval);
  18642. + device_remove_file(&dev->dev, &dev_attr_busconnected);
  18643. + device_remove_file(&dev->dev, &dev_attr_gotgctl);
  18644. + device_remove_file(&dev->dev, &dev_attr_gusbcfg);
  18645. + device_remove_file(&dev->dev, &dev_attr_grxfsiz);
  18646. + device_remove_file(&dev->dev, &dev_attr_gnptxfsiz);
  18647. + device_remove_file(&dev->dev, &dev_attr_gpvndctl);
  18648. + device_remove_file(&dev->dev, &dev_attr_ggpio);
  18649. + device_remove_file(&dev->dev, &dev_attr_guid);
  18650. + device_remove_file(&dev->dev, &dev_attr_gsnpsid);
  18651. + device_remove_file(&dev->dev, &dev_attr_devspeed);
  18652. + device_remove_file(&dev->dev, &dev_attr_enumspeed);
  18653. + device_remove_file(&dev->dev, &dev_attr_hptxfsiz);
  18654. + device_remove_file(&dev->dev, &dev_attr_hprt0);
  18655. + device_remove_file(&dev->dev, &dev_attr_remote_wakeup);
  18656. + device_remove_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn);
  18657. + device_remove_file(&dev->dev, &dev_attr_disconnect_us);
  18658. + device_remove_file(&dev->dev, &dev_attr_regdump);
  18659. + device_remove_file(&dev->dev, &dev_attr_spramdump);
  18660. + device_remove_file(&dev->dev, &dev_attr_hcddump);
  18661. + device_remove_file(&dev->dev, &dev_attr_hcd_frrem);
  18662. + device_remove_file(&dev->dev, &dev_attr_rd_reg_test);
  18663. + device_remove_file(&dev->dev, &dev_attr_wr_reg_test);
  18664. +#ifdef CONFIG_USB_DWC_OTG_LPM
  18665. + device_remove_file(&dev->dev, &dev_attr_lpm_response);
  18666. + device_remove_file(&dev->dev, &dev_attr_sleep_status);
  18667. +#endif
  18668. +}
  18669. --- /dev/null
  18670. +++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.h
  18671. @@ -0,0 +1,89 @@
  18672. +/* ==========================================================================
  18673. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.h $
  18674. + * $Revision: #13 $
  18675. + * $Date: 2010/06/21 $
  18676. + * $Change: 1532021 $
  18677. + *
  18678. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  18679. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  18680. + * otherwise expressly agreed to in writing between Synopsys and you.
  18681. + *
  18682. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  18683. + * any End User Software License Agreement or Agreement for Licensed Product
  18684. + * with Synopsys or any supplement thereto. You are permitted to use and
  18685. + * redistribute this Software in source and binary forms, with or without
  18686. + * modification, provided that redistributions of source code must retain this
  18687. + * notice. You may not view, use, disclose, copy or distribute this file or
  18688. + * any information contained herein except pursuant to this license grant from
  18689. + * Synopsys. If you do not agree with this notice, including the disclaimer
  18690. + * below, then you are not authorized to use the Software.
  18691. + *
  18692. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  18693. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18694. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18695. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  18696. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  18697. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  18698. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  18699. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  18700. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  18701. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  18702. + * DAMAGE.
  18703. + * ========================================================================== */
  18704. +
  18705. +#if !defined(__DWC_OTG_ATTR_H__)
  18706. +#define __DWC_OTG_ATTR_H__
  18707. +
  18708. +/** @file
  18709. + * This file contains the interface to the Linux device attributes.
  18710. + */
  18711. +extern struct device_attribute dev_attr_regoffset;
  18712. +extern struct device_attribute dev_attr_regvalue;
  18713. +
  18714. +extern struct device_attribute dev_attr_mode;
  18715. +extern struct device_attribute dev_attr_hnpcapable;
  18716. +extern struct device_attribute dev_attr_srpcapable;
  18717. +extern struct device_attribute dev_attr_hnp;
  18718. +extern struct device_attribute dev_attr_srp;
  18719. +extern struct device_attribute dev_attr_buspower;
  18720. +extern struct device_attribute dev_attr_bussuspend;
  18721. +extern struct device_attribute dev_attr_mode_ch_tim_en;
  18722. +extern struct device_attribute dev_attr_fr_interval;
  18723. +extern struct device_attribute dev_attr_busconnected;
  18724. +extern struct device_attribute dev_attr_gotgctl;
  18725. +extern struct device_attribute dev_attr_gusbcfg;
  18726. +extern struct device_attribute dev_attr_grxfsiz;
  18727. +extern struct device_attribute dev_attr_gnptxfsiz;
  18728. +extern struct device_attribute dev_attr_gpvndctl;
  18729. +extern struct device_attribute dev_attr_ggpio;
  18730. +extern struct device_attribute dev_attr_guid;
  18731. +extern struct device_attribute dev_attr_gsnpsid;
  18732. +extern struct device_attribute dev_attr_devspeed;
  18733. +extern struct device_attribute dev_attr_enumspeed;
  18734. +extern struct device_attribute dev_attr_hptxfsiz;
  18735. +extern struct device_attribute dev_attr_hprt0;
  18736. +#ifdef CONFIG_USB_DWC_OTG_LPM
  18737. +extern struct device_attribute dev_attr_lpm_response;
  18738. +extern struct device_attribute devi_attr_sleep_status;
  18739. +#endif
  18740. +
  18741. +void dwc_otg_attr_create(
  18742. +#ifdef LM_INTERFACE
  18743. + struct lm_device *dev
  18744. +#elif defined(PCI_INTERFACE)
  18745. + struct pci_dev *dev
  18746. +#elif defined(PLATFORM_INTERFACE)
  18747. + struct platform_device *dev
  18748. +#endif
  18749. + );
  18750. +
  18751. +void dwc_otg_attr_remove(
  18752. +#ifdef LM_INTERFACE
  18753. + struct lm_device *dev
  18754. +#elif defined(PCI_INTERFACE)
  18755. + struct pci_dev *dev
  18756. +#elif defined(PLATFORM_INTERFACE)
  18757. + struct platform_device *dev
  18758. +#endif
  18759. + );
  18760. +#endif
  18761. --- /dev/null
  18762. +++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.c
  18763. @@ -0,0 +1,1876 @@
  18764. +/* ==========================================================================
  18765. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  18766. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  18767. + * otherwise expressly agreed to in writing between Synopsys and you.
  18768. + *
  18769. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  18770. + * any End User Software License Agreement or Agreement for Licensed Product
  18771. + * with Synopsys or any supplement thereto. You are permitted to use and
  18772. + * redistribute this Software in source and binary forms, with or without
  18773. + * modification, provided that redistributions of source code must retain this
  18774. + * notice. You may not view, use, disclose, copy or distribute this file or
  18775. + * any information contained herein except pursuant to this license grant from
  18776. + * Synopsys. If you do not agree with this notice, including the disclaimer
  18777. + * below, then you are not authorized to use the Software.
  18778. + *
  18779. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  18780. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18781. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18782. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  18783. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  18784. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  18785. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  18786. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  18787. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  18788. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  18789. + * DAMAGE.
  18790. + * ========================================================================== */
  18791. +
  18792. +/** @file
  18793. + *
  18794. + * This file contains the most of the CFI(Core Feature Interface)
  18795. + * implementation for the OTG.
  18796. + */
  18797. +
  18798. +#ifdef DWC_UTE_CFI
  18799. +
  18800. +#include "dwc_otg_pcd.h"
  18801. +#include "dwc_otg_cfi.h"
  18802. +
  18803. +/** This definition should actually migrate to the Portability Library */
  18804. +#define DWC_CONSTANT_CPU_TO_LE16(x) (x)
  18805. +
  18806. +extern dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex);
  18807. +
  18808. +static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen);
  18809. +static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
  18810. + struct dwc_otg_pcd *pcd,
  18811. + struct cfi_usb_ctrlrequest *ctrl_req);
  18812. +static int cfi_set_feature_value(struct dwc_otg_pcd *pcd);
  18813. +static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
  18814. + struct cfi_usb_ctrlrequest *req);
  18815. +static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
  18816. + struct cfi_usb_ctrlrequest *req);
  18817. +static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
  18818. + struct cfi_usb_ctrlrequest *req);
  18819. +static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
  18820. + struct cfi_usb_ctrlrequest *req);
  18821. +static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep);
  18822. +
  18823. +static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if);
  18824. +static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue);
  18825. +static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue);
  18826. +
  18827. +static uint8_t resize_fifos(dwc_otg_core_if_t * core_if);
  18828. +
  18829. +/** This is the header of the all features descriptor */
  18830. +static cfi_all_features_header_t all_props_desc_header = {
  18831. + .wVersion = DWC_CONSTANT_CPU_TO_LE16(0x100),
  18832. + .wCoreID = DWC_CONSTANT_CPU_TO_LE16(CFI_CORE_ID_OTG),
  18833. + .wNumFeatures = DWC_CONSTANT_CPU_TO_LE16(9),
  18834. +};
  18835. +
  18836. +/** This is an array of statically allocated feature descriptors */
  18837. +static cfi_feature_desc_header_t prop_descs[] = {
  18838. +
  18839. + /* FT_ID_DMA_MODE */
  18840. + {
  18841. + .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_MODE),
  18842. + .bmAttributes = CFI_FEATURE_ATTR_RW,
  18843. + .wDataLength = DWC_CONSTANT_CPU_TO_LE16(1),
  18844. + },
  18845. +
  18846. + /* FT_ID_DMA_BUFFER_SETUP */
  18847. + {
  18848. + .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFFER_SETUP),
  18849. + .bmAttributes = CFI_FEATURE_ATTR_RW,
  18850. + .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
  18851. + },
  18852. +
  18853. + /* FT_ID_DMA_BUFF_ALIGN */
  18854. + {
  18855. + .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFF_ALIGN),
  18856. + .bmAttributes = CFI_FEATURE_ATTR_RW,
  18857. + .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
  18858. + },
  18859. +
  18860. + /* FT_ID_DMA_CONCAT_SETUP */
  18861. + {
  18862. + .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CONCAT_SETUP),
  18863. + .bmAttributes = CFI_FEATURE_ATTR_RW,
  18864. + //.wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
  18865. + },
  18866. +
  18867. + /* FT_ID_DMA_CIRCULAR */
  18868. + {
  18869. + .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CIRCULAR),
  18870. + .bmAttributes = CFI_FEATURE_ATTR_RW,
  18871. + .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
  18872. + },
  18873. +
  18874. + /* FT_ID_THRESHOLD_SETUP */
  18875. + {
  18876. + .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_THRESHOLD_SETUP),
  18877. + .bmAttributes = CFI_FEATURE_ATTR_RW,
  18878. + .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6),
  18879. + },
  18880. +
  18881. + /* FT_ID_DFIFO_DEPTH */
  18882. + {
  18883. + .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DFIFO_DEPTH),
  18884. + .bmAttributes = CFI_FEATURE_ATTR_RO,
  18885. + .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
  18886. + },
  18887. +
  18888. + /* FT_ID_TX_FIFO_DEPTH */
  18889. + {
  18890. + .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_TX_FIFO_DEPTH),
  18891. + .bmAttributes = CFI_FEATURE_ATTR_RW,
  18892. + .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
  18893. + },
  18894. +
  18895. + /* FT_ID_RX_FIFO_DEPTH */
  18896. + {
  18897. + .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_RX_FIFO_DEPTH),
  18898. + .bmAttributes = CFI_FEATURE_ATTR_RW,
  18899. + .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2),
  18900. + }
  18901. +};
  18902. +
  18903. +/** The table of feature names */
  18904. +cfi_string_t prop_name_table[] = {
  18905. + {FT_ID_DMA_MODE, "dma_mode"},
  18906. + {FT_ID_DMA_BUFFER_SETUP, "buffer_setup"},
  18907. + {FT_ID_DMA_BUFF_ALIGN, "buffer_align"},
  18908. + {FT_ID_DMA_CONCAT_SETUP, "concat_setup"},
  18909. + {FT_ID_DMA_CIRCULAR, "buffer_circular"},
  18910. + {FT_ID_THRESHOLD_SETUP, "threshold_setup"},
  18911. + {FT_ID_DFIFO_DEPTH, "dfifo_depth"},
  18912. + {FT_ID_TX_FIFO_DEPTH, "txfifo_depth"},
  18913. + {FT_ID_RX_FIFO_DEPTH, "rxfifo_depth"},
  18914. + {}
  18915. +};
  18916. +
  18917. +/************************************************************************/
  18918. +
  18919. +/**
  18920. + * Returns the name of the feature by its ID
  18921. + * or NULL if no featute ID matches.
  18922. + *
  18923. + */
  18924. +const uint8_t *get_prop_name(uint16_t prop_id, int *len)
  18925. +{
  18926. + cfi_string_t *pstr;
  18927. + *len = 0;
  18928. +
  18929. + for (pstr = prop_name_table; pstr && pstr->s; pstr++) {
  18930. + if (pstr->id == prop_id) {
  18931. + *len = DWC_STRLEN(pstr->s);
  18932. + return pstr->s;
  18933. + }
  18934. + }
  18935. + return NULL;
  18936. +}
  18937. +
  18938. +/**
  18939. + * This function handles all CFI specific control requests.
  18940. + *
  18941. + * Return a negative value to stall the DCE.
  18942. + */
  18943. +int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl)
  18944. +{
  18945. + int retval = 0;
  18946. + dwc_otg_pcd_ep_t *ep = NULL;
  18947. + cfiobject_t *cfi = pcd->cfi;
  18948. + struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
  18949. + uint16_t wLen = DWC_LE16_TO_CPU(&ctrl->wLength);
  18950. + uint16_t wValue = DWC_LE16_TO_CPU(&ctrl->wValue);
  18951. + uint16_t wIndex = DWC_LE16_TO_CPU(&ctrl->wIndex);
  18952. + uint32_t regaddr = 0;
  18953. + uint32_t regval = 0;
  18954. +
  18955. + /* Save this Control Request in the CFI object.
  18956. + * The data field will be assigned in the data stage completion CB function.
  18957. + */
  18958. + cfi->ctrl_req = *ctrl;
  18959. + cfi->ctrl_req.data = NULL;
  18960. +
  18961. + cfi->need_gadget_att = 0;
  18962. + cfi->need_status_in_complete = 0;
  18963. +
  18964. + switch (ctrl->bRequest) {
  18965. + case VEN_CORE_GET_FEATURES:
  18966. + retval = cfi_core_features_buf(cfi->buf_in.buf, CFI_IN_BUF_LEN);
  18967. + if (retval >= 0) {
  18968. + //dump_msg(cfi->buf_in.buf, retval);
  18969. + ep = &pcd->ep0;
  18970. +
  18971. + retval = min((uint16_t) retval, wLen);
  18972. + /* Transfer this buffer to the host through the EP0-IN EP */
  18973. + ep->dwc_ep.dma_addr = cfi->buf_in.addr;
  18974. + ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
  18975. + ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
  18976. + ep->dwc_ep.xfer_len = retval;
  18977. + ep->dwc_ep.xfer_count = 0;
  18978. + ep->dwc_ep.sent_zlp = 0;
  18979. + ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
  18980. +
  18981. + pcd->ep0_pending = 1;
  18982. + dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
  18983. + }
  18984. + retval = 0;
  18985. + break;
  18986. +
  18987. + case VEN_CORE_GET_FEATURE:
  18988. + CFI_INFO("VEN_CORE_GET_FEATURE\n");
  18989. + retval = cfi_get_feature_value(cfi->buf_in.buf, CFI_IN_BUF_LEN,
  18990. + pcd, ctrl);
  18991. + if (retval >= 0) {
  18992. + ep = &pcd->ep0;
  18993. +
  18994. + retval = min((uint16_t) retval, wLen);
  18995. + /* Transfer this buffer to the host through the EP0-IN EP */
  18996. + ep->dwc_ep.dma_addr = cfi->buf_in.addr;
  18997. + ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
  18998. + ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
  18999. + ep->dwc_ep.xfer_len = retval;
  19000. + ep->dwc_ep.xfer_count = 0;
  19001. + ep->dwc_ep.sent_zlp = 0;
  19002. + ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
  19003. +
  19004. + pcd->ep0_pending = 1;
  19005. + dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
  19006. + }
  19007. + CFI_INFO("VEN_CORE_GET_FEATURE=%d\n", retval);
  19008. + dump_msg(cfi->buf_in.buf, retval);
  19009. + break;
  19010. +
  19011. + case VEN_CORE_SET_FEATURE:
  19012. + CFI_INFO("VEN_CORE_SET_FEATURE\n");
  19013. + /* Set up an XFER to get the data stage of the control request,
  19014. + * which is the new value of the feature to be modified.
  19015. + */
  19016. + ep = &pcd->ep0;
  19017. + ep->dwc_ep.is_in = 0;
  19018. + ep->dwc_ep.dma_addr = cfi->buf_out.addr;
  19019. + ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
  19020. + ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
  19021. + ep->dwc_ep.xfer_len = wLen;
  19022. + ep->dwc_ep.xfer_count = 0;
  19023. + ep->dwc_ep.sent_zlp = 0;
  19024. + ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
  19025. +
  19026. + pcd->ep0_pending = 1;
  19027. + /* Read the control write's data stage */
  19028. + dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
  19029. + retval = 0;
  19030. + break;
  19031. +
  19032. + case VEN_CORE_RESET_FEATURES:
  19033. + CFI_INFO("VEN_CORE_RESET_FEATURES\n");
  19034. + cfi->need_gadget_att = 1;
  19035. + cfi->need_status_in_complete = 1;
  19036. + retval = cfi_preproc_reset(pcd, ctrl);
  19037. + CFI_INFO("VEN_CORE_RESET_FEATURES = (%d)\n", retval);
  19038. + break;
  19039. +
  19040. + case VEN_CORE_ACTIVATE_FEATURES:
  19041. + CFI_INFO("VEN_CORE_ACTIVATE_FEATURES\n");
  19042. + break;
  19043. +
  19044. + case VEN_CORE_READ_REGISTER:
  19045. + CFI_INFO("VEN_CORE_READ_REGISTER\n");
  19046. + /* wValue optionally contains the HI WORD of the register offset and
  19047. + * wIndex contains the LOW WORD of the register offset
  19048. + */
  19049. + if (wValue == 0) {
  19050. + /* @TODO - MAS - fix the access to the base field */
  19051. + regaddr = 0;
  19052. + //regaddr = (uint32_t) pcd->otg_dev->os_dep.base;
  19053. + //GET_CORE_IF(pcd)->co
  19054. + regaddr |= wIndex;
  19055. + } else {
  19056. + regaddr = (wValue << 16) | wIndex;
  19057. + }
  19058. +
  19059. + /* Read a 32-bit value of the memory at the regaddr */
  19060. + regval = DWC_READ_REG32((uint32_t *) regaddr);
  19061. +
  19062. + ep = &pcd->ep0;
  19063. + dwc_memcpy(cfi->buf_in.buf, &regval, sizeof(uint32_t));
  19064. + ep->dwc_ep.is_in = 1;
  19065. + ep->dwc_ep.dma_addr = cfi->buf_in.addr;
  19066. + ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf;
  19067. + ep->dwc_ep.xfer_buff = cfi->buf_in.buf;
  19068. + ep->dwc_ep.xfer_len = wLen;
  19069. + ep->dwc_ep.xfer_count = 0;
  19070. + ep->dwc_ep.sent_zlp = 0;
  19071. + ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
  19072. +
  19073. + pcd->ep0_pending = 1;
  19074. + dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
  19075. + cfi->need_gadget_att = 0;
  19076. + retval = 0;
  19077. + break;
  19078. +
  19079. + case VEN_CORE_WRITE_REGISTER:
  19080. + CFI_INFO("VEN_CORE_WRITE_REGISTER\n");
  19081. + /* Set up an XFER to get the data stage of the control request,
  19082. + * which is the new value of the register to be modified.
  19083. + */
  19084. + ep = &pcd->ep0;
  19085. + ep->dwc_ep.is_in = 0;
  19086. + ep->dwc_ep.dma_addr = cfi->buf_out.addr;
  19087. + ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf;
  19088. + ep->dwc_ep.xfer_buff = cfi->buf_out.buf;
  19089. + ep->dwc_ep.xfer_len = wLen;
  19090. + ep->dwc_ep.xfer_count = 0;
  19091. + ep->dwc_ep.sent_zlp = 0;
  19092. + ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
  19093. +
  19094. + pcd->ep0_pending = 1;
  19095. + /* Read the control write's data stage */
  19096. + dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep);
  19097. + retval = 0;
  19098. + break;
  19099. +
  19100. + default:
  19101. + retval = -DWC_E_NOT_SUPPORTED;
  19102. + break;
  19103. + }
  19104. +
  19105. + return retval;
  19106. +}
  19107. +
  19108. +/**
  19109. + * This function prepares the core features descriptors and copies its
  19110. + * raw representation into the buffer <buf>.
  19111. + *
  19112. + * The buffer structure is as follows:
  19113. + * all_features_header (8 bytes)
  19114. + * features_#1 (8 bytes + feature name string length)
  19115. + * features_#2 (8 bytes + feature name string length)
  19116. + * .....
  19117. + * features_#n - where n=the total count of feature descriptors
  19118. + */
  19119. +static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen)
  19120. +{
  19121. + cfi_feature_desc_header_t *prop_hdr = prop_descs;
  19122. + cfi_feature_desc_header_t *prop;
  19123. + cfi_all_features_header_t *all_props_hdr = &all_props_desc_header;
  19124. + cfi_all_features_header_t *tmp;
  19125. + uint8_t *tmpbuf = buf;
  19126. + const uint8_t *pname = NULL;
  19127. + int i, j, namelen = 0, totlen;
  19128. +
  19129. + /* Prepare and copy the core features into the buffer */
  19130. + CFI_INFO("%s:\n", __func__);
  19131. +
  19132. + tmp = (cfi_all_features_header_t *) tmpbuf;
  19133. + *tmp = *all_props_hdr;
  19134. + tmpbuf += CFI_ALL_FEATURES_HDR_LEN;
  19135. +
  19136. + j = sizeof(prop_descs) / sizeof(cfi_all_features_header_t);
  19137. + for (i = 0; i < j; i++, prop_hdr++) {
  19138. + pname = get_prop_name(prop_hdr->wFeatureID, &namelen);
  19139. + prop = (cfi_feature_desc_header_t *) tmpbuf;
  19140. + *prop = *prop_hdr;
  19141. +
  19142. + prop->bNameLen = namelen;
  19143. + prop->wLength =
  19144. + DWC_CONSTANT_CPU_TO_LE16(CFI_FEATURE_DESC_HDR_LEN +
  19145. + namelen);
  19146. +
  19147. + tmpbuf += CFI_FEATURE_DESC_HDR_LEN;
  19148. + dwc_memcpy(tmpbuf, pname, namelen);
  19149. + tmpbuf += namelen;
  19150. + }
  19151. +
  19152. + totlen = tmpbuf - buf;
  19153. +
  19154. + if (totlen > 0) {
  19155. + tmp = (cfi_all_features_header_t *) buf;
  19156. + tmp->wTotalLen = DWC_CONSTANT_CPU_TO_LE16(totlen);
  19157. + }
  19158. +
  19159. + return totlen;
  19160. +}
  19161. +
  19162. +/**
  19163. + * This function releases all the dynamic memory in the CFI object.
  19164. + */
  19165. +static void cfi_release(cfiobject_t * cfiobj)
  19166. +{
  19167. + cfi_ep_t *cfiep;
  19168. + dwc_list_link_t *tmp;
  19169. +
  19170. + CFI_INFO("%s\n", __func__);
  19171. +
  19172. + if (cfiobj->buf_in.buf) {
  19173. + DWC_DMA_FREE(CFI_IN_BUF_LEN, cfiobj->buf_in.buf,
  19174. + cfiobj->buf_in.addr);
  19175. + cfiobj->buf_in.buf = NULL;
  19176. + }
  19177. +
  19178. + if (cfiobj->buf_out.buf) {
  19179. + DWC_DMA_FREE(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf,
  19180. + cfiobj->buf_out.addr);
  19181. + cfiobj->buf_out.buf = NULL;
  19182. + }
  19183. +
  19184. + /* Free the Buffer Setup values for each EP */
  19185. + //list_for_each_entry(cfiep, &cfiobj->active_eps, lh) {
  19186. + DWC_LIST_FOREACH(tmp, &cfiobj->active_eps) {
  19187. + cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
  19188. + cfi_free_ep_bs_dyn_data(cfiep);
  19189. + }
  19190. +}
  19191. +
  19192. +/**
  19193. + * This function frees the dynamically allocated EP buffer setup data.
  19194. + */
  19195. +static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep)
  19196. +{
  19197. + if (cfiep->bm_sg) {
  19198. + DWC_FREE(cfiep->bm_sg);
  19199. + cfiep->bm_sg = NULL;
  19200. + }
  19201. +
  19202. + if (cfiep->bm_align) {
  19203. + DWC_FREE(cfiep->bm_align);
  19204. + cfiep->bm_align = NULL;
  19205. + }
  19206. +
  19207. + if (cfiep->bm_concat) {
  19208. + if (NULL != cfiep->bm_concat->wTxBytes) {
  19209. + DWC_FREE(cfiep->bm_concat->wTxBytes);
  19210. + cfiep->bm_concat->wTxBytes = NULL;
  19211. + }
  19212. + DWC_FREE(cfiep->bm_concat);
  19213. + cfiep->bm_concat = NULL;
  19214. + }
  19215. +}
  19216. +
  19217. +/**
  19218. + * This function initializes the default values of the features
  19219. + * for a specific endpoint and should be called only once when
  19220. + * the EP is enabled first time.
  19221. + */
  19222. +static int cfi_ep_init_defaults(struct dwc_otg_pcd *pcd, cfi_ep_t * cfiep)
  19223. +{
  19224. + int retval = 0;
  19225. +
  19226. + cfiep->bm_sg = DWC_ALLOC(sizeof(ddma_sg_buffer_setup_t));
  19227. + if (NULL == cfiep->bm_sg) {
  19228. + CFI_INFO("Failed to allocate memory for SG feature value\n");
  19229. + return -DWC_E_NO_MEMORY;
  19230. + }
  19231. + dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
  19232. +
  19233. + /* For the Concatenation feature's default value we do not allocate
  19234. + * memory for the wTxBytes field - it will be done in the set_feature_value
  19235. + * request handler.
  19236. + */
  19237. + cfiep->bm_concat = DWC_ALLOC(sizeof(ddma_concat_buffer_setup_t));
  19238. + if (NULL == cfiep->bm_concat) {
  19239. + CFI_INFO
  19240. + ("Failed to allocate memory for CONCATENATION feature value\n");
  19241. + DWC_FREE(cfiep->bm_sg);
  19242. + return -DWC_E_NO_MEMORY;
  19243. + }
  19244. + dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
  19245. +
  19246. + cfiep->bm_align = DWC_ALLOC(sizeof(ddma_align_buffer_setup_t));
  19247. + if (NULL == cfiep->bm_align) {
  19248. + CFI_INFO
  19249. + ("Failed to allocate memory for Alignment feature value\n");
  19250. + DWC_FREE(cfiep->bm_sg);
  19251. + DWC_FREE(cfiep->bm_concat);
  19252. + return -DWC_E_NO_MEMORY;
  19253. + }
  19254. + dwc_memset(cfiep->bm_align, 0, sizeof(ddma_align_buffer_setup_t));
  19255. +
  19256. + return retval;
  19257. +}
  19258. +
  19259. +/**
  19260. + * The callback function that notifies the CFI on the activation of
  19261. + * an endpoint in the PCD. The following steps are done in this function:
  19262. + *
  19263. + * Create a dynamically allocated cfi_ep_t object (a CFI wrapper to the PCD's
  19264. + * active endpoint)
  19265. + * Create MAX_DMA_DESCS_PER_EP count DMA Descriptors for the EP
  19266. + * Set the Buffer Mode to standard
  19267. + * Initialize the default values for all EP modes (SG, Circular, Concat, Align)
  19268. + * Add the cfi_ep_t object to the list of active endpoints in the CFI object
  19269. + */
  19270. +static int cfi_ep_enable(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
  19271. + struct dwc_otg_pcd_ep *ep)
  19272. +{
  19273. + cfi_ep_t *cfiep;
  19274. + int retval = -DWC_E_NOT_SUPPORTED;
  19275. +
  19276. + CFI_INFO("%s: epname=%s; epnum=0x%02x\n", __func__,
  19277. + "EP_" /*ep->ep.name */ , ep->desc->bEndpointAddress);
  19278. + /* MAS - Check whether this endpoint already is in the list */
  19279. + cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
  19280. +
  19281. + if (NULL == cfiep) {
  19282. + /* Allocate a cfi_ep_t object */
  19283. + cfiep = DWC_ALLOC(sizeof(cfi_ep_t));
  19284. + if (NULL == cfiep) {
  19285. + CFI_INFO
  19286. + ("Unable to allocate memory for <cfiep> in function %s\n",
  19287. + __func__);
  19288. + return -DWC_E_NO_MEMORY;
  19289. + }
  19290. + dwc_memset(cfiep, 0, sizeof(cfi_ep_t));
  19291. +
  19292. + /* Save the dwc_otg_pcd_ep pointer in the cfiep object */
  19293. + cfiep->ep = ep;
  19294. +
  19295. + /* Allocate the DMA Descriptors chain of MAX_DMA_DESCS_PER_EP count */
  19296. + ep->dwc_ep.descs =
  19297. + DWC_DMA_ALLOC(MAX_DMA_DESCS_PER_EP *
  19298. + sizeof(dwc_otg_dma_desc_t),
  19299. + &ep->dwc_ep.descs_dma_addr);
  19300. +
  19301. + if (NULL == ep->dwc_ep.descs) {
  19302. + DWC_FREE(cfiep);
  19303. + return -DWC_E_NO_MEMORY;
  19304. + }
  19305. +
  19306. + DWC_LIST_INIT(&cfiep->lh);
  19307. +
  19308. + /* Set the buffer mode to BM_STANDARD. It will be modified
  19309. + * when building descriptors for a specific buffer mode */
  19310. + ep->dwc_ep.buff_mode = BM_STANDARD;
  19311. +
  19312. + /* Create and initialize the default values for this EP's Buffer modes */
  19313. + if ((retval = cfi_ep_init_defaults(pcd, cfiep)) < 0)
  19314. + return retval;
  19315. +
  19316. + /* Add the cfi_ep_t object to the CFI object's list of active endpoints */
  19317. + DWC_LIST_INSERT_TAIL(&cfi->active_eps, &cfiep->lh);
  19318. + retval = 0;
  19319. + } else { /* The sought EP already is in the list */
  19320. + CFI_INFO("%s: The sought EP already is in the list\n",
  19321. + __func__);
  19322. + }
  19323. +
  19324. + return retval;
  19325. +}
  19326. +
  19327. +/**
  19328. + * This function is called when the data stage of a 3-stage Control Write request
  19329. + * is complete.
  19330. + *
  19331. + */
  19332. +static int cfi_ctrl_write_complete(struct cfiobject *cfi,
  19333. + struct dwc_otg_pcd *pcd)
  19334. +{
  19335. + uint32_t addr, reg_value;
  19336. + uint16_t wIndex, wValue;
  19337. + uint8_t bRequest;
  19338. + uint8_t *buf = cfi->buf_out.buf;
  19339. + //struct usb_ctrlrequest *ctrl_req = &cfi->ctrl_req_saved;
  19340. + struct cfi_usb_ctrlrequest *ctrl_req = &cfi->ctrl_req;
  19341. + int retval = -DWC_E_NOT_SUPPORTED;
  19342. +
  19343. + CFI_INFO("%s\n", __func__);
  19344. +
  19345. + bRequest = ctrl_req->bRequest;
  19346. + wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
  19347. + wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
  19348. +
  19349. + /*
  19350. + * Save the pointer to the data stage in the ctrl_req's <data> field.
  19351. + * The request should be already saved in the command stage by now.
  19352. + */
  19353. + ctrl_req->data = cfi->buf_out.buf;
  19354. + cfi->need_status_in_complete = 0;
  19355. + cfi->need_gadget_att = 0;
  19356. +
  19357. + switch (bRequest) {
  19358. + case VEN_CORE_WRITE_REGISTER:
  19359. + /* The buffer contains raw data of the new value for the register */
  19360. + reg_value = *((uint32_t *) buf);
  19361. + if (wValue == 0) {
  19362. + addr = 0;
  19363. + //addr = (uint32_t) pcd->otg_dev->os_dep.base;
  19364. + addr += wIndex;
  19365. + } else {
  19366. + addr = (wValue << 16) | wIndex;
  19367. + }
  19368. +
  19369. + //writel(reg_value, addr);
  19370. +
  19371. + retval = 0;
  19372. + cfi->need_status_in_complete = 1;
  19373. + break;
  19374. +
  19375. + case VEN_CORE_SET_FEATURE:
  19376. + /* The buffer contains raw data of the new value of the feature */
  19377. + retval = cfi_set_feature_value(pcd);
  19378. + if (retval < 0)
  19379. + return retval;
  19380. +
  19381. + cfi->need_status_in_complete = 1;
  19382. + break;
  19383. +
  19384. + default:
  19385. + break;
  19386. + }
  19387. +
  19388. + return retval;
  19389. +}
  19390. +
  19391. +/**
  19392. + * This function builds the DMA descriptors for the SG buffer mode.
  19393. + */
  19394. +static void cfi_build_sg_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
  19395. + dwc_otg_pcd_request_t * req)
  19396. +{
  19397. + struct dwc_otg_pcd_ep *ep = cfiep->ep;
  19398. + ddma_sg_buffer_setup_t *sgval = cfiep->bm_sg;
  19399. + struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
  19400. + struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
  19401. + dma_addr_t buff_addr = req->dma;
  19402. + int i;
  19403. + uint32_t txsize, off;
  19404. +
  19405. + txsize = sgval->wSize;
  19406. + off = sgval->bOffset;
  19407. +
  19408. +// CFI_INFO("%s: %s TXSIZE=0x%08x; OFFSET=0x%08x\n",
  19409. +// __func__, cfiep->ep->ep.name, txsize, off);
  19410. +
  19411. + for (i = 0; i < sgval->bCount; i++) {
  19412. + desc->status.b.bs = BS_HOST_BUSY;
  19413. + desc->buf = buff_addr;
  19414. + desc->status.b.l = 0;
  19415. + desc->status.b.ioc = 0;
  19416. + desc->status.b.sp = 0;
  19417. + desc->status.b.bytes = txsize;
  19418. + desc->status.b.bs = BS_HOST_READY;
  19419. +
  19420. + /* Set the next address of the buffer */
  19421. + buff_addr += txsize + off;
  19422. + desc_last = desc;
  19423. + desc++;
  19424. + }
  19425. +
  19426. + /* Set the last, ioc and sp bits on the Last DMA Descriptor */
  19427. + desc_last->status.b.l = 1;
  19428. + desc_last->status.b.ioc = 1;
  19429. + desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
  19430. + /* Save the last DMA descriptor pointer */
  19431. + cfiep->dma_desc_last = desc_last;
  19432. + cfiep->desc_count = sgval->bCount;
  19433. +}
  19434. +
  19435. +/**
  19436. + * This function builds the DMA descriptors for the Concatenation buffer mode.
  19437. + */
  19438. +static void cfi_build_concat_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
  19439. + dwc_otg_pcd_request_t * req)
  19440. +{
  19441. + struct dwc_otg_pcd_ep *ep = cfiep->ep;
  19442. + ddma_concat_buffer_setup_t *concatval = cfiep->bm_concat;
  19443. + struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
  19444. + struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs;
  19445. + dma_addr_t buff_addr = req->dma;
  19446. + int i;
  19447. + uint16_t *txsize;
  19448. +
  19449. + txsize = concatval->wTxBytes;
  19450. +
  19451. + for (i = 0; i < concatval->hdr.bDescCount; i++) {
  19452. + desc->buf = buff_addr;
  19453. + desc->status.b.bs = BS_HOST_BUSY;
  19454. + desc->status.b.l = 0;
  19455. + desc->status.b.ioc = 0;
  19456. + desc->status.b.sp = 0;
  19457. + desc->status.b.bytes = *txsize;
  19458. + desc->status.b.bs = BS_HOST_READY;
  19459. +
  19460. + txsize++;
  19461. + /* Set the next address of the buffer */
  19462. + buff_addr += UGETW(ep->desc->wMaxPacketSize);
  19463. + desc_last = desc;
  19464. + desc++;
  19465. + }
  19466. +
  19467. + /* Set the last, ioc and sp bits on the Last DMA Descriptor */
  19468. + desc_last->status.b.l = 1;
  19469. + desc_last->status.b.ioc = 1;
  19470. + desc_last->status.b.sp = ep->dwc_ep.sent_zlp;
  19471. + cfiep->dma_desc_last = desc_last;
  19472. + cfiep->desc_count = concatval->hdr.bDescCount;
  19473. +}
  19474. +
  19475. +/**
  19476. + * This function builds the DMA descriptors for the Circular buffer mode
  19477. + */
  19478. +static void cfi_build_circ_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
  19479. + dwc_otg_pcd_request_t * req)
  19480. +{
  19481. + /* @todo: MAS - add implementation when this feature needs to be tested */
  19482. +}
  19483. +
  19484. +/**
  19485. + * This function builds the DMA descriptors for the Alignment buffer mode
  19486. + */
  19487. +static void cfi_build_align_descs(struct cfiobject *cfi, cfi_ep_t * cfiep,
  19488. + dwc_otg_pcd_request_t * req)
  19489. +{
  19490. + struct dwc_otg_pcd_ep *ep = cfiep->ep;
  19491. + ddma_align_buffer_setup_t *alignval = cfiep->bm_align;
  19492. + struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs;
  19493. + dma_addr_t buff_addr = req->dma;
  19494. +
  19495. + desc->status.b.bs = BS_HOST_BUSY;
  19496. + desc->status.b.l = 1;
  19497. + desc->status.b.ioc = 1;
  19498. + desc->status.b.sp = ep->dwc_ep.sent_zlp;
  19499. + desc->status.b.bytes = req->length;
  19500. + /* Adjust the buffer alignment */
  19501. + desc->buf = (buff_addr + alignval->bAlign);
  19502. + desc->status.b.bs = BS_HOST_READY;
  19503. + cfiep->dma_desc_last = desc;
  19504. + cfiep->desc_count = 1;
  19505. +}
  19506. +
  19507. +/**
  19508. + * This function builds the DMA descriptors chain for different modes of the
  19509. + * buffer setup of an endpoint.
  19510. + */
  19511. +static void cfi_build_descriptors(struct cfiobject *cfi,
  19512. + struct dwc_otg_pcd *pcd,
  19513. + struct dwc_otg_pcd_ep *ep,
  19514. + dwc_otg_pcd_request_t * req)
  19515. +{
  19516. + cfi_ep_t *cfiep;
  19517. +
  19518. + /* Get the cfiep by the dwc_otg_pcd_ep */
  19519. + cfiep = get_cfi_ep_by_pcd_ep(cfi, ep);
  19520. + if (NULL == cfiep) {
  19521. + CFI_INFO("%s: Unable to find a matching active endpoint\n",
  19522. + __func__);
  19523. + return;
  19524. + }
  19525. +
  19526. + cfiep->xfer_len = req->length;
  19527. +
  19528. + /* Iterate through all the DMA descriptors */
  19529. + switch (cfiep->ep->dwc_ep.buff_mode) {
  19530. + case BM_SG:
  19531. + cfi_build_sg_descs(cfi, cfiep, req);
  19532. + break;
  19533. +
  19534. + case BM_CONCAT:
  19535. + cfi_build_concat_descs(cfi, cfiep, req);
  19536. + break;
  19537. +
  19538. + case BM_CIRCULAR:
  19539. + cfi_build_circ_descs(cfi, cfiep, req);
  19540. + break;
  19541. +
  19542. + case BM_ALIGN:
  19543. + cfi_build_align_descs(cfi, cfiep, req);
  19544. + break;
  19545. +
  19546. + default:
  19547. + break;
  19548. + }
  19549. +}
  19550. +
  19551. +/**
  19552. + * Allocate DMA buffer for different Buffer modes.
  19553. + */
  19554. +static void *cfi_ep_alloc_buf(struct cfiobject *cfi, struct dwc_otg_pcd *pcd,
  19555. + struct dwc_otg_pcd_ep *ep, dma_addr_t * dma,
  19556. + unsigned size, gfp_t flags)
  19557. +{
  19558. + return DWC_DMA_ALLOC(size, dma);
  19559. +}
  19560. +
  19561. +/**
  19562. + * This function initializes the CFI object.
  19563. + */
  19564. +int init_cfi(cfiobject_t * cfiobj)
  19565. +{
  19566. + CFI_INFO("%s\n", __func__);
  19567. +
  19568. + /* Allocate a buffer for IN XFERs */
  19569. + cfiobj->buf_in.buf =
  19570. + DWC_DMA_ALLOC(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr);
  19571. + if (NULL == cfiobj->buf_in.buf) {
  19572. + CFI_INFO("Unable to allocate buffer for INs\n");
  19573. + return -DWC_E_NO_MEMORY;
  19574. + }
  19575. +
  19576. + /* Allocate a buffer for OUT XFERs */
  19577. + cfiobj->buf_out.buf =
  19578. + DWC_DMA_ALLOC(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr);
  19579. + if (NULL == cfiobj->buf_out.buf) {
  19580. + CFI_INFO("Unable to allocate buffer for OUT\n");
  19581. + return -DWC_E_NO_MEMORY;
  19582. + }
  19583. +
  19584. + /* Initialize the callback function pointers */
  19585. + cfiobj->ops.release = cfi_release;
  19586. + cfiobj->ops.ep_enable = cfi_ep_enable;
  19587. + cfiobj->ops.ctrl_write_complete = cfi_ctrl_write_complete;
  19588. + cfiobj->ops.build_descriptors = cfi_build_descriptors;
  19589. + cfiobj->ops.ep_alloc_buf = cfi_ep_alloc_buf;
  19590. +
  19591. + /* Initialize the list of active endpoints in the CFI object */
  19592. + DWC_LIST_INIT(&cfiobj->active_eps);
  19593. +
  19594. + return 0;
  19595. +}
  19596. +
  19597. +/**
  19598. + * This function reads the required feature's current value into the buffer
  19599. + *
  19600. + * @retval: Returns negative as error, or the data length of the feature
  19601. + */
  19602. +static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen,
  19603. + struct dwc_otg_pcd *pcd,
  19604. + struct cfi_usb_ctrlrequest *ctrl_req)
  19605. +{
  19606. + int retval = -DWC_E_NOT_SUPPORTED;
  19607. + struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd);
  19608. + uint16_t dfifo, rxfifo, txfifo;
  19609. +
  19610. + switch (ctrl_req->wIndex) {
  19611. + /* Whether the DDMA is enabled or not */
  19612. + case FT_ID_DMA_MODE:
  19613. + *buf = (coreif->dma_enable && coreif->dma_desc_enable) ? 1 : 0;
  19614. + retval = 1;
  19615. + break;
  19616. +
  19617. + case FT_ID_DMA_BUFFER_SETUP:
  19618. + retval = cfi_ep_get_sg_val(buf, pcd, ctrl_req);
  19619. + break;
  19620. +
  19621. + case FT_ID_DMA_BUFF_ALIGN:
  19622. + retval = cfi_ep_get_align_val(buf, pcd, ctrl_req);
  19623. + break;
  19624. +
  19625. + case FT_ID_DMA_CONCAT_SETUP:
  19626. + retval = cfi_ep_get_concat_val(buf, pcd, ctrl_req);
  19627. + break;
  19628. +
  19629. + case FT_ID_DMA_CIRCULAR:
  19630. + CFI_INFO("GetFeature value (FT_ID_DMA_CIRCULAR)\n");
  19631. + break;
  19632. +
  19633. + case FT_ID_THRESHOLD_SETUP:
  19634. + CFI_INFO("GetFeature value (FT_ID_THRESHOLD_SETUP)\n");
  19635. + break;
  19636. +
  19637. + case FT_ID_DFIFO_DEPTH:
  19638. + dfifo = get_dfifo_size(coreif);
  19639. + *((uint16_t *) buf) = dfifo;
  19640. + retval = sizeof(uint16_t);
  19641. + break;
  19642. +
  19643. + case FT_ID_TX_FIFO_DEPTH:
  19644. + retval = get_txfifo_size(pcd, ctrl_req->wValue);
  19645. + if (retval >= 0) {
  19646. + txfifo = retval;
  19647. + *((uint16_t *) buf) = txfifo;
  19648. + retval = sizeof(uint16_t);
  19649. + }
  19650. + break;
  19651. +
  19652. + case FT_ID_RX_FIFO_DEPTH:
  19653. + retval = get_rxfifo_size(coreif, ctrl_req->wValue);
  19654. + if (retval >= 0) {
  19655. + rxfifo = retval;
  19656. + *((uint16_t *) buf) = rxfifo;
  19657. + retval = sizeof(uint16_t);
  19658. + }
  19659. + break;
  19660. + }
  19661. +
  19662. + return retval;
  19663. +}
  19664. +
  19665. +/**
  19666. + * This function resets the SG for the specified EP to its default value
  19667. + */
  19668. +static int cfi_reset_sg_val(cfi_ep_t * cfiep)
  19669. +{
  19670. + dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
  19671. + return 0;
  19672. +}
  19673. +
  19674. +/**
  19675. + * This function resets the Alignment for the specified EP to its default value
  19676. + */
  19677. +static int cfi_reset_align_val(cfi_ep_t * cfiep)
  19678. +{
  19679. + dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t));
  19680. + return 0;
  19681. +}
  19682. +
  19683. +/**
  19684. + * This function resets the Concatenation for the specified EP to its default value
  19685. + * This function will also set the value of the wTxBytes field to NULL after
  19686. + * freeing the memory previously allocated for this field.
  19687. + */
  19688. +static int cfi_reset_concat_val(cfi_ep_t * cfiep)
  19689. +{
  19690. + /* First we need to free the wTxBytes field */
  19691. + if (cfiep->bm_concat->wTxBytes) {
  19692. + DWC_FREE(cfiep->bm_concat->wTxBytes);
  19693. + cfiep->bm_concat->wTxBytes = NULL;
  19694. + }
  19695. +
  19696. + dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t));
  19697. + return 0;
  19698. +}
  19699. +
  19700. +/**
  19701. + * This function resets all the buffer setups of the specified endpoint
  19702. + */
  19703. +static int cfi_ep_reset_all_setup_vals(cfi_ep_t * cfiep)
  19704. +{
  19705. + cfi_reset_sg_val(cfiep);
  19706. + cfi_reset_align_val(cfiep);
  19707. + cfi_reset_concat_val(cfiep);
  19708. + return 0;
  19709. +}
  19710. +
  19711. +static int cfi_handle_reset_fifo_val(struct dwc_otg_pcd *pcd, uint8_t ep_addr,
  19712. + uint8_t rx_rst, uint8_t tx_rst)
  19713. +{
  19714. + int retval = -DWC_E_INVALID;
  19715. + uint16_t tx_siz[15];
  19716. + uint16_t rx_siz = 0;
  19717. + dwc_otg_pcd_ep_t *ep = NULL;
  19718. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  19719. + dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
  19720. +
  19721. + if (rx_rst) {
  19722. + rx_siz = params->dev_rx_fifo_size;
  19723. + params->dev_rx_fifo_size = GET_CORE_IF(pcd)->init_rxfsiz;
  19724. + }
  19725. +
  19726. + if (tx_rst) {
  19727. + if (ep_addr == 0) {
  19728. + int i;
  19729. +
  19730. + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
  19731. + tx_siz[i] =
  19732. + core_if->core_params->dev_tx_fifo_size[i];
  19733. + core_if->core_params->dev_tx_fifo_size[i] =
  19734. + core_if->init_txfsiz[i];
  19735. + }
  19736. + } else {
  19737. +
  19738. + ep = get_ep_by_addr(pcd, ep_addr);
  19739. +
  19740. + if (NULL == ep) {
  19741. + CFI_INFO
  19742. + ("%s: Unable to get the endpoint addr=0x%02x\n",
  19743. + __func__, ep_addr);
  19744. + return -DWC_E_INVALID;
  19745. + }
  19746. +
  19747. + tx_siz[0] =
  19748. + params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num -
  19749. + 1];
  19750. + params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] =
  19751. + GET_CORE_IF(pcd)->init_txfsiz[ep->
  19752. + dwc_ep.tx_fifo_num -
  19753. + 1];
  19754. + }
  19755. + }
  19756. +
  19757. + if (resize_fifos(GET_CORE_IF(pcd))) {
  19758. + retval = 0;
  19759. + } else {
  19760. + CFI_INFO
  19761. + ("%s: Error resetting the feature Reset All(FIFO size)\n",
  19762. + __func__);
  19763. + if (rx_rst) {
  19764. + params->dev_rx_fifo_size = rx_siz;
  19765. + }
  19766. +
  19767. + if (tx_rst) {
  19768. + if (ep_addr == 0) {
  19769. + int i;
  19770. + for (i = 0; i < core_if->hwcfg4.b.num_in_eps;
  19771. + i++) {
  19772. + core_if->
  19773. + core_params->dev_tx_fifo_size[i] =
  19774. + tx_siz[i];
  19775. + }
  19776. + } else {
  19777. + params->dev_tx_fifo_size[ep->
  19778. + dwc_ep.tx_fifo_num -
  19779. + 1] = tx_siz[0];
  19780. + }
  19781. + }
  19782. + retval = -DWC_E_INVALID;
  19783. + }
  19784. + return retval;
  19785. +}
  19786. +
  19787. +static int cfi_handle_reset_all(struct dwc_otg_pcd *pcd, uint8_t addr)
  19788. +{
  19789. + int retval = 0;
  19790. + cfi_ep_t *cfiep;
  19791. + cfiobject_t *cfi = pcd->cfi;
  19792. + dwc_list_link_t *tmp;
  19793. +
  19794. + retval = cfi_handle_reset_fifo_val(pcd, addr, 1, 1);
  19795. + if (retval < 0) {
  19796. + return retval;
  19797. + }
  19798. +
  19799. + /* If the EP address is known then reset the features for only that EP */
  19800. + if (addr) {
  19801. + cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
  19802. + if (NULL == cfiep) {
  19803. + CFI_INFO("%s: Error getting the EP address 0x%02x\n",
  19804. + __func__, addr);
  19805. + return -DWC_E_INVALID;
  19806. + }
  19807. + retval = cfi_ep_reset_all_setup_vals(cfiep);
  19808. + cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
  19809. + }
  19810. + /* Otherwise (wValue == 0), reset all features of all EP's */
  19811. + else {
  19812. + /* Traverse all the active EP's and reset the feature(s) value(s) */
  19813. + //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
  19814. + DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
  19815. + cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
  19816. + retval = cfi_ep_reset_all_setup_vals(cfiep);
  19817. + cfiep->ep->dwc_ep.buff_mode = BM_STANDARD;
  19818. + if (retval < 0) {
  19819. + CFI_INFO
  19820. + ("%s: Error resetting the feature Reset All\n",
  19821. + __func__);
  19822. + return retval;
  19823. + }
  19824. + }
  19825. + }
  19826. + return retval;
  19827. +}
  19828. +
  19829. +static int cfi_handle_reset_dma_buff_setup(struct dwc_otg_pcd *pcd,
  19830. + uint8_t addr)
  19831. +{
  19832. + int retval = 0;
  19833. + cfi_ep_t *cfiep;
  19834. + cfiobject_t *cfi = pcd->cfi;
  19835. + dwc_list_link_t *tmp;
  19836. +
  19837. + /* If the EP address is known then reset the features for only that EP */
  19838. + if (addr) {
  19839. + cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
  19840. + if (NULL == cfiep) {
  19841. + CFI_INFO("%s: Error getting the EP address 0x%02x\n",
  19842. + __func__, addr);
  19843. + return -DWC_E_INVALID;
  19844. + }
  19845. + retval = cfi_reset_sg_val(cfiep);
  19846. + }
  19847. + /* Otherwise (wValue == 0), reset all features of all EP's */
  19848. + else {
  19849. + /* Traverse all the active EP's and reset the feature(s) value(s) */
  19850. + //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
  19851. + DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
  19852. + cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
  19853. + retval = cfi_reset_sg_val(cfiep);
  19854. + if (retval < 0) {
  19855. + CFI_INFO
  19856. + ("%s: Error resetting the feature Buffer Setup\n",
  19857. + __func__);
  19858. + return retval;
  19859. + }
  19860. + }
  19861. + }
  19862. + return retval;
  19863. +}
  19864. +
  19865. +static int cfi_handle_reset_concat_val(struct dwc_otg_pcd *pcd, uint8_t addr)
  19866. +{
  19867. + int retval = 0;
  19868. + cfi_ep_t *cfiep;
  19869. + cfiobject_t *cfi = pcd->cfi;
  19870. + dwc_list_link_t *tmp;
  19871. +
  19872. + /* If the EP address is known then reset the features for only that EP */
  19873. + if (addr) {
  19874. + cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
  19875. + if (NULL == cfiep) {
  19876. + CFI_INFO("%s: Error getting the EP address 0x%02x\n",
  19877. + __func__, addr);
  19878. + return -DWC_E_INVALID;
  19879. + }
  19880. + retval = cfi_reset_concat_val(cfiep);
  19881. + }
  19882. + /* Otherwise (wValue == 0), reset all features of all EP's */
  19883. + else {
  19884. + /* Traverse all the active EP's and reset the feature(s) value(s) */
  19885. + //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
  19886. + DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
  19887. + cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
  19888. + retval = cfi_reset_concat_val(cfiep);
  19889. + if (retval < 0) {
  19890. + CFI_INFO
  19891. + ("%s: Error resetting the feature Concatenation Value\n",
  19892. + __func__);
  19893. + return retval;
  19894. + }
  19895. + }
  19896. + }
  19897. + return retval;
  19898. +}
  19899. +
  19900. +static int cfi_handle_reset_align_val(struct dwc_otg_pcd *pcd, uint8_t addr)
  19901. +{
  19902. + int retval = 0;
  19903. + cfi_ep_t *cfiep;
  19904. + cfiobject_t *cfi = pcd->cfi;
  19905. + dwc_list_link_t *tmp;
  19906. +
  19907. + /* If the EP address is known then reset the features for only that EP */
  19908. + if (addr) {
  19909. + cfiep = get_cfi_ep_by_addr(pcd->cfi, addr);
  19910. + if (NULL == cfiep) {
  19911. + CFI_INFO("%s: Error getting the EP address 0x%02x\n",
  19912. + __func__, addr);
  19913. + return -DWC_E_INVALID;
  19914. + }
  19915. + retval = cfi_reset_align_val(cfiep);
  19916. + }
  19917. + /* Otherwise (wValue == 0), reset all features of all EP's */
  19918. + else {
  19919. + /* Traverse all the active EP's and reset the feature(s) value(s) */
  19920. + //list_for_each_entry(cfiep, &cfi->active_eps, lh) {
  19921. + DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
  19922. + cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
  19923. + retval = cfi_reset_align_val(cfiep);
  19924. + if (retval < 0) {
  19925. + CFI_INFO
  19926. + ("%s: Error resetting the feature Aliignment Value\n",
  19927. + __func__);
  19928. + return retval;
  19929. + }
  19930. + }
  19931. + }
  19932. + return retval;
  19933. +
  19934. +}
  19935. +
  19936. +static int cfi_preproc_reset(struct dwc_otg_pcd *pcd,
  19937. + struct cfi_usb_ctrlrequest *req)
  19938. +{
  19939. + int retval = 0;
  19940. +
  19941. + switch (req->wIndex) {
  19942. + case 0:
  19943. + /* Reset all features */
  19944. + retval = cfi_handle_reset_all(pcd, req->wValue & 0xff);
  19945. + break;
  19946. +
  19947. + case FT_ID_DMA_BUFFER_SETUP:
  19948. + /* Reset the SG buffer setup */
  19949. + retval =
  19950. + cfi_handle_reset_dma_buff_setup(pcd, req->wValue & 0xff);
  19951. + break;
  19952. +
  19953. + case FT_ID_DMA_CONCAT_SETUP:
  19954. + /* Reset the Concatenation buffer setup */
  19955. + retval = cfi_handle_reset_concat_val(pcd, req->wValue & 0xff);
  19956. + break;
  19957. +
  19958. + case FT_ID_DMA_BUFF_ALIGN:
  19959. + /* Reset the Alignment buffer setup */
  19960. + retval = cfi_handle_reset_align_val(pcd, req->wValue & 0xff);
  19961. + break;
  19962. +
  19963. + case FT_ID_TX_FIFO_DEPTH:
  19964. + retval =
  19965. + cfi_handle_reset_fifo_val(pcd, req->wValue & 0xff, 0, 1);
  19966. + pcd->cfi->need_gadget_att = 0;
  19967. + break;
  19968. +
  19969. + case FT_ID_RX_FIFO_DEPTH:
  19970. + retval = cfi_handle_reset_fifo_val(pcd, 0, 1, 0);
  19971. + pcd->cfi->need_gadget_att = 0;
  19972. + break;
  19973. + default:
  19974. + break;
  19975. + }
  19976. + return retval;
  19977. +}
  19978. +
  19979. +/**
  19980. + * This function sets a new value for the SG buffer setup.
  19981. + */
  19982. +static int cfi_ep_set_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
  19983. +{
  19984. + uint8_t inaddr, outaddr;
  19985. + cfi_ep_t *epin, *epout;
  19986. + ddma_sg_buffer_setup_t *psgval;
  19987. + uint32_t desccount, size;
  19988. +
  19989. + CFI_INFO("%s\n", __func__);
  19990. +
  19991. + psgval = (ddma_sg_buffer_setup_t *) buf;
  19992. + desccount = (uint32_t) psgval->bCount;
  19993. + size = (uint32_t) psgval->wSize;
  19994. +
  19995. + /* Check the DMA descriptor count */
  19996. + if ((desccount > MAX_DMA_DESCS_PER_EP) || (desccount == 0)) {
  19997. + CFI_INFO
  19998. + ("%s: The count of DMA Descriptors should be between 1 and %d\n",
  19999. + __func__, MAX_DMA_DESCS_PER_EP);
  20000. + return -DWC_E_INVALID;
  20001. + }
  20002. +
  20003. + /* Check the DMA descriptor count */
  20004. +
  20005. + if (size == 0) {
  20006. +
  20007. + CFI_INFO("%s: The transfer size should be at least 1 byte\n",
  20008. + __func__);
  20009. +
  20010. + return -DWC_E_INVALID;
  20011. +
  20012. + }
  20013. +
  20014. + inaddr = psgval->bInEndpointAddress;
  20015. + outaddr = psgval->bOutEndpointAddress;
  20016. +
  20017. + epin = get_cfi_ep_by_addr(pcd->cfi, inaddr);
  20018. + epout = get_cfi_ep_by_addr(pcd->cfi, outaddr);
  20019. +
  20020. + if (NULL == epin || NULL == epout) {
  20021. + CFI_INFO
  20022. + ("%s: Unable to get the endpoints inaddr=0x%02x outaddr=0x%02x\n",
  20023. + __func__, inaddr, outaddr);
  20024. + return -DWC_E_INVALID;
  20025. + }
  20026. +
  20027. + epin->ep->dwc_ep.buff_mode = BM_SG;
  20028. + dwc_memcpy(epin->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
  20029. +
  20030. + epout->ep->dwc_ep.buff_mode = BM_SG;
  20031. + dwc_memcpy(epout->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t));
  20032. +
  20033. + return 0;
  20034. +}
  20035. +
  20036. +/**
  20037. + * This function sets a new value for the buffer Alignment setup.
  20038. + */
  20039. +static int cfi_ep_set_alignment_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
  20040. +{
  20041. + cfi_ep_t *ep;
  20042. + uint8_t addr;
  20043. + ddma_align_buffer_setup_t *palignval;
  20044. +
  20045. + palignval = (ddma_align_buffer_setup_t *) buf;
  20046. + addr = palignval->bEndpointAddress;
  20047. +
  20048. + ep = get_cfi_ep_by_addr(pcd->cfi, addr);
  20049. +
  20050. + if (NULL == ep) {
  20051. + CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
  20052. + __func__, addr);
  20053. + return -DWC_E_INVALID;
  20054. + }
  20055. +
  20056. + ep->ep->dwc_ep.buff_mode = BM_ALIGN;
  20057. + dwc_memcpy(ep->bm_align, palignval, sizeof(ddma_align_buffer_setup_t));
  20058. +
  20059. + return 0;
  20060. +}
  20061. +
  20062. +/**
  20063. + * This function sets a new value for the Concatenation buffer setup.
  20064. + */
  20065. +static int cfi_ep_set_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd)
  20066. +{
  20067. + uint8_t addr;
  20068. + cfi_ep_t *ep;
  20069. + struct _ddma_concat_buffer_setup_hdr *pConcatValHdr;
  20070. + uint16_t *pVals;
  20071. + uint32_t desccount;
  20072. + int i;
  20073. + uint16_t mps;
  20074. +
  20075. + pConcatValHdr = (struct _ddma_concat_buffer_setup_hdr *)buf;
  20076. + desccount = (uint32_t) pConcatValHdr->bDescCount;
  20077. + pVals = (uint16_t *) (buf + BS_CONCAT_VAL_HDR_LEN);
  20078. +
  20079. + /* Check the DMA descriptor count */
  20080. + if (desccount > MAX_DMA_DESCS_PER_EP) {
  20081. + CFI_INFO("%s: Maximum DMA Descriptor count should be %d\n",
  20082. + __func__, MAX_DMA_DESCS_PER_EP);
  20083. + return -DWC_E_INVALID;
  20084. + }
  20085. +
  20086. + addr = pConcatValHdr->bEndpointAddress;
  20087. + ep = get_cfi_ep_by_addr(pcd->cfi, addr);
  20088. + if (NULL == ep) {
  20089. + CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
  20090. + __func__, addr);
  20091. + return -DWC_E_INVALID;
  20092. + }
  20093. +
  20094. + mps = UGETW(ep->ep->desc->wMaxPacketSize);
  20095. +
  20096. +#if 0
  20097. + for (i = 0; i < desccount; i++) {
  20098. + CFI_INFO("%s: wTxSize[%d]=0x%04x\n", __func__, i, pVals[i]);
  20099. + }
  20100. + CFI_INFO("%s: epname=%s; mps=%d\n", __func__, ep->ep->ep.name, mps);
  20101. +#endif
  20102. +
  20103. + /* Check the wTxSizes to be less than or equal to the mps */
  20104. + for (i = 0; i < desccount; i++) {
  20105. + if (pVals[i] > mps) {
  20106. + CFI_INFO
  20107. + ("%s: ERROR - the wTxSize[%d] should be <= MPS (wTxSize=%d)\n",
  20108. + __func__, i, pVals[i]);
  20109. + return -DWC_E_INVALID;
  20110. + }
  20111. + }
  20112. +
  20113. + ep->ep->dwc_ep.buff_mode = BM_CONCAT;
  20114. + dwc_memcpy(ep->bm_concat, pConcatValHdr, BS_CONCAT_VAL_HDR_LEN);
  20115. +
  20116. + /* Free the previously allocated storage for the wTxBytes */
  20117. + if (ep->bm_concat->wTxBytes) {
  20118. + DWC_FREE(ep->bm_concat->wTxBytes);
  20119. + }
  20120. +
  20121. + /* Allocate a new storage for the wTxBytes field */
  20122. + ep->bm_concat->wTxBytes =
  20123. + DWC_ALLOC(sizeof(uint16_t) * pConcatValHdr->bDescCount);
  20124. + if (NULL == ep->bm_concat->wTxBytes) {
  20125. + CFI_INFO("%s: Unable to allocate memory\n", __func__);
  20126. + return -DWC_E_NO_MEMORY;
  20127. + }
  20128. +
  20129. + /* Copy the new values into the wTxBytes filed */
  20130. + dwc_memcpy(ep->bm_concat->wTxBytes, buf + BS_CONCAT_VAL_HDR_LEN,
  20131. + sizeof(uint16_t) * pConcatValHdr->bDescCount);
  20132. +
  20133. + return 0;
  20134. +}
  20135. +
  20136. +/**
  20137. + * This function calculates the total of all FIFO sizes
  20138. + *
  20139. + * @param core_if Programming view of DWC_otg controller
  20140. + *
  20141. + * @return The total of data FIFO sizes.
  20142. + *
  20143. + */
  20144. +static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if)
  20145. +{
  20146. + dwc_otg_core_params_t *params = core_if->core_params;
  20147. + uint16_t dfifo_total = 0;
  20148. + int i;
  20149. +
  20150. + /* The shared RxFIFO size */
  20151. + dfifo_total =
  20152. + params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
  20153. +
  20154. + /* Add up each TxFIFO size to the total */
  20155. + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
  20156. + dfifo_total += params->dev_tx_fifo_size[i];
  20157. + }
  20158. +
  20159. + return dfifo_total;
  20160. +}
  20161. +
  20162. +/**
  20163. + * This function returns Rx FIFO size
  20164. + *
  20165. + * @param core_if Programming view of DWC_otg controller
  20166. + *
  20167. + * @return The total of data FIFO sizes.
  20168. + *
  20169. + */
  20170. +static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue)
  20171. +{
  20172. + switch (wValue >> 8) {
  20173. + case 0:
  20174. + return (core_if->pwron_rxfsiz <
  20175. + 32768) ? core_if->pwron_rxfsiz : 32768;
  20176. + break;
  20177. + case 1:
  20178. + return core_if->core_params->dev_rx_fifo_size;
  20179. + break;
  20180. + default:
  20181. + return -DWC_E_INVALID;
  20182. + break;
  20183. + }
  20184. +}
  20185. +
  20186. +/**
  20187. + * This function returns Tx FIFO size for IN EP
  20188. + *
  20189. + * @param core_if Programming view of DWC_otg controller
  20190. + *
  20191. + * @return The total of data FIFO sizes.
  20192. + *
  20193. + */
  20194. +static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue)
  20195. +{
  20196. + dwc_otg_pcd_ep_t *ep;
  20197. +
  20198. + ep = get_ep_by_addr(pcd, wValue & 0xff);
  20199. +
  20200. + if (NULL == ep) {
  20201. + CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
  20202. + __func__, wValue & 0xff);
  20203. + return -DWC_E_INVALID;
  20204. + }
  20205. +
  20206. + if (!ep->dwc_ep.is_in) {
  20207. + CFI_INFO
  20208. + ("%s: No Tx FIFO assingned to the Out endpoint addr=0x%02x\n",
  20209. + __func__, wValue & 0xff);
  20210. + return -DWC_E_INVALID;
  20211. + }
  20212. +
  20213. + switch (wValue >> 8) {
  20214. + case 0:
  20215. + return (GET_CORE_IF(pcd)->pwron_txfsiz
  20216. + [ep->dwc_ep.tx_fifo_num - 1] <
  20217. + 768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep->
  20218. + dwc_ep.tx_fifo_num
  20219. + - 1] : 32768;
  20220. + break;
  20221. + case 1:
  20222. + return GET_CORE_IF(pcd)->core_params->
  20223. + dev_tx_fifo_size[ep->dwc_ep.num - 1];
  20224. + break;
  20225. + default:
  20226. + return -DWC_E_INVALID;
  20227. + break;
  20228. + }
  20229. +}
  20230. +
  20231. +/**
  20232. + * This function checks if the submitted combination of
  20233. + * device mode FIFO sizes is possible or not.
  20234. + *
  20235. + * @param core_if Programming view of DWC_otg controller
  20236. + *
  20237. + * @return 1 if possible, 0 otherwise.
  20238. + *
  20239. + */
  20240. +static uint8_t check_fifo_sizes(dwc_otg_core_if_t * core_if)
  20241. +{
  20242. + uint16_t dfifo_actual = 0;
  20243. + dwc_otg_core_params_t *params = core_if->core_params;
  20244. + uint16_t start_addr = 0;
  20245. + int i;
  20246. +
  20247. + dfifo_actual =
  20248. + params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size;
  20249. +
  20250. + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
  20251. + dfifo_actual += params->dev_tx_fifo_size[i];
  20252. + }
  20253. +
  20254. + if (dfifo_actual > core_if->total_fifo_size) {
  20255. + return 0;
  20256. + }
  20257. +
  20258. + if (params->dev_rx_fifo_size > 32768 || params->dev_rx_fifo_size < 16)
  20259. + return 0;
  20260. +
  20261. + if (params->dev_nperio_tx_fifo_size > 32768
  20262. + || params->dev_nperio_tx_fifo_size < 16)
  20263. + return 0;
  20264. +
  20265. + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
  20266. +
  20267. + if (params->dev_tx_fifo_size[i] > 768
  20268. + || params->dev_tx_fifo_size[i] < 4)
  20269. + return 0;
  20270. + }
  20271. +
  20272. + if (params->dev_rx_fifo_size > core_if->pwron_rxfsiz)
  20273. + return 0;
  20274. + start_addr = params->dev_rx_fifo_size;
  20275. +
  20276. + if (params->dev_nperio_tx_fifo_size > core_if->pwron_gnptxfsiz)
  20277. + return 0;
  20278. + start_addr += params->dev_nperio_tx_fifo_size;
  20279. +
  20280. + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
  20281. +
  20282. + if (params->dev_tx_fifo_size[i] > core_if->pwron_txfsiz[i])
  20283. + return 0;
  20284. + start_addr += params->dev_tx_fifo_size[i];
  20285. + }
  20286. +
  20287. + return 1;
  20288. +}
  20289. +
  20290. +/**
  20291. + * This function resizes Device mode FIFOs
  20292. + *
  20293. + * @param core_if Programming view of DWC_otg controller
  20294. + *
  20295. + * @return 1 if successful, 0 otherwise
  20296. + *
  20297. + */
  20298. +static uint8_t resize_fifos(dwc_otg_core_if_t * core_if)
  20299. +{
  20300. + int i = 0;
  20301. + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
  20302. + dwc_otg_core_params_t *params = core_if->core_params;
  20303. + uint32_t rx_fifo_size;
  20304. + fifosize_data_t nptxfifosize;
  20305. + fifosize_data_t txfifosize[15];
  20306. +
  20307. + uint32_t rx_fsz_bak;
  20308. + uint32_t nptxfsz_bak;
  20309. + uint32_t txfsz_bak[15];
  20310. +
  20311. + uint16_t start_address;
  20312. + uint8_t retval = 1;
  20313. +
  20314. + if (!check_fifo_sizes(core_if)) {
  20315. + return 0;
  20316. + }
  20317. +
  20318. + /* Configure data FIFO sizes */
  20319. + if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
  20320. + rx_fsz_bak = DWC_READ_REG32(&global_regs->grxfsiz);
  20321. + rx_fifo_size = params->dev_rx_fifo_size;
  20322. + DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size);
  20323. +
  20324. + /*
  20325. + * Tx FIFOs These FIFOs are numbered from 1 to 15.
  20326. + * Indexes of the FIFO size module parameters in the
  20327. + * dev_tx_fifo_size array and the FIFO size registers in
  20328. + * the dtxfsiz array run from 0 to 14.
  20329. + */
  20330. +
  20331. + /* Non-periodic Tx FIFO */
  20332. + nptxfsz_bak = DWC_READ_REG32(&global_regs->gnptxfsiz);
  20333. + nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
  20334. + start_address = params->dev_rx_fifo_size;
  20335. + nptxfifosize.b.startaddr = start_address;
  20336. +
  20337. + DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32);
  20338. +
  20339. + start_address += nptxfifosize.b.depth;
  20340. +
  20341. + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
  20342. + txfsz_bak[i] = DWC_READ_REG32(&global_regs->dtxfsiz[i]);
  20343. +
  20344. + txfifosize[i].b.depth = params->dev_tx_fifo_size[i];
  20345. + txfifosize[i].b.startaddr = start_address;
  20346. + DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
  20347. + txfifosize[i].d32);
  20348. +
  20349. + start_address += txfifosize[i].b.depth;
  20350. + }
  20351. +
  20352. + /** Check if register values are set correctly */
  20353. + if (rx_fifo_size != DWC_READ_REG32(&global_regs->grxfsiz)) {
  20354. + retval = 0;
  20355. + }
  20356. +
  20357. + if (nptxfifosize.d32 != DWC_READ_REG32(&global_regs->gnptxfsiz)) {
  20358. + retval = 0;
  20359. + }
  20360. +
  20361. + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
  20362. + if (txfifosize[i].d32 !=
  20363. + DWC_READ_REG32(&global_regs->dtxfsiz[i])) {
  20364. + retval = 0;
  20365. + }
  20366. + }
  20367. +
  20368. + /** If register values are not set correctly, reset old values */
  20369. + if (retval == 0) {
  20370. + DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fsz_bak);
  20371. +
  20372. + /* Non-periodic Tx FIFO */
  20373. + DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfsz_bak);
  20374. +
  20375. + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
  20376. + DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
  20377. + txfsz_bak[i]);
  20378. + }
  20379. + }
  20380. + } else {
  20381. + return 0;
  20382. + }
  20383. +
  20384. + /* Flush the FIFOs */
  20385. + dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */
  20386. + dwc_otg_flush_rx_fifo(core_if);
  20387. +
  20388. + return retval;
  20389. +}
  20390. +
  20391. +/**
  20392. + * This function sets a new value for the buffer Alignment setup.
  20393. + */
  20394. +static int cfi_ep_set_tx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)
  20395. +{
  20396. + int retval;
  20397. + uint32_t fsiz;
  20398. + uint16_t size;
  20399. + uint16_t ep_addr;
  20400. + dwc_otg_pcd_ep_t *ep;
  20401. + dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
  20402. + tx_fifo_size_setup_t *ptxfifoval;
  20403. +
  20404. + ptxfifoval = (tx_fifo_size_setup_t *) buf;
  20405. + ep_addr = ptxfifoval->bEndpointAddress;
  20406. + size = ptxfifoval->wDepth;
  20407. +
  20408. + ep = get_ep_by_addr(pcd, ep_addr);
  20409. +
  20410. + CFI_INFO
  20411. + ("%s: Set Tx FIFO size: endpoint addr=0x%02x, depth=%d, FIFO Num=%d\n",
  20412. + __func__, ep_addr, size, ep->dwc_ep.tx_fifo_num);
  20413. +
  20414. + if (NULL == ep) {
  20415. + CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n",
  20416. + __func__, ep_addr);
  20417. + return -DWC_E_INVALID;
  20418. + }
  20419. +
  20420. + fsiz = params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1];
  20421. + params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = size;
  20422. +
  20423. + if (resize_fifos(GET_CORE_IF(pcd))) {
  20424. + retval = 0;
  20425. + } else {
  20426. + CFI_INFO
  20427. + ("%s: Error setting the feature Tx FIFO Size for EP%d\n",
  20428. + __func__, ep_addr);
  20429. + params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = fsiz;
  20430. + retval = -DWC_E_INVALID;
  20431. + }
  20432. +
  20433. + return retval;
  20434. +}
  20435. +
  20436. +/**
  20437. + * This function sets a new value for the buffer Alignment setup.
  20438. + */
  20439. +static int cfi_set_rx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd)
  20440. +{
  20441. + int retval;
  20442. + uint32_t fsiz;
  20443. + uint16_t size;
  20444. + dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params;
  20445. + rx_fifo_size_setup_t *prxfifoval;
  20446. +
  20447. + prxfifoval = (rx_fifo_size_setup_t *) buf;
  20448. + size = prxfifoval->wDepth;
  20449. +
  20450. + fsiz = params->dev_rx_fifo_size;
  20451. + params->dev_rx_fifo_size = size;
  20452. +
  20453. + if (resize_fifos(GET_CORE_IF(pcd))) {
  20454. + retval = 0;
  20455. + } else {
  20456. + CFI_INFO("%s: Error setting the feature Rx FIFO Size\n",
  20457. + __func__);
  20458. + params->dev_rx_fifo_size = fsiz;
  20459. + retval = -DWC_E_INVALID;
  20460. + }
  20461. +
  20462. + return retval;
  20463. +}
  20464. +
  20465. +/**
  20466. + * This function reads the SG of an EP's buffer setup into the buffer buf
  20467. + */
  20468. +static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
  20469. + struct cfi_usb_ctrlrequest *req)
  20470. +{
  20471. + int retval = -DWC_E_INVALID;
  20472. + uint8_t addr;
  20473. + cfi_ep_t *ep;
  20474. +
  20475. + /* The Low Byte of the wValue contains a non-zero address of the endpoint */
  20476. + addr = req->wValue & 0xFF;
  20477. + if (addr == 0) /* The address should be non-zero */
  20478. + return retval;
  20479. +
  20480. + ep = get_cfi_ep_by_addr(pcd->cfi, addr);
  20481. + if (NULL == ep) {
  20482. + CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
  20483. + __func__, addr);
  20484. + return retval;
  20485. + }
  20486. +
  20487. + dwc_memcpy(buf, ep->bm_sg, BS_SG_VAL_DESC_LEN);
  20488. + retval = BS_SG_VAL_DESC_LEN;
  20489. + return retval;
  20490. +}
  20491. +
  20492. +/**
  20493. + * This function reads the Concatenation value of an EP's buffer mode into
  20494. + * the buffer buf
  20495. + */
  20496. +static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
  20497. + struct cfi_usb_ctrlrequest *req)
  20498. +{
  20499. + int retval = -DWC_E_INVALID;
  20500. + uint8_t addr;
  20501. + cfi_ep_t *ep;
  20502. + uint8_t desc_count;
  20503. +
  20504. + /* The Low Byte of the wValue contains a non-zero address of the endpoint */
  20505. + addr = req->wValue & 0xFF;
  20506. + if (addr == 0) /* The address should be non-zero */
  20507. + return retval;
  20508. +
  20509. + ep = get_cfi_ep_by_addr(pcd->cfi, addr);
  20510. + if (NULL == ep) {
  20511. + CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
  20512. + __func__, addr);
  20513. + return retval;
  20514. + }
  20515. +
  20516. + /* Copy the header to the buffer */
  20517. + dwc_memcpy(buf, ep->bm_concat, BS_CONCAT_VAL_HDR_LEN);
  20518. + /* Advance the buffer pointer by the header size */
  20519. + buf += BS_CONCAT_VAL_HDR_LEN;
  20520. +
  20521. + desc_count = ep->bm_concat->hdr.bDescCount;
  20522. + /* Copy alll the wTxBytes to the buffer */
  20523. + dwc_memcpy(buf, ep->bm_concat->wTxBytes, sizeof(uid16_t) * desc_count);
  20524. +
  20525. + retval = BS_CONCAT_VAL_HDR_LEN + sizeof(uid16_t) * desc_count;
  20526. + return retval;
  20527. +}
  20528. +
  20529. +/**
  20530. + * This function reads the buffer Alignment value of an EP's buffer mode into
  20531. + * the buffer buf
  20532. + *
  20533. + * @return The total number of bytes copied to the buffer or negative error code.
  20534. + */
  20535. +static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd,
  20536. + struct cfi_usb_ctrlrequest *req)
  20537. +{
  20538. + int retval = -DWC_E_INVALID;
  20539. + uint8_t addr;
  20540. + cfi_ep_t *ep;
  20541. +
  20542. + /* The Low Byte of the wValue contains a non-zero address of the endpoint */
  20543. + addr = req->wValue & 0xFF;
  20544. + if (addr == 0) /* The address should be non-zero */
  20545. + return retval;
  20546. +
  20547. + ep = get_cfi_ep_by_addr(pcd->cfi, addr);
  20548. + if (NULL == ep) {
  20549. + CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n",
  20550. + __func__, addr);
  20551. + return retval;
  20552. + }
  20553. +
  20554. + dwc_memcpy(buf, ep->bm_align, BS_ALIGN_VAL_HDR_LEN);
  20555. + retval = BS_ALIGN_VAL_HDR_LEN;
  20556. +
  20557. + return retval;
  20558. +}
  20559. +
  20560. +/**
  20561. + * This function sets a new value for the specified feature
  20562. + *
  20563. + * @param pcd A pointer to the PCD object
  20564. + *
  20565. + * @return 0 if successful, negative error code otherwise to stall the DCE.
  20566. + */
  20567. +static int cfi_set_feature_value(struct dwc_otg_pcd *pcd)
  20568. +{
  20569. + int retval = -DWC_E_NOT_SUPPORTED;
  20570. + uint16_t wIndex, wValue;
  20571. + uint8_t bRequest;
  20572. + struct dwc_otg_core_if *coreif;
  20573. + cfiobject_t *cfi = pcd->cfi;
  20574. + struct cfi_usb_ctrlrequest *ctrl_req;
  20575. + uint8_t *buf;
  20576. + ctrl_req = &cfi->ctrl_req;
  20577. +
  20578. + buf = pcd->cfi->ctrl_req.data;
  20579. +
  20580. + coreif = GET_CORE_IF(pcd);
  20581. + bRequest = ctrl_req->bRequest;
  20582. + wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex);
  20583. + wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue);
  20584. +
  20585. + /* See which feature is to be modified */
  20586. + switch (wIndex) {
  20587. + case FT_ID_DMA_BUFFER_SETUP:
  20588. + /* Modify the feature */
  20589. + if ((retval = cfi_ep_set_sg_val(buf, pcd)) < 0)
  20590. + return retval;
  20591. +
  20592. + /* And send this request to the gadget */
  20593. + cfi->need_gadget_att = 1;
  20594. + break;
  20595. +
  20596. + case FT_ID_DMA_BUFF_ALIGN:
  20597. + if ((retval = cfi_ep_set_alignment_val(buf, pcd)) < 0)
  20598. + return retval;
  20599. + cfi->need_gadget_att = 1;
  20600. + break;
  20601. +
  20602. + case FT_ID_DMA_CONCAT_SETUP:
  20603. + /* Modify the feature */
  20604. + if ((retval = cfi_ep_set_concat_val(buf, pcd)) < 0)
  20605. + return retval;
  20606. + cfi->need_gadget_att = 1;
  20607. + break;
  20608. +
  20609. + case FT_ID_DMA_CIRCULAR:
  20610. + CFI_INFO("FT_ID_DMA_CIRCULAR\n");
  20611. + break;
  20612. +
  20613. + case FT_ID_THRESHOLD_SETUP:
  20614. + CFI_INFO("FT_ID_THRESHOLD_SETUP\n");
  20615. + break;
  20616. +
  20617. + case FT_ID_DFIFO_DEPTH:
  20618. + CFI_INFO("FT_ID_DFIFO_DEPTH\n");
  20619. + break;
  20620. +
  20621. + case FT_ID_TX_FIFO_DEPTH:
  20622. + CFI_INFO("FT_ID_TX_FIFO_DEPTH\n");
  20623. + if ((retval = cfi_ep_set_tx_fifo_val(buf, pcd)) < 0)
  20624. + return retval;
  20625. + cfi->need_gadget_att = 0;
  20626. + break;
  20627. +
  20628. + case FT_ID_RX_FIFO_DEPTH:
  20629. + CFI_INFO("FT_ID_RX_FIFO_DEPTH\n");
  20630. + if ((retval = cfi_set_rx_fifo_val(buf, pcd)) < 0)
  20631. + return retval;
  20632. + cfi->need_gadget_att = 0;
  20633. + break;
  20634. + }
  20635. +
  20636. + return retval;
  20637. +}
  20638. +
  20639. +#endif //DWC_UTE_CFI
  20640. --- /dev/null
  20641. +++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.h
  20642. @@ -0,0 +1,320 @@
  20643. +/* ==========================================================================
  20644. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  20645. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  20646. + * otherwise expressly agreed to in writing between Synopsys and you.
  20647. + *
  20648. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  20649. + * any End User Software License Agreement or Agreement for Licensed Product
  20650. + * with Synopsys or any supplement thereto. You are permitted to use and
  20651. + * redistribute this Software in source and binary forms, with or without
  20652. + * modification, provided that redistributions of source code must retain this
  20653. + * notice. You may not view, use, disclose, copy or distribute this file or
  20654. + * any information contained herein except pursuant to this license grant from
  20655. + * Synopsys. If you do not agree with this notice, including the disclaimer
  20656. + * below, then you are not authorized to use the Software.
  20657. + *
  20658. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  20659. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20660. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20661. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  20662. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20663. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  20664. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  20665. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  20666. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  20667. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  20668. + * DAMAGE.
  20669. + * ========================================================================== */
  20670. +
  20671. +#if !defined(__DWC_OTG_CFI_H__)
  20672. +#define __DWC_OTG_CFI_H__
  20673. +
  20674. +#include "dwc_otg_pcd.h"
  20675. +#include "dwc_cfi_common.h"
  20676. +
  20677. +/**
  20678. + * @file
  20679. + * This file contains the CFI related OTG PCD specific common constants,
  20680. + * interfaces(functions and macros) and data structures.The CFI Protocol is an
  20681. + * optional interface for internal testing purposes that a DUT may implement to
  20682. + * support testing of configurable features.
  20683. + *
  20684. + */
  20685. +
  20686. +struct dwc_otg_pcd;
  20687. +struct dwc_otg_pcd_ep;
  20688. +
  20689. +/** OTG CFI Features (properties) ID constants */
  20690. +/** This is a request for all Core Features */
  20691. +#define FT_ID_DMA_MODE 0x0001
  20692. +#define FT_ID_DMA_BUFFER_SETUP 0x0002
  20693. +#define FT_ID_DMA_BUFF_ALIGN 0x0003
  20694. +#define FT_ID_DMA_CONCAT_SETUP 0x0004
  20695. +#define FT_ID_DMA_CIRCULAR 0x0005
  20696. +#define FT_ID_THRESHOLD_SETUP 0x0006
  20697. +#define FT_ID_DFIFO_DEPTH 0x0007
  20698. +#define FT_ID_TX_FIFO_DEPTH 0x0008
  20699. +#define FT_ID_RX_FIFO_DEPTH 0x0009
  20700. +
  20701. +/**********************************************************/
  20702. +#define CFI_INFO_DEF
  20703. +
  20704. +#ifdef CFI_INFO_DEF
  20705. +#define CFI_INFO(fmt...) DWC_PRINTF("CFI: " fmt);
  20706. +#else
  20707. +#define CFI_INFO(fmt...)
  20708. +#endif
  20709. +
  20710. +#define min(x,y) ({ \
  20711. + x < y ? x : y; })
  20712. +
  20713. +#define max(x,y) ({ \
  20714. + x > y ? x : y; })
  20715. +
  20716. +/**
  20717. + * Descriptor DMA SG Buffer setup structure (SG buffer). This structure is
  20718. + * also used for setting up a buffer for Circular DDMA.
  20719. + */
  20720. +struct _ddma_sg_buffer_setup {
  20721. +#define BS_SG_VAL_DESC_LEN 6
  20722. + /* The OUT EP address */
  20723. + uint8_t bOutEndpointAddress;
  20724. + /* The IN EP address */
  20725. + uint8_t bInEndpointAddress;
  20726. + /* Number of bytes to put between transfer segments (must be DWORD boundaries) */
  20727. + uint8_t bOffset;
  20728. + /* The number of transfer segments (a DMA descriptors per each segment) */
  20729. + uint8_t bCount;
  20730. + /* Size (in byte) of each transfer segment */
  20731. + uint16_t wSize;
  20732. +} __attribute__ ((packed));
  20733. +typedef struct _ddma_sg_buffer_setup ddma_sg_buffer_setup_t;
  20734. +
  20735. +/** Descriptor DMA Concatenation Buffer setup structure */
  20736. +struct _ddma_concat_buffer_setup_hdr {
  20737. +#define BS_CONCAT_VAL_HDR_LEN 4
  20738. + /* The endpoint for which the buffer is to be set up */
  20739. + uint8_t bEndpointAddress;
  20740. + /* The count of descriptors to be used */
  20741. + uint8_t bDescCount;
  20742. + /* The total size of the transfer */
  20743. + uint16_t wSize;
  20744. +} __attribute__ ((packed));
  20745. +typedef struct _ddma_concat_buffer_setup_hdr ddma_concat_buffer_setup_hdr_t;
  20746. +
  20747. +/** Descriptor DMA Concatenation Buffer setup structure */
  20748. +struct _ddma_concat_buffer_setup {
  20749. + /* The SG header */
  20750. + ddma_concat_buffer_setup_hdr_t hdr;
  20751. +
  20752. + /* The XFER sizes pointer (allocated dynamically) */
  20753. + uint16_t *wTxBytes;
  20754. +} __attribute__ ((packed));
  20755. +typedef struct _ddma_concat_buffer_setup ddma_concat_buffer_setup_t;
  20756. +
  20757. +/** Descriptor DMA Alignment Buffer setup structure */
  20758. +struct _ddma_align_buffer_setup {
  20759. +#define BS_ALIGN_VAL_HDR_LEN 2
  20760. + uint8_t bEndpointAddress;
  20761. + uint8_t bAlign;
  20762. +} __attribute__ ((packed));
  20763. +typedef struct _ddma_align_buffer_setup ddma_align_buffer_setup_t;
  20764. +
  20765. +/** Transmit FIFO Size setup structure */
  20766. +struct _tx_fifo_size_setup {
  20767. + uint8_t bEndpointAddress;
  20768. + uint16_t wDepth;
  20769. +} __attribute__ ((packed));
  20770. +typedef struct _tx_fifo_size_setup tx_fifo_size_setup_t;
  20771. +
  20772. +/** Transmit FIFO Size setup structure */
  20773. +struct _rx_fifo_size_setup {
  20774. + uint16_t wDepth;
  20775. +} __attribute__ ((packed));
  20776. +typedef struct _rx_fifo_size_setup rx_fifo_size_setup_t;
  20777. +
  20778. +/**
  20779. + * struct cfi_usb_ctrlrequest - the CFI implementation of the struct usb_ctrlrequest
  20780. + * This structure encapsulates the standard usb_ctrlrequest and adds a pointer
  20781. + * to the data returned in the data stage of a 3-stage Control Write requests.
  20782. + */
  20783. +struct cfi_usb_ctrlrequest {
  20784. + uint8_t bRequestType;
  20785. + uint8_t bRequest;
  20786. + uint16_t wValue;
  20787. + uint16_t wIndex;
  20788. + uint16_t wLength;
  20789. + uint8_t *data;
  20790. +} UPACKED;
  20791. +
  20792. +/*---------------------------------------------------------------------------*/
  20793. +
  20794. +/**
  20795. + * The CFI wrapper of the enabled and activated dwc_otg_pcd_ep structures.
  20796. + * This structure is used to store the buffer setup data for any
  20797. + * enabled endpoint in the PCD.
  20798. + */
  20799. +struct cfi_ep {
  20800. + /* Entry for the list container */
  20801. + dwc_list_link_t lh;
  20802. + /* Pointer to the active PCD endpoint structure */
  20803. + struct dwc_otg_pcd_ep *ep;
  20804. + /* The last descriptor in the chain of DMA descriptors of the endpoint */
  20805. + struct dwc_otg_dma_desc *dma_desc_last;
  20806. + /* The SG feature value */
  20807. + ddma_sg_buffer_setup_t *bm_sg;
  20808. + /* The Circular feature value */
  20809. + ddma_sg_buffer_setup_t *bm_circ;
  20810. + /* The Concatenation feature value */
  20811. + ddma_concat_buffer_setup_t *bm_concat;
  20812. + /* The Alignment feature value */
  20813. + ddma_align_buffer_setup_t *bm_align;
  20814. + /* XFER length */
  20815. + uint32_t xfer_len;
  20816. + /*
  20817. + * Count of DMA descriptors currently used.
  20818. + * The total should not exceed the MAX_DMA_DESCS_PER_EP value
  20819. + * defined in the dwc_otg_cil.h
  20820. + */
  20821. + uint32_t desc_count;
  20822. +};
  20823. +typedef struct cfi_ep cfi_ep_t;
  20824. +
  20825. +typedef struct cfi_dma_buff {
  20826. +#define CFI_IN_BUF_LEN 1024
  20827. +#define CFI_OUT_BUF_LEN 1024
  20828. + dma_addr_t addr;
  20829. + uint8_t *buf;
  20830. +} cfi_dma_buff_t;
  20831. +
  20832. +struct cfiobject;
  20833. +
  20834. +/**
  20835. + * This is the interface for the CFI operations.
  20836. + *
  20837. + * @param ep_enable Called when any endpoint is enabled and activated.
  20838. + * @param release Called when the CFI object is released and it needs to correctly
  20839. + * deallocate the dynamic memory
  20840. + * @param ctrl_write_complete Called when the data stage of the request is complete
  20841. + */
  20842. +typedef struct cfi_ops {
  20843. + int (*ep_enable) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd,
  20844. + struct dwc_otg_pcd_ep * ep);
  20845. + void *(*ep_alloc_buf) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd,
  20846. + struct dwc_otg_pcd_ep * ep, dma_addr_t * dma,
  20847. + unsigned size, gfp_t flags);
  20848. + void (*release) (struct cfiobject * cfi);
  20849. + int (*ctrl_write_complete) (struct cfiobject * cfi,
  20850. + struct dwc_otg_pcd * pcd);
  20851. + void (*build_descriptors) (struct cfiobject * cfi,
  20852. + struct dwc_otg_pcd * pcd,
  20853. + struct dwc_otg_pcd_ep * ep,
  20854. + dwc_otg_pcd_request_t * req);
  20855. +} cfi_ops_t;
  20856. +
  20857. +struct cfiobject {
  20858. + cfi_ops_t ops;
  20859. + struct dwc_otg_pcd *pcd;
  20860. + struct usb_gadget *gadget;
  20861. +
  20862. + /* Buffers used to send/receive CFI-related request data */
  20863. + cfi_dma_buff_t buf_in;
  20864. + cfi_dma_buff_t buf_out;
  20865. +
  20866. + /* CFI specific Control request wrapper */
  20867. + struct cfi_usb_ctrlrequest ctrl_req;
  20868. +
  20869. + /* The list of active EP's in the PCD of type cfi_ep_t */
  20870. + dwc_list_link_t active_eps;
  20871. +
  20872. + /* This flag shall control the propagation of a specific request
  20873. + * to the gadget's processing routines.
  20874. + * 0 - no gadget handling
  20875. + * 1 - the gadget needs to know about this request (w/o completing a status
  20876. + * phase - just return a 0 to the _setup callback)
  20877. + */
  20878. + uint8_t need_gadget_att;
  20879. +
  20880. + /* Flag indicating whether the status IN phase needs to be
  20881. + * completed by the PCD
  20882. + */
  20883. + uint8_t need_status_in_complete;
  20884. +};
  20885. +typedef struct cfiobject cfiobject_t;
  20886. +
  20887. +#define DUMP_MSG
  20888. +
  20889. +#if defined(DUMP_MSG)
  20890. +static inline void dump_msg(const u8 * buf, unsigned int length)
  20891. +{
  20892. + unsigned int start, num, i;
  20893. + char line[52], *p;
  20894. +
  20895. + if (length >= 512)
  20896. + return;
  20897. +
  20898. + start = 0;
  20899. + while (length > 0) {
  20900. + num = min(length, 16u);
  20901. + p = line;
  20902. + for (i = 0; i < num; ++i) {
  20903. + if (i == 8)
  20904. + *p++ = ' ';
  20905. + DWC_SPRINTF(p, " %02x", buf[i]);
  20906. + p += 3;
  20907. + }
  20908. + *p = 0;
  20909. + DWC_DEBUG("%6x: %s\n", start, line);
  20910. + buf += num;
  20911. + start += num;
  20912. + length -= num;
  20913. + }
  20914. +}
  20915. +#else
  20916. +static inline void dump_msg(const u8 * buf, unsigned int length)
  20917. +{
  20918. +}
  20919. +#endif
  20920. +
  20921. +/**
  20922. + * This function returns a pointer to cfi_ep_t object with the addr address.
  20923. + */
  20924. +static inline struct cfi_ep *get_cfi_ep_by_addr(struct cfiobject *cfi,
  20925. + uint8_t addr)
  20926. +{
  20927. + struct cfi_ep *pcfiep;
  20928. + dwc_list_link_t *tmp;
  20929. +
  20930. + DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
  20931. + pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
  20932. +
  20933. + if (pcfiep->ep->desc->bEndpointAddress == addr) {
  20934. + return pcfiep;
  20935. + }
  20936. + }
  20937. +
  20938. + return NULL;
  20939. +}
  20940. +
  20941. +/**
  20942. + * This function returns a pointer to cfi_ep_t object that matches
  20943. + * the dwc_otg_pcd_ep object.
  20944. + */
  20945. +static inline struct cfi_ep *get_cfi_ep_by_pcd_ep(struct cfiobject *cfi,
  20946. + struct dwc_otg_pcd_ep *ep)
  20947. +{
  20948. + struct cfi_ep *pcfiep = NULL;
  20949. + dwc_list_link_t *tmp;
  20950. +
  20951. + DWC_LIST_FOREACH(tmp, &cfi->active_eps) {
  20952. + pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh);
  20953. + if (pcfiep->ep == ep) {
  20954. + return pcfiep;
  20955. + }
  20956. + }
  20957. + return NULL;
  20958. +}
  20959. +
  20960. +int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl);
  20961. +
  20962. +#endif /* (__DWC_OTG_CFI_H__) */
  20963. --- /dev/null
  20964. +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.c
  20965. @@ -0,0 +1,7151 @@
  20966. +/* ==========================================================================
  20967. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $
  20968. + * $Revision: #191 $
  20969. + * $Date: 2012/08/10 $
  20970. + * $Change: 2047372 $
  20971. + *
  20972. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  20973. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  20974. + * otherwise expressly agreed to in writing between Synopsys and you.
  20975. + *
  20976. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  20977. + * any End User Software License Agreement or Agreement for Licensed Product
  20978. + * with Synopsys or any supplement thereto. You are permitted to use and
  20979. + * redistribute this Software in source and binary forms, with or without
  20980. + * modification, provided that redistributions of source code must retain this
  20981. + * notice. You may not view, use, disclose, copy or distribute this file or
  20982. + * any information contained herein except pursuant to this license grant from
  20983. + * Synopsys. If you do not agree with this notice, including the disclaimer
  20984. + * below, then you are not authorized to use the Software.
  20985. + *
  20986. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  20987. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20988. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20989. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  20990. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20991. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  20992. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  20993. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  20994. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  20995. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  20996. + * DAMAGE.
  20997. + * ========================================================================== */
  20998. +
  20999. +/** @file
  21000. + *
  21001. + * The Core Interface Layer provides basic services for accessing and
  21002. + * managing the DWC_otg hardware. These services are used by both the
  21003. + * Host Controller Driver and the Peripheral Controller Driver.
  21004. + *
  21005. + * The CIL manages the memory map for the core so that the HCD and PCD
  21006. + * don't have to do this separately. It also handles basic tasks like
  21007. + * reading/writing the registers and data FIFOs in the controller.
  21008. + * Some of the data access functions provide encapsulation of several
  21009. + * operations required to perform a task, such as writing multiple
  21010. + * registers to start a transfer. Finally, the CIL performs basic
  21011. + * services that are not specific to either the host or device modes
  21012. + * of operation. These services include management of the OTG Host
  21013. + * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A
  21014. + * Diagnostic API is also provided to allow testing of the controller
  21015. + * hardware.
  21016. + *
  21017. + * The Core Interface Layer has the following requirements:
  21018. + * - Provides basic controller operations.
  21019. + * - Minimal use of OS services.
  21020. + * - The OS services used will be abstracted by using inline functions
  21021. + * or macros.
  21022. + *
  21023. + */
  21024. +
  21025. +#include "dwc_os.h"
  21026. +#include "dwc_otg_regs.h"
  21027. +#include "dwc_otg_cil.h"
  21028. +
  21029. +static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if);
  21030. +
  21031. +/**
  21032. + * This function is called to initialize the DWC_otg CSR data
  21033. + * structures. The register addresses in the device and host
  21034. + * structures are initialized from the base address supplied by the
  21035. + * caller. The calling function must make the OS calls to get the
  21036. + * base address of the DWC_otg controller registers. The core_params
  21037. + * argument holds the parameters that specify how the core should be
  21038. + * configured.
  21039. + *
  21040. + * @param reg_base_addr Base address of DWC_otg core registers
  21041. + *
  21042. + */
  21043. +dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr)
  21044. +{
  21045. + dwc_otg_core_if_t *core_if = 0;
  21046. + dwc_otg_dev_if_t *dev_if = 0;
  21047. + dwc_otg_host_if_t *host_if = 0;
  21048. + uint8_t *reg_base = (uint8_t *) reg_base_addr;
  21049. + int i = 0;
  21050. +
  21051. + DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, reg_base_addr);
  21052. +
  21053. + core_if = DWC_ALLOC(sizeof(dwc_otg_core_if_t));
  21054. +
  21055. + if (core_if == NULL) {
  21056. + DWC_DEBUGPL(DBG_CIL,
  21057. + "Allocation of dwc_otg_core_if_t failed\n");
  21058. + return 0;
  21059. + }
  21060. + core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base;
  21061. +
  21062. + /*
  21063. + * Allocate the Device Mode structures.
  21064. + */
  21065. + dev_if = DWC_ALLOC(sizeof(dwc_otg_dev_if_t));
  21066. +
  21067. + if (dev_if == NULL) {
  21068. + DWC_DEBUGPL(DBG_CIL, "Allocation of dwc_otg_dev_if_t failed\n");
  21069. + DWC_FREE(core_if);
  21070. + return 0;
  21071. + }
  21072. +
  21073. + dev_if->dev_global_regs =
  21074. + (dwc_otg_device_global_regs_t *) (reg_base +
  21075. + DWC_DEV_GLOBAL_REG_OFFSET);
  21076. +
  21077. + for (i = 0; i < MAX_EPS_CHANNELS; i++) {
  21078. + dev_if->in_ep_regs[i] = (dwc_otg_dev_in_ep_regs_t *)
  21079. + (reg_base + DWC_DEV_IN_EP_REG_OFFSET +
  21080. + (i * DWC_EP_REG_OFFSET));
  21081. +
  21082. + dev_if->out_ep_regs[i] = (dwc_otg_dev_out_ep_regs_t *)
  21083. + (reg_base + DWC_DEV_OUT_EP_REG_OFFSET +
  21084. + (i * DWC_EP_REG_OFFSET));
  21085. + DWC_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p\n",
  21086. + i, &dev_if->in_ep_regs[i]->diepctl);
  21087. + DWC_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p\n",
  21088. + i, &dev_if->out_ep_regs[i]->doepctl);
  21089. + }
  21090. +
  21091. + dev_if->speed = 0; // unknown
  21092. +
  21093. + core_if->dev_if = dev_if;
  21094. +
  21095. + /*
  21096. + * Allocate the Host Mode structures.
  21097. + */
  21098. + host_if = DWC_ALLOC(sizeof(dwc_otg_host_if_t));
  21099. +
  21100. + if (host_if == NULL) {
  21101. + DWC_DEBUGPL(DBG_CIL,
  21102. + "Allocation of dwc_otg_host_if_t failed\n");
  21103. + DWC_FREE(dev_if);
  21104. + DWC_FREE(core_if);
  21105. + return 0;
  21106. + }
  21107. +
  21108. + host_if->host_global_regs = (dwc_otg_host_global_regs_t *)
  21109. + (reg_base + DWC_OTG_HOST_GLOBAL_REG_OFFSET);
  21110. +
  21111. + host_if->hprt0 =
  21112. + (uint32_t *) (reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET);
  21113. +
  21114. + for (i = 0; i < MAX_EPS_CHANNELS; i++) {
  21115. + host_if->hc_regs[i] = (dwc_otg_hc_regs_t *)
  21116. + (reg_base + DWC_OTG_HOST_CHAN_REGS_OFFSET +
  21117. + (i * DWC_OTG_CHAN_REGS_OFFSET));
  21118. + DWC_DEBUGPL(DBG_CILV, "hc_reg[%d]->hcchar=%p\n",
  21119. + i, &host_if->hc_regs[i]->hcchar);
  21120. + }
  21121. +
  21122. + host_if->num_host_channels = MAX_EPS_CHANNELS;
  21123. + core_if->host_if = host_if;
  21124. +
  21125. + for (i = 0; i < MAX_EPS_CHANNELS; i++) {
  21126. + core_if->data_fifo[i] =
  21127. + (uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET +
  21128. + (i * DWC_OTG_DATA_FIFO_SIZE));
  21129. + DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08lx\n",
  21130. + i, (unsigned long)core_if->data_fifo[i]);
  21131. + }
  21132. +
  21133. + core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET);
  21134. +
  21135. + /* Initiate lx_state to L3 disconnected state */
  21136. + core_if->lx_state = DWC_OTG_L3;
  21137. + /*
  21138. + * Store the contents of the hardware configuration registers here for
  21139. + * easy access later.
  21140. + */
  21141. + core_if->hwcfg1.d32 =
  21142. + DWC_READ_REG32(&core_if->core_global_regs->ghwcfg1);
  21143. + core_if->hwcfg2.d32 =
  21144. + DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2);
  21145. + core_if->hwcfg3.d32 =
  21146. + DWC_READ_REG32(&core_if->core_global_regs->ghwcfg3);
  21147. + core_if->hwcfg4.d32 =
  21148. + DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4);
  21149. +
  21150. + /* Force host mode to get HPTXFSIZ exact power on value */
  21151. + {
  21152. + gusbcfg_data_t gusbcfg = {.d32 = 0 };
  21153. + gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
  21154. + gusbcfg.b.force_host_mode = 1;
  21155. + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
  21156. + dwc_mdelay(100);
  21157. + core_if->hptxfsiz.d32 =
  21158. + DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
  21159. + gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
  21160. + gusbcfg.b.force_host_mode = 0;
  21161. + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
  21162. + dwc_mdelay(100);
  21163. + }
  21164. +
  21165. + DWC_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32);
  21166. + DWC_DEBUGPL(DBG_CILV, "hwcfg2=%08x\n", core_if->hwcfg2.d32);
  21167. + DWC_DEBUGPL(DBG_CILV, "hwcfg3=%08x\n", core_if->hwcfg3.d32);
  21168. + DWC_DEBUGPL(DBG_CILV, "hwcfg4=%08x\n", core_if->hwcfg4.d32);
  21169. +
  21170. + core_if->hcfg.d32 =
  21171. + DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
  21172. + core_if->dcfg.d32 =
  21173. + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
  21174. +
  21175. + DWC_DEBUGPL(DBG_CILV, "hcfg=%08x\n", core_if->hcfg.d32);
  21176. + DWC_DEBUGPL(DBG_CILV, "dcfg=%08x\n", core_if->dcfg.d32);
  21177. +
  21178. + DWC_DEBUGPL(DBG_CILV, "op_mode=%0x\n", core_if->hwcfg2.b.op_mode);
  21179. + DWC_DEBUGPL(DBG_CILV, "arch=%0x\n", core_if->hwcfg2.b.architecture);
  21180. + DWC_DEBUGPL(DBG_CILV, "num_dev_ep=%d\n", core_if->hwcfg2.b.num_dev_ep);
  21181. + DWC_DEBUGPL(DBG_CILV, "num_host_chan=%d\n",
  21182. + core_if->hwcfg2.b.num_host_chan);
  21183. + DWC_DEBUGPL(DBG_CILV, "nonperio_tx_q_depth=0x%0x\n",
  21184. + core_if->hwcfg2.b.nonperio_tx_q_depth);
  21185. + DWC_DEBUGPL(DBG_CILV, "host_perio_tx_q_depth=0x%0x\n",
  21186. + core_if->hwcfg2.b.host_perio_tx_q_depth);
  21187. + DWC_DEBUGPL(DBG_CILV, "dev_token_q_depth=0x%0x\n",
  21188. + core_if->hwcfg2.b.dev_token_q_depth);
  21189. +
  21190. + DWC_DEBUGPL(DBG_CILV, "Total FIFO SZ=%d\n",
  21191. + core_if->hwcfg3.b.dfifo_depth);
  21192. + DWC_DEBUGPL(DBG_CILV, "xfer_size_cntr_width=%0x\n",
  21193. + core_if->hwcfg3.b.xfer_size_cntr_width);
  21194. +
  21195. + /*
  21196. + * Set the SRP sucess bit for FS-I2c
  21197. + */
  21198. + core_if->srp_success = 0;
  21199. + core_if->srp_timer_started = 0;
  21200. +
  21201. + /*
  21202. + * Create new workqueue and init works
  21203. + */
  21204. + core_if->wq_otg = DWC_WORKQ_ALLOC("dwc_otg");
  21205. + if (core_if->wq_otg == 0) {
  21206. + DWC_WARN("DWC_WORKQ_ALLOC failed\n");
  21207. + DWC_FREE(host_if);
  21208. + DWC_FREE(dev_if);
  21209. + DWC_FREE(core_if);
  21210. + return 0;
  21211. + }
  21212. +
  21213. + core_if->snpsid = DWC_READ_REG32(&core_if->core_global_regs->gsnpsid);
  21214. +
  21215. + DWC_PRINTF("Core Release: %x.%x%x%x\n",
  21216. + (core_if->snpsid >> 12 & 0xF),
  21217. + (core_if->snpsid >> 8 & 0xF),
  21218. + (core_if->snpsid >> 4 & 0xF), (core_if->snpsid & 0xF));
  21219. +
  21220. + core_if->wkp_timer = DWC_TIMER_ALLOC("Wake Up Timer",
  21221. + w_wakeup_detected, core_if);
  21222. + if (core_if->wkp_timer == 0) {
  21223. + DWC_WARN("DWC_TIMER_ALLOC failed\n");
  21224. + DWC_FREE(host_if);
  21225. + DWC_FREE(dev_if);
  21226. + DWC_WORKQ_FREE(core_if->wq_otg);
  21227. + DWC_FREE(core_if);
  21228. + return 0;
  21229. + }
  21230. +
  21231. + if (dwc_otg_setup_params(core_if)) {
  21232. + DWC_WARN("Error while setting core params\n");
  21233. + }
  21234. +
  21235. + core_if->hibernation_suspend = 0;
  21236. +
  21237. + /** ADP initialization */
  21238. + dwc_otg_adp_init(core_if);
  21239. +
  21240. + return core_if;
  21241. +}
  21242. +
  21243. +/**
  21244. + * This function frees the structures allocated by dwc_otg_cil_init().
  21245. + *
  21246. + * @param core_if The core interface pointer returned from
  21247. + * dwc_otg_cil_init().
  21248. + *
  21249. + */
  21250. +void dwc_otg_cil_remove(dwc_otg_core_if_t * core_if)
  21251. +{
  21252. + dctl_data_t dctl = {.d32 = 0 };
  21253. + DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if);
  21254. +
  21255. + /* Disable all interrupts */
  21256. + DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 1, 0);
  21257. + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0);
  21258. +
  21259. + dctl.b.sftdiscon = 1;
  21260. + if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
  21261. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0,
  21262. + dctl.d32);
  21263. + }
  21264. +
  21265. + if (core_if->wq_otg) {
  21266. + DWC_WORKQ_WAIT_WORK_DONE(core_if->wq_otg, 500);
  21267. + DWC_WORKQ_FREE(core_if->wq_otg);
  21268. + }
  21269. + if (core_if->dev_if) {
  21270. + DWC_FREE(core_if->dev_if);
  21271. + }
  21272. + if (core_if->host_if) {
  21273. + DWC_FREE(core_if->host_if);
  21274. + }
  21275. +
  21276. + /** Remove ADP Stuff */
  21277. + dwc_otg_adp_remove(core_if);
  21278. + if (core_if->core_params) {
  21279. + DWC_FREE(core_if->core_params);
  21280. + }
  21281. + if (core_if->wkp_timer) {
  21282. + DWC_TIMER_FREE(core_if->wkp_timer);
  21283. + }
  21284. + if (core_if->srp_timer) {
  21285. + DWC_TIMER_FREE(core_if->srp_timer);
  21286. + }
  21287. + DWC_FREE(core_if);
  21288. +}
  21289. +
  21290. +/**
  21291. + * This function enables the controller's Global Interrupt in the AHB Config
  21292. + * register.
  21293. + *
  21294. + * @param core_if Programming view of DWC_otg controller.
  21295. + */
  21296. +void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * core_if)
  21297. +{
  21298. + gahbcfg_data_t ahbcfg = {.d32 = 0 };
  21299. + ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */
  21300. + DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32);
  21301. +}
  21302. +
  21303. +/**
  21304. + * This function disables the controller's Global Interrupt in the AHB Config
  21305. + * register.
  21306. + *
  21307. + * @param core_if Programming view of DWC_otg controller.
  21308. + */
  21309. +void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * core_if)
  21310. +{
  21311. + gahbcfg_data_t ahbcfg = {.d32 = 0 };
  21312. + ahbcfg.b.glblintrmsk = 1; /* Disable interrupts */
  21313. + DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
  21314. +}
  21315. +
  21316. +/**
  21317. + * This function initializes the commmon interrupts, used in both
  21318. + * device and host modes.
  21319. + *
  21320. + * @param core_if Programming view of the DWC_otg controller
  21321. + *
  21322. + */
  21323. +static void dwc_otg_enable_common_interrupts(dwc_otg_core_if_t * core_if)
  21324. +{
  21325. + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
  21326. + gintmsk_data_t intr_mask = {.d32 = 0 };
  21327. +
  21328. + /* Clear any pending OTG Interrupts */
  21329. + DWC_WRITE_REG32(&global_regs->gotgint, 0xFFFFFFFF);
  21330. +
  21331. + /* Clear any pending interrupts */
  21332. + DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
  21333. +
  21334. + /*
  21335. + * Enable the interrupts in the GINTMSK.
  21336. + */
  21337. + intr_mask.b.modemismatch = 1;
  21338. + intr_mask.b.otgintr = 1;
  21339. +
  21340. + if (!core_if->dma_enable) {
  21341. + intr_mask.b.rxstsqlvl = 1;
  21342. + }
  21343. +
  21344. + intr_mask.b.conidstschng = 1;
  21345. + intr_mask.b.wkupintr = 1;
  21346. + intr_mask.b.disconnect = 0;
  21347. + intr_mask.b.usbsuspend = 1;
  21348. + intr_mask.b.sessreqintr = 1;
  21349. +#ifdef CONFIG_USB_DWC_OTG_LPM
  21350. + if (core_if->core_params->lpm_enable) {
  21351. + intr_mask.b.lpmtranrcvd = 1;
  21352. + }
  21353. +#endif
  21354. + DWC_WRITE_REG32(&global_regs->gintmsk, intr_mask.d32);
  21355. +}
  21356. +
  21357. +/*
  21358. + * The restore operation is modified to support Synopsys Emulated Powerdown and
  21359. + * Hibernation. This function is for exiting from Device mode hibernation by
  21360. + * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup.
  21361. + * @param core_if Programming view of DWC_otg controller.
  21362. + * @param rem_wakeup - indicates whether resume is initiated by Device or Host.
  21363. + * @param reset - indicates whether resume is initiated by Reset.
  21364. + */
  21365. +int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,
  21366. + int rem_wakeup, int reset)
  21367. +{
  21368. + gpwrdn_data_t gpwrdn = {.d32 = 0 };
  21369. + pcgcctl_data_t pcgcctl = {.d32 = 0 };
  21370. + dctl_data_t dctl = {.d32 = 0 };
  21371. +
  21372. + int timeout = 2000;
  21373. +
  21374. + if (!core_if->hibernation_suspend) {
  21375. + DWC_PRINTF("Already exited from Hibernation\n");
  21376. + return 1;
  21377. + }
  21378. +
  21379. + DWC_DEBUGPL(DBG_PCD, "%s called\n", __FUNCTION__);
  21380. + /* Switch-on voltage to the core */
  21381. + gpwrdn.b.pwrdnswtch = 1;
  21382. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  21383. + dwc_udelay(10);
  21384. +
  21385. + /* Reset core */
  21386. + gpwrdn.d32 = 0;
  21387. + gpwrdn.b.pwrdnrstn = 1;
  21388. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  21389. + dwc_udelay(10);
  21390. +
  21391. + /* Assert Restore signal */
  21392. + gpwrdn.d32 = 0;
  21393. + gpwrdn.b.restore = 1;
  21394. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
  21395. + dwc_udelay(10);
  21396. +
  21397. + /* Disable power clamps */
  21398. + gpwrdn.d32 = 0;
  21399. + gpwrdn.b.pwrdnclmp = 1;
  21400. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  21401. +
  21402. + if (rem_wakeup) {
  21403. + dwc_udelay(70);
  21404. + }
  21405. +
  21406. + /* Deassert Reset core */
  21407. + gpwrdn.d32 = 0;
  21408. + gpwrdn.b.pwrdnrstn = 1;
  21409. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
  21410. + dwc_udelay(10);
  21411. +
  21412. + /* Disable PMU interrupt */
  21413. + gpwrdn.d32 = 0;
  21414. + gpwrdn.b.pmuintsel = 1;
  21415. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  21416. +
  21417. + /* Mask interrupts from gpwrdn */
  21418. + gpwrdn.d32 = 0;
  21419. + gpwrdn.b.connect_det_msk = 1;
  21420. + gpwrdn.b.srp_det_msk = 1;
  21421. + gpwrdn.b.disconn_det_msk = 1;
  21422. + gpwrdn.b.rst_det_msk = 1;
  21423. + gpwrdn.b.lnstchng_msk = 1;
  21424. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  21425. +
  21426. + /* Indicates that we are going out from hibernation */
  21427. + core_if->hibernation_suspend = 0;
  21428. +
  21429. + /*
  21430. + * Set Restore Essential Regs bit in PCGCCTL register, restore_mode = 1
  21431. + * indicates restore from remote_wakeup
  21432. + */
  21433. + restore_essential_regs(core_if, rem_wakeup, 0);
  21434. +
  21435. + /*
  21436. + * Wait a little for seeing new value of variable hibernation_suspend if
  21437. + * Restore done interrupt received before polling
  21438. + */
  21439. + dwc_udelay(10);
  21440. +
  21441. + if (core_if->hibernation_suspend == 0) {
  21442. + /*
  21443. + * Wait For Restore_done Interrupt. This mechanism of polling the
  21444. + * interrupt is introduced to avoid any possible race conditions
  21445. + */
  21446. + do {
  21447. + gintsts_data_t gintsts;
  21448. + gintsts.d32 =
  21449. + DWC_READ_REG32(&core_if->core_global_regs->gintsts);
  21450. + if (gintsts.b.restoredone) {
  21451. + gintsts.d32 = 0;
  21452. + gintsts.b.restoredone = 1;
  21453. + DWC_WRITE_REG32(&core_if->core_global_regs->
  21454. + gintsts, gintsts.d32);
  21455. + DWC_PRINTF("Restore Done Interrupt seen\n");
  21456. + break;
  21457. + }
  21458. + dwc_udelay(10);
  21459. + } while (--timeout);
  21460. + if (!timeout) {
  21461. + DWC_PRINTF("Restore Done interrupt wasn't generated here\n");
  21462. + }
  21463. + }
  21464. + /* Clear all pending interupts */
  21465. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
  21466. +
  21467. + /* De-assert Restore */
  21468. + gpwrdn.d32 = 0;
  21469. + gpwrdn.b.restore = 1;
  21470. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  21471. + dwc_udelay(10);
  21472. +
  21473. + if (!rem_wakeup) {
  21474. + pcgcctl.d32 = 0;
  21475. + pcgcctl.b.rstpdwnmodule = 1;
  21476. + DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
  21477. + }
  21478. +
  21479. + /* Restore GUSBCFG and DCFG */
  21480. + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
  21481. + core_if->gr_backup->gusbcfg_local);
  21482. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
  21483. + core_if->dr_backup->dcfg);
  21484. +
  21485. + /* De-assert Wakeup Logic */
  21486. + gpwrdn.d32 = 0;
  21487. + gpwrdn.b.pmuactv = 1;
  21488. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  21489. + dwc_udelay(10);
  21490. +
  21491. + if (!rem_wakeup) {
  21492. + /* Set Device programming done bit */
  21493. + dctl.b.pwronprgdone = 1;
  21494. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
  21495. + } else {
  21496. + /* Start Remote Wakeup Signaling */
  21497. + dctl.d32 = core_if->dr_backup->dctl;
  21498. + dctl.b.rmtwkupsig = 1;
  21499. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
  21500. + }
  21501. +
  21502. + dwc_mdelay(2);
  21503. + /* Clear all pending interupts */
  21504. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
  21505. +
  21506. + /* Restore global registers */
  21507. + dwc_otg_restore_global_regs(core_if);
  21508. + /* Restore device global registers */
  21509. + dwc_otg_restore_dev_regs(core_if, rem_wakeup);
  21510. +
  21511. + if (rem_wakeup) {
  21512. + dwc_mdelay(7);
  21513. + dctl.d32 = 0;
  21514. + dctl.b.rmtwkupsig = 1;
  21515. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
  21516. + }
  21517. +
  21518. + core_if->hibernation_suspend = 0;
  21519. + /* The core will be in ON STATE */
  21520. + core_if->lx_state = DWC_OTG_L0;
  21521. + DWC_PRINTF("Hibernation recovery completes here\n");
  21522. +
  21523. + return 1;
  21524. +}
  21525. +
  21526. +/*
  21527. + * The restore operation is modified to support Synopsys Emulated Powerdown and
  21528. + * Hibernation. This function is for exiting from Host mode hibernation by
  21529. + * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup.
  21530. + * @param core_if Programming view of DWC_otg controller.
  21531. + * @param rem_wakeup - indicates whether resume is initiated by Device or Host.
  21532. + * @param reset - indicates whether resume is initiated by Reset.
  21533. + */
  21534. +int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if,
  21535. + int rem_wakeup, int reset)
  21536. +{
  21537. + gpwrdn_data_t gpwrdn = {.d32 = 0 };
  21538. + hprt0_data_t hprt0 = {.d32 = 0 };
  21539. +
  21540. + int timeout = 2000;
  21541. +
  21542. + DWC_DEBUGPL(DBG_HCD, "%s called\n", __FUNCTION__);
  21543. + /* Switch-on voltage to the core */
  21544. + gpwrdn.b.pwrdnswtch = 1;
  21545. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  21546. + dwc_udelay(10);
  21547. +
  21548. + /* Reset core */
  21549. + gpwrdn.d32 = 0;
  21550. + gpwrdn.b.pwrdnrstn = 1;
  21551. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  21552. + dwc_udelay(10);
  21553. +
  21554. + /* Assert Restore signal */
  21555. + gpwrdn.d32 = 0;
  21556. + gpwrdn.b.restore = 1;
  21557. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
  21558. + dwc_udelay(10);
  21559. +
  21560. + /* Disable power clamps */
  21561. + gpwrdn.d32 = 0;
  21562. + gpwrdn.b.pwrdnclmp = 1;
  21563. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  21564. +
  21565. + if (!rem_wakeup) {
  21566. + dwc_udelay(50);
  21567. + }
  21568. +
  21569. + /* Deassert Reset core */
  21570. + gpwrdn.d32 = 0;
  21571. + gpwrdn.b.pwrdnrstn = 1;
  21572. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
  21573. + dwc_udelay(10);
  21574. +
  21575. + /* Disable PMU interrupt */
  21576. + gpwrdn.d32 = 0;
  21577. + gpwrdn.b.pmuintsel = 1;
  21578. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  21579. +
  21580. + gpwrdn.d32 = 0;
  21581. + gpwrdn.b.connect_det_msk = 1;
  21582. + gpwrdn.b.srp_det_msk = 1;
  21583. + gpwrdn.b.disconn_det_msk = 1;
  21584. + gpwrdn.b.rst_det_msk = 1;
  21585. + gpwrdn.b.lnstchng_msk = 1;
  21586. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  21587. +
  21588. + /* Indicates that we are going out from hibernation */
  21589. + core_if->hibernation_suspend = 0;
  21590. +
  21591. + /* Set Restore Essential Regs bit in PCGCCTL register */
  21592. + restore_essential_regs(core_if, rem_wakeup, 1);
  21593. +
  21594. + /* Wait a little for seeing new value of variable hibernation_suspend if
  21595. + * Restore done interrupt received before polling */
  21596. + dwc_udelay(10);
  21597. +
  21598. + if (core_if->hibernation_suspend == 0) {
  21599. + /* Wait For Restore_done Interrupt. This mechanism of polling the
  21600. + * interrupt is introduced to avoid any possible race conditions
  21601. + */
  21602. + do {
  21603. + gintsts_data_t gintsts;
  21604. + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
  21605. + if (gintsts.b.restoredone) {
  21606. + gintsts.d32 = 0;
  21607. + gintsts.b.restoredone = 1;
  21608. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
  21609. + DWC_DEBUGPL(DBG_HCD,"Restore Done Interrupt seen\n");
  21610. + break;
  21611. + }
  21612. + dwc_udelay(10);
  21613. + } while (--timeout);
  21614. + if (!timeout) {
  21615. + DWC_WARN("Restore Done interrupt wasn't generated\n");
  21616. + }
  21617. + }
  21618. +
  21619. + /* Set the flag's value to 0 again after receiving restore done interrupt */
  21620. + core_if->hibernation_suspend = 0;
  21621. +
  21622. + /* This step is not described in functional spec but if not wait for this
  21623. + * delay, mismatch interrupts occurred because just after restore core is
  21624. + * in Device mode(gintsts.curmode == 0) */
  21625. + dwc_mdelay(100);
  21626. +
  21627. + /* Clear all pending interrupts */
  21628. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
  21629. +
  21630. + /* De-assert Restore */
  21631. + gpwrdn.d32 = 0;
  21632. + gpwrdn.b.restore = 1;
  21633. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  21634. + dwc_udelay(10);
  21635. +
  21636. + /* Restore GUSBCFG and HCFG */
  21637. + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
  21638. + core_if->gr_backup->gusbcfg_local);
  21639. + DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg,
  21640. + core_if->hr_backup->hcfg_local);
  21641. +
  21642. + /* De-assert Wakeup Logic */
  21643. + gpwrdn.d32 = 0;
  21644. + gpwrdn.b.pmuactv = 1;
  21645. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  21646. + dwc_udelay(10);
  21647. +
  21648. + /* Start the Resume operation by programming HPRT0 */
  21649. + hprt0.d32 = core_if->hr_backup->hprt0_local;
  21650. + hprt0.b.prtpwr = 1;
  21651. + hprt0.b.prtena = 0;
  21652. + hprt0.b.prtsusp = 0;
  21653. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  21654. +
  21655. + DWC_PRINTF("Resume Starts Now\n");
  21656. + if (!reset) { // Indicates it is Resume Operation
  21657. + hprt0.d32 = core_if->hr_backup->hprt0_local;
  21658. + hprt0.b.prtres = 1;
  21659. + hprt0.b.prtpwr = 1;
  21660. + hprt0.b.prtena = 0;
  21661. + hprt0.b.prtsusp = 0;
  21662. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  21663. +
  21664. + if (!rem_wakeup)
  21665. + hprt0.b.prtres = 0;
  21666. + /* Wait for Resume time and then program HPRT again */
  21667. + dwc_mdelay(100);
  21668. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  21669. +
  21670. + } else { // Indicates it is Reset Operation
  21671. + hprt0.d32 = core_if->hr_backup->hprt0_local;
  21672. + hprt0.b.prtrst = 1;
  21673. + hprt0.b.prtpwr = 1;
  21674. + hprt0.b.prtena = 0;
  21675. + hprt0.b.prtsusp = 0;
  21676. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  21677. + /* Wait for Reset time and then program HPRT again */
  21678. + dwc_mdelay(60);
  21679. + hprt0.b.prtrst = 0;
  21680. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  21681. + }
  21682. + /* Clear all interrupt status */
  21683. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  21684. + hprt0.b.prtconndet = 1;
  21685. + hprt0.b.prtenchng = 1;
  21686. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  21687. +
  21688. + /* Clear all pending interupts */
  21689. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
  21690. +
  21691. + /* Restore global registers */
  21692. + dwc_otg_restore_global_regs(core_if);
  21693. + /* Restore host global registers */
  21694. + dwc_otg_restore_host_regs(core_if, reset);
  21695. +
  21696. + /* The core will be in ON STATE */
  21697. + core_if->lx_state = DWC_OTG_L0;
  21698. + DWC_PRINTF("Hibernation recovery is complete here\n");
  21699. + return 0;
  21700. +}
  21701. +
  21702. +/** Saves some register values into system memory. */
  21703. +int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if)
  21704. +{
  21705. + struct dwc_otg_global_regs_backup *gr;
  21706. + int i;
  21707. +
  21708. + gr = core_if->gr_backup;
  21709. + if (!gr) {
  21710. + gr = DWC_ALLOC(sizeof(*gr));
  21711. + if (!gr) {
  21712. + return -DWC_E_NO_MEMORY;
  21713. + }
  21714. + core_if->gr_backup = gr;
  21715. + }
  21716. +
  21717. + gr->gotgctl_local = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
  21718. + gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
  21719. + gr->gahbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
  21720. + gr->gusbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
  21721. + gr->grxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
  21722. + gr->gnptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz);
  21723. + gr->hptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
  21724. +#ifdef CONFIG_USB_DWC_OTG_LPM
  21725. + gr->glpmcfg_local = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
  21726. +#endif
  21727. + gr->gi2cctl_local = DWC_READ_REG32(&core_if->core_global_regs->gi2cctl);
  21728. + gr->pcgcctl_local = DWC_READ_REG32(core_if->pcgcctl);
  21729. + gr->gdfifocfg_local =
  21730. + DWC_READ_REG32(&core_if->core_global_regs->gdfifocfg);
  21731. + for (i = 0; i < MAX_EPS_CHANNELS; i++) {
  21732. + gr->dtxfsiz_local[i] =
  21733. + DWC_READ_REG32(&(core_if->core_global_regs->dtxfsiz[i]));
  21734. + }
  21735. +
  21736. + DWC_DEBUGPL(DBG_ANY, "===========Backing Global registers==========\n");
  21737. + DWC_DEBUGPL(DBG_ANY, "Backed up gotgctl = %08x\n", gr->gotgctl_local);
  21738. + DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk = %08x\n", gr->gintmsk_local);
  21739. + DWC_DEBUGPL(DBG_ANY, "Backed up gahbcfg = %08x\n", gr->gahbcfg_local);
  21740. + DWC_DEBUGPL(DBG_ANY, "Backed up gusbcfg = %08x\n", gr->gusbcfg_local);
  21741. + DWC_DEBUGPL(DBG_ANY, "Backed up grxfsiz = %08x\n", gr->grxfsiz_local);
  21742. + DWC_DEBUGPL(DBG_ANY, "Backed up gnptxfsiz = %08x\n",
  21743. + gr->gnptxfsiz_local);
  21744. + DWC_DEBUGPL(DBG_ANY, "Backed up hptxfsiz = %08x\n",
  21745. + gr->hptxfsiz_local);
  21746. +#ifdef CONFIG_USB_DWC_OTG_LPM
  21747. + DWC_DEBUGPL(DBG_ANY, "Backed up glpmcfg = %08x\n", gr->glpmcfg_local);
  21748. +#endif
  21749. + DWC_DEBUGPL(DBG_ANY, "Backed up gi2cctl = %08x\n", gr->gi2cctl_local);
  21750. + DWC_DEBUGPL(DBG_ANY, "Backed up pcgcctl = %08x\n", gr->pcgcctl_local);
  21751. + DWC_DEBUGPL(DBG_ANY,"Backed up gdfifocfg = %08x\n",gr->gdfifocfg_local);
  21752. +
  21753. + return 0;
  21754. +}
  21755. +
  21756. +/** Saves GINTMSK register before setting the msk bits. */
  21757. +int dwc_otg_save_gintmsk_reg(dwc_otg_core_if_t * core_if)
  21758. +{
  21759. + struct dwc_otg_global_regs_backup *gr;
  21760. +
  21761. + gr = core_if->gr_backup;
  21762. + if (!gr) {
  21763. + gr = DWC_ALLOC(sizeof(*gr));
  21764. + if (!gr) {
  21765. + return -DWC_E_NO_MEMORY;
  21766. + }
  21767. + core_if->gr_backup = gr;
  21768. + }
  21769. +
  21770. + gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
  21771. +
  21772. + DWC_DEBUGPL(DBG_ANY,"=============Backing GINTMSK registers============\n");
  21773. + DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk = %08x\n", gr->gintmsk_local);
  21774. +
  21775. + return 0;
  21776. +}
  21777. +
  21778. +int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if)
  21779. +{
  21780. + struct dwc_otg_dev_regs_backup *dr;
  21781. + int i;
  21782. +
  21783. + dr = core_if->dr_backup;
  21784. + if (!dr) {
  21785. + dr = DWC_ALLOC(sizeof(*dr));
  21786. + if (!dr) {
  21787. + return -DWC_E_NO_MEMORY;
  21788. + }
  21789. + core_if->dr_backup = dr;
  21790. + }
  21791. +
  21792. + dr->dcfg = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
  21793. + dr->dctl = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
  21794. + dr->daintmsk =
  21795. + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
  21796. + dr->diepmsk =
  21797. + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->diepmsk);
  21798. + dr->doepmsk =
  21799. + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->doepmsk);
  21800. +
  21801. + for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
  21802. + dr->diepctl[i] =
  21803. + DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl);
  21804. + dr->dieptsiz[i] =
  21805. + DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz);
  21806. + dr->diepdma[i] =
  21807. + DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma);
  21808. + }
  21809. +
  21810. + DWC_DEBUGPL(DBG_ANY,
  21811. + "=============Backing Host registers==============\n");
  21812. + DWC_DEBUGPL(DBG_ANY, "Backed up dcfg = %08x\n", dr->dcfg);
  21813. + DWC_DEBUGPL(DBG_ANY, "Backed up dctl = %08x\n", dr->dctl);
  21814. + DWC_DEBUGPL(DBG_ANY, "Backed up daintmsk = %08x\n",
  21815. + dr->daintmsk);
  21816. + DWC_DEBUGPL(DBG_ANY, "Backed up diepmsk = %08x\n", dr->diepmsk);
  21817. + DWC_DEBUGPL(DBG_ANY, "Backed up doepmsk = %08x\n", dr->doepmsk);
  21818. + for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
  21819. + DWC_DEBUGPL(DBG_ANY, "Backed up diepctl[%d] = %08x\n", i,
  21820. + dr->diepctl[i]);
  21821. + DWC_DEBUGPL(DBG_ANY, "Backed up dieptsiz[%d] = %08x\n",
  21822. + i, dr->dieptsiz[i]);
  21823. + DWC_DEBUGPL(DBG_ANY, "Backed up diepdma[%d] = %08x\n", i,
  21824. + dr->diepdma[i]);
  21825. + }
  21826. +
  21827. + return 0;
  21828. +}
  21829. +
  21830. +int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if)
  21831. +{
  21832. + struct dwc_otg_host_regs_backup *hr;
  21833. + int i;
  21834. +
  21835. + hr = core_if->hr_backup;
  21836. + if (!hr) {
  21837. + hr = DWC_ALLOC(sizeof(*hr));
  21838. + if (!hr) {
  21839. + return -DWC_E_NO_MEMORY;
  21840. + }
  21841. + core_if->hr_backup = hr;
  21842. + }
  21843. +
  21844. + hr->hcfg_local =
  21845. + DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
  21846. + hr->haintmsk_local =
  21847. + DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk);
  21848. + for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {
  21849. + hr->hcintmsk_local[i] =
  21850. + DWC_READ_REG32(&core_if->host_if->hc_regs[i]->hcintmsk);
  21851. + }
  21852. + hr->hprt0_local = DWC_READ_REG32(core_if->host_if->hprt0);
  21853. + hr->hfir_local =
  21854. + DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);
  21855. +
  21856. + DWC_DEBUGPL(DBG_ANY,
  21857. + "=============Backing Host registers===============\n");
  21858. + DWC_DEBUGPL(DBG_ANY, "Backed up hcfg = %08x\n",
  21859. + hr->hcfg_local);
  21860. + DWC_DEBUGPL(DBG_ANY, "Backed up haintmsk = %08x\n", hr->haintmsk_local);
  21861. + for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {
  21862. + DWC_DEBUGPL(DBG_ANY, "Backed up hcintmsk[%02d]=%08x\n", i,
  21863. + hr->hcintmsk_local[i]);
  21864. + }
  21865. + DWC_DEBUGPL(DBG_ANY, "Backed up hprt0 = %08x\n",
  21866. + hr->hprt0_local);
  21867. + DWC_DEBUGPL(DBG_ANY, "Backed up hfir = %08x\n",
  21868. + hr->hfir_local);
  21869. +
  21870. + return 0;
  21871. +}
  21872. +
  21873. +int dwc_otg_restore_global_regs(dwc_otg_core_if_t *core_if)
  21874. +{
  21875. + struct dwc_otg_global_regs_backup *gr;
  21876. + int i;
  21877. +
  21878. + gr = core_if->gr_backup;
  21879. + if (!gr) {
  21880. + return -DWC_E_INVALID;
  21881. + }
  21882. +
  21883. + DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, gr->gotgctl_local);
  21884. + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gr->gintmsk_local);
  21885. + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gr->gusbcfg_local);
  21886. + DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gr->gahbcfg_local);
  21887. + DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, gr->grxfsiz_local);
  21888. + DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz,
  21889. + gr->gnptxfsiz_local);
  21890. + DWC_WRITE_REG32(&core_if->core_global_regs->hptxfsiz,
  21891. + gr->hptxfsiz_local);
  21892. + DWC_WRITE_REG32(&core_if->core_global_regs->gdfifocfg,
  21893. + gr->gdfifocfg_local);
  21894. + for (i = 0; i < MAX_EPS_CHANNELS; i++) {
  21895. + DWC_WRITE_REG32(&core_if->core_global_regs->dtxfsiz[i],
  21896. + gr->dtxfsiz_local[i]);
  21897. + }
  21898. +
  21899. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
  21900. + DWC_WRITE_REG32(core_if->host_if->hprt0, 0x0000100A);
  21901. + DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg,
  21902. + (gr->gahbcfg_local));
  21903. + return 0;
  21904. +}
  21905. +
  21906. +int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, int rem_wakeup)
  21907. +{
  21908. + struct dwc_otg_dev_regs_backup *dr;
  21909. + int i;
  21910. +
  21911. + dr = core_if->dr_backup;
  21912. +
  21913. + if (!dr) {
  21914. + return -DWC_E_INVALID;
  21915. + }
  21916. +
  21917. + if (!rem_wakeup) {
  21918. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
  21919. + dr->dctl);
  21920. + }
  21921. +
  21922. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, dr->daintmsk);
  21923. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, dr->diepmsk);
  21924. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, dr->doepmsk);
  21925. +
  21926. + for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
  21927. + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz, dr->dieptsiz[i]);
  21928. + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma, dr->diepdma[i]);
  21929. + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl, dr->diepctl[i]);
  21930. + }
  21931. +
  21932. + return 0;
  21933. +}
  21934. +
  21935. +int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset)
  21936. +{
  21937. + struct dwc_otg_host_regs_backup *hr;
  21938. + int i;
  21939. + hr = core_if->hr_backup;
  21940. +
  21941. + if (!hr) {
  21942. + return -DWC_E_INVALID;
  21943. + }
  21944. +
  21945. + DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hr->hcfg_local);
  21946. + //if (!reset)
  21947. + //{
  21948. + // DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hr->hfir_local);
  21949. + //}
  21950. +
  21951. + DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk,
  21952. + hr->haintmsk_local);
  21953. + for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) {
  21954. + DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk,
  21955. + hr->hcintmsk_local[i]);
  21956. + }
  21957. +
  21958. + return 0;
  21959. +}
  21960. +
  21961. +int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if)
  21962. +{
  21963. + struct dwc_otg_global_regs_backup *gr;
  21964. +
  21965. + gr = core_if->gr_backup;
  21966. +
  21967. + /* Restore values for LPM and I2C */
  21968. +#ifdef CONFIG_USB_DWC_OTG_LPM
  21969. + DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, gr->glpmcfg_local);
  21970. +#endif
  21971. + DWC_WRITE_REG32(&core_if->core_global_regs->gi2cctl, gr->gi2cctl_local);
  21972. +
  21973. + return 0;
  21974. +}
  21975. +
  21976. +int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode, int is_host)
  21977. +{
  21978. + struct dwc_otg_global_regs_backup *gr;
  21979. + pcgcctl_data_t pcgcctl = {.d32 = 0 };
  21980. + gahbcfg_data_t gahbcfg = {.d32 = 0 };
  21981. + gusbcfg_data_t gusbcfg = {.d32 = 0 };
  21982. + gintmsk_data_t gintmsk = {.d32 = 0 };
  21983. +
  21984. + /* Restore LPM and I2C registers */
  21985. + restore_lpm_i2c_regs(core_if);
  21986. +
  21987. + /* Set PCGCCTL to 0 */
  21988. + DWC_WRITE_REG32(core_if->pcgcctl, 0x00000000);
  21989. +
  21990. + gr = core_if->gr_backup;
  21991. + /* Load restore values for [31:14] bits */
  21992. + DWC_WRITE_REG32(core_if->pcgcctl,
  21993. + ((gr->pcgcctl_local & 0xffffc000) | 0x00020000));
  21994. +
  21995. + /* Umnask global Interrupt in GAHBCFG and restore it */
  21996. + gahbcfg.d32 = gr->gahbcfg_local;
  21997. + gahbcfg.b.glblintrmsk = 1;
  21998. + DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32);
  21999. +
  22000. + /* Clear all pending interupts */
  22001. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
  22002. +
  22003. + /* Unmask restore done interrupt */
  22004. + gintmsk.b.restoredone = 1;
  22005. + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
  22006. +
  22007. + /* Restore GUSBCFG and HCFG/DCFG */
  22008. + gusbcfg.d32 = core_if->gr_backup->gusbcfg_local;
  22009. + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32);
  22010. +
  22011. + if (is_host) {
  22012. + hcfg_data_t hcfg = {.d32 = 0 };
  22013. + hcfg.d32 = core_if->hr_backup->hcfg_local;
  22014. + DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg,
  22015. + hcfg.d32);
  22016. +
  22017. + /* Load restore values for [31:14] bits */
  22018. + pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
  22019. + pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;
  22020. +
  22021. + if (rmode)
  22022. + pcgcctl.b.restoremode = 1;
  22023. + DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
  22024. + dwc_udelay(10);
  22025. +
  22026. + /* Load restore values for [31:14] bits and set EssRegRestored bit */
  22027. + pcgcctl.d32 = gr->pcgcctl_local | 0xffffc000;
  22028. + pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
  22029. + pcgcctl.b.ess_reg_restored = 1;
  22030. + if (rmode)
  22031. + pcgcctl.b.restoremode = 1;
  22032. + DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
  22033. + } else {
  22034. + dcfg_data_t dcfg = {.d32 = 0 };
  22035. + dcfg.d32 = core_if->dr_backup->dcfg;
  22036. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
  22037. +
  22038. + /* Load restore values for [31:14] bits */
  22039. + pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
  22040. + pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;
  22041. + if (!rmode) {
  22042. + pcgcctl.d32 |= 0x208;
  22043. + }
  22044. + DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
  22045. + dwc_udelay(10);
  22046. +
  22047. + /* Load restore values for [31:14] bits */
  22048. + pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000;
  22049. + pcgcctl.d32 = gr->pcgcctl_local | 0x00020000;
  22050. + pcgcctl.b.ess_reg_restored = 1;
  22051. + if (!rmode)
  22052. + pcgcctl.d32 |= 0x208;
  22053. + DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
  22054. + }
  22055. +
  22056. + return 0;
  22057. +}
  22058. +
  22059. +/**
  22060. + * Initializes the FSLSPClkSel field of the HCFG register depending on the PHY
  22061. + * type.
  22062. + */
  22063. +static void init_fslspclksel(dwc_otg_core_if_t * core_if)
  22064. +{
  22065. + uint32_t val;
  22066. + hcfg_data_t hcfg;
  22067. +
  22068. + if (((core_if->hwcfg2.b.hs_phy_type == 2) &&
  22069. + (core_if->hwcfg2.b.fs_phy_type == 1) &&
  22070. + (core_if->core_params->ulpi_fs_ls)) ||
  22071. + (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
  22072. + /* Full speed PHY */
  22073. + val = DWC_HCFG_48_MHZ;
  22074. + } else {
  22075. + /* High speed PHY running at full speed or high speed */
  22076. + val = DWC_HCFG_30_60_MHZ;
  22077. + }
  22078. +
  22079. + DWC_DEBUGPL(DBG_CIL, "Initializing HCFG.FSLSPClkSel to 0x%1x\n", val);
  22080. + hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
  22081. + hcfg.b.fslspclksel = val;
  22082. + DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32);
  22083. +}
  22084. +
  22085. +/**
  22086. + * Initializes the DevSpd field of the DCFG register depending on the PHY type
  22087. + * and the enumeration speed of the device.
  22088. + */
  22089. +static void init_devspd(dwc_otg_core_if_t * core_if)
  22090. +{
  22091. + uint32_t val;
  22092. + dcfg_data_t dcfg;
  22093. +
  22094. + if (((core_if->hwcfg2.b.hs_phy_type == 2) &&
  22095. + (core_if->hwcfg2.b.fs_phy_type == 1) &&
  22096. + (core_if->core_params->ulpi_fs_ls)) ||
  22097. + (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
  22098. + /* Full speed PHY */
  22099. + val = 0x3;
  22100. + } else if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
  22101. + /* High speed PHY running at full speed */
  22102. + val = 0x1;
  22103. + } else {
  22104. + /* High speed PHY running at high speed */
  22105. + val = 0x0;
  22106. + }
  22107. +
  22108. + DWC_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val);
  22109. +
  22110. + dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
  22111. + dcfg.b.devspd = val;
  22112. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
  22113. +}
  22114. +
  22115. +/**
  22116. + * This function calculates the number of IN EPS
  22117. + * using GHWCFG1 and GHWCFG2 registers values
  22118. + *
  22119. + * @param core_if Programming view of the DWC_otg controller
  22120. + */
  22121. +static uint32_t calc_num_in_eps(dwc_otg_core_if_t * core_if)
  22122. +{
  22123. + uint32_t num_in_eps = 0;
  22124. + uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep;
  22125. + uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 3;
  22126. + uint32_t num_tx_fifos = core_if->hwcfg4.b.num_in_eps;
  22127. + int i;
  22128. +
  22129. + for (i = 0; i < num_eps; ++i) {
  22130. + if (!(hwcfg1 & 0x1))
  22131. + num_in_eps++;
  22132. +
  22133. + hwcfg1 >>= 2;
  22134. + }
  22135. +
  22136. + if (core_if->hwcfg4.b.ded_fifo_en) {
  22137. + num_in_eps =
  22138. + (num_in_eps > num_tx_fifos) ? num_tx_fifos : num_in_eps;
  22139. + }
  22140. +
  22141. + return num_in_eps;
  22142. +}
  22143. +
  22144. +/**
  22145. + * This function calculates the number of OUT EPS
  22146. + * using GHWCFG1 and GHWCFG2 registers values
  22147. + *
  22148. + * @param core_if Programming view of the DWC_otg controller
  22149. + */
  22150. +static uint32_t calc_num_out_eps(dwc_otg_core_if_t * core_if)
  22151. +{
  22152. + uint32_t num_out_eps = 0;
  22153. + uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep;
  22154. + uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 2;
  22155. + int i;
  22156. +
  22157. + for (i = 0; i < num_eps; ++i) {
  22158. + if (!(hwcfg1 & 0x1))
  22159. + num_out_eps++;
  22160. +
  22161. + hwcfg1 >>= 2;
  22162. + }
  22163. + return num_out_eps;
  22164. +}
  22165. +
  22166. +/**
  22167. + * This function initializes the DWC_otg controller registers and
  22168. + * prepares the core for device mode or host mode operation.
  22169. + *
  22170. + * @param core_if Programming view of the DWC_otg controller
  22171. + *
  22172. + */
  22173. +void dwc_otg_core_init(dwc_otg_core_if_t * core_if)
  22174. +{
  22175. + int i = 0;
  22176. + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
  22177. + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
  22178. + gahbcfg_data_t ahbcfg = {.d32 = 0 };
  22179. + gusbcfg_data_t usbcfg = {.d32 = 0 };
  22180. + gi2cctl_data_t i2cctl = {.d32 = 0 };
  22181. +
  22182. + DWC_DEBUGPL(DBG_CILV, "dwc_otg_core_init(%p) regs at %p\n",
  22183. + core_if, global_regs);
  22184. +
  22185. + /* Common Initialization */
  22186. + usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
  22187. +
  22188. + /* Program the ULPI External VBUS bit if needed */
  22189. + usbcfg.b.ulpi_ext_vbus_drv =
  22190. + (core_if->core_params->phy_ulpi_ext_vbus ==
  22191. + DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0;
  22192. +
  22193. + /* Set external TS Dline pulsing */
  22194. + usbcfg.b.term_sel_dl_pulse =
  22195. + (core_if->core_params->ts_dline == 1) ? 1 : 0;
  22196. + DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
  22197. +
  22198. + /* Reset the Controller */
  22199. + dwc_otg_core_reset(core_if);
  22200. +
  22201. + core_if->adp_enable = core_if->core_params->adp_supp_enable;
  22202. + core_if->power_down = core_if->core_params->power_down;
  22203. + core_if->otg_sts = 0;
  22204. +
  22205. + /* Initialize parameters from Hardware configuration registers. */
  22206. + dev_if->num_in_eps = calc_num_in_eps(core_if);
  22207. + dev_if->num_out_eps = calc_num_out_eps(core_if);
  22208. +
  22209. + DWC_DEBUGPL(DBG_CIL, "num_dev_perio_in_ep=%d\n",
  22210. + core_if->hwcfg4.b.num_dev_perio_in_ep);
  22211. +
  22212. + for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {
  22213. + dev_if->perio_tx_fifo_size[i] =
  22214. + DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16;
  22215. + DWC_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n",
  22216. + i, dev_if->perio_tx_fifo_size[i]);
  22217. + }
  22218. +
  22219. + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
  22220. + dev_if->tx_fifo_size[i] =
  22221. + DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16;
  22222. + DWC_DEBUGPL(DBG_CIL, "Tx FIFO SZ #%d=0x%0x\n",
  22223. + i, dev_if->tx_fifo_size[i]);
  22224. + }
  22225. +
  22226. + core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth;
  22227. + core_if->rx_fifo_size = DWC_READ_REG32(&global_regs->grxfsiz);
  22228. + core_if->nperio_tx_fifo_size =
  22229. + DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16;
  22230. +
  22231. + DWC_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", core_if->total_fifo_size);
  22232. + DWC_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", core_if->rx_fifo_size);
  22233. + DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO SZ=%d\n",
  22234. + core_if->nperio_tx_fifo_size);
  22235. +
  22236. + /* This programming sequence needs to happen in FS mode before any other
  22237. + * programming occurs */
  22238. + if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) &&
  22239. + (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
  22240. + /* If FS mode with FS PHY */
  22241. +
  22242. + /* core_init() is now called on every switch so only call the
  22243. + * following for the first time through. */
  22244. + if (!core_if->phy_init_done) {
  22245. + core_if->phy_init_done = 1;
  22246. + DWC_DEBUGPL(DBG_CIL, "FS_PHY detected\n");
  22247. + usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
  22248. + usbcfg.b.physel = 1;
  22249. + DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
  22250. +
  22251. + /* Reset after a PHY select */
  22252. + dwc_otg_core_reset(core_if);
  22253. + }
  22254. +
  22255. + /* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also
  22256. + * do this on HNP Dev/Host mode switches (done in dev_init and
  22257. + * host_init). */
  22258. + if (dwc_otg_is_host_mode(core_if)) {
  22259. + init_fslspclksel(core_if);
  22260. + } else {
  22261. + init_devspd(core_if);
  22262. + }
  22263. +
  22264. + if (core_if->core_params->i2c_enable) {
  22265. + DWC_DEBUGPL(DBG_CIL, "FS_PHY Enabling I2c\n");
  22266. + /* Program GUSBCFG.OtgUtmifsSel to I2C */
  22267. + usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
  22268. + usbcfg.b.otgutmifssel = 1;
  22269. + DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
  22270. +
  22271. + /* Program GI2CCTL.I2CEn */
  22272. + i2cctl.d32 = DWC_READ_REG32(&global_regs->gi2cctl);
  22273. + i2cctl.b.i2cdevaddr = 1;
  22274. + i2cctl.b.i2cen = 0;
  22275. + DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32);
  22276. + i2cctl.b.i2cen = 1;
  22277. + DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32);
  22278. + }
  22279. +
  22280. + } /* endif speed == DWC_SPEED_PARAM_FULL */
  22281. + else {
  22282. + /* High speed PHY. */
  22283. + if (!core_if->phy_init_done) {
  22284. + core_if->phy_init_done = 1;
  22285. + /* HS PHY parameters. These parameters are preserved
  22286. + * during soft reset so only program the first time. Do
  22287. + * a soft reset immediately after setting phyif. */
  22288. +
  22289. + if (core_if->core_params->phy_type == 2) {
  22290. + /* ULPI interface */
  22291. + usbcfg.b.ulpi_utmi_sel = 1;
  22292. + usbcfg.b.phyif = 0;
  22293. + usbcfg.b.ddrsel =
  22294. + core_if->core_params->phy_ulpi_ddr;
  22295. + } else if (core_if->core_params->phy_type == 1) {
  22296. + /* UTMI+ interface */
  22297. + usbcfg.b.ulpi_utmi_sel = 0;
  22298. + if (core_if->core_params->phy_utmi_width == 16) {
  22299. + usbcfg.b.phyif = 1;
  22300. +
  22301. + } else {
  22302. + usbcfg.b.phyif = 0;
  22303. + }
  22304. + } else {
  22305. + DWC_ERROR("FS PHY TYPE\n");
  22306. + }
  22307. + DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
  22308. + /* Reset after setting the PHY parameters */
  22309. + dwc_otg_core_reset(core_if);
  22310. + }
  22311. + }
  22312. +
  22313. + if ((core_if->hwcfg2.b.hs_phy_type == 2) &&
  22314. + (core_if->hwcfg2.b.fs_phy_type == 1) &&
  22315. + (core_if->core_params->ulpi_fs_ls)) {
  22316. + DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS\n");
  22317. + usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
  22318. + usbcfg.b.ulpi_fsls = 1;
  22319. + usbcfg.b.ulpi_clk_sus_m = 1;
  22320. + DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
  22321. + } else {
  22322. + usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
  22323. + usbcfg.b.ulpi_fsls = 0;
  22324. + usbcfg.b.ulpi_clk_sus_m = 0;
  22325. + DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
  22326. + }
  22327. +
  22328. + /* Program the GAHBCFG Register. */
  22329. + switch (core_if->hwcfg2.b.architecture) {
  22330. +
  22331. + case DWC_SLAVE_ONLY_ARCH:
  22332. + DWC_DEBUGPL(DBG_CIL, "Slave Only Mode\n");
  22333. + ahbcfg.b.nptxfemplvl_txfemplvl =
  22334. + DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
  22335. + ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
  22336. + core_if->dma_enable = 0;
  22337. + core_if->dma_desc_enable = 0;
  22338. + break;
  22339. +
  22340. + case DWC_EXT_DMA_ARCH:
  22341. + DWC_DEBUGPL(DBG_CIL, "External DMA Mode\n");
  22342. + {
  22343. + uint8_t brst_sz = core_if->core_params->dma_burst_size;
  22344. + ahbcfg.b.hburstlen = 0;
  22345. + while (brst_sz > 1) {
  22346. + ahbcfg.b.hburstlen++;
  22347. + brst_sz >>= 1;
  22348. + }
  22349. + }
  22350. + core_if->dma_enable = (core_if->core_params->dma_enable != 0);
  22351. + core_if->dma_desc_enable =
  22352. + (core_if->core_params->dma_desc_enable != 0);
  22353. + break;
  22354. +
  22355. + case DWC_INT_DMA_ARCH:
  22356. + DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n");
  22357. + /* Old value was DWC_GAHBCFG_INT_DMA_BURST_INCR - done for
  22358. + Host mode ISOC in issue fix - vahrama */
  22359. + /* Broadcom had altered to (1<<3)|(0<<0) - WRESP=1, max 4 beats */
  22360. + ahbcfg.b.hburstlen = (1<<3)|(0<<0);//DWC_GAHBCFG_INT_DMA_BURST_INCR4;
  22361. + core_if->dma_enable = (core_if->core_params->dma_enable != 0);
  22362. + core_if->dma_desc_enable =
  22363. + (core_if->core_params->dma_desc_enable != 0);
  22364. + break;
  22365. +
  22366. + }
  22367. + if (core_if->dma_enable) {
  22368. + if (core_if->dma_desc_enable) {
  22369. + DWC_PRINTF("Using Descriptor DMA mode\n");
  22370. + } else {
  22371. + DWC_PRINTF("Using Buffer DMA mode\n");
  22372. +
  22373. + }
  22374. + } else {
  22375. + DWC_PRINTF("Using Slave mode\n");
  22376. + core_if->dma_desc_enable = 0;
  22377. + }
  22378. +
  22379. + if (core_if->core_params->ahb_single) {
  22380. + ahbcfg.b.ahbsingle = 1;
  22381. + }
  22382. +
  22383. + ahbcfg.b.dmaenable = core_if->dma_enable;
  22384. + DWC_WRITE_REG32(&global_regs->gahbcfg, ahbcfg.d32);
  22385. +
  22386. + core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en;
  22387. +
  22388. + core_if->pti_enh_enable = core_if->core_params->pti_enable != 0;
  22389. + core_if->multiproc_int_enable = core_if->core_params->mpi_enable;
  22390. + DWC_PRINTF("Periodic Transfer Interrupt Enhancement - %s\n",
  22391. + ((core_if->pti_enh_enable) ? "enabled" : "disabled"));
  22392. + DWC_PRINTF("Multiprocessor Interrupt Enhancement - %s\n",
  22393. + ((core_if->multiproc_int_enable) ? "enabled" : "disabled"));
  22394. +
  22395. + /*
  22396. + * Program the GUSBCFG register.
  22397. + */
  22398. + usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
  22399. +
  22400. + switch (core_if->hwcfg2.b.op_mode) {
  22401. + case DWC_MODE_HNP_SRP_CAPABLE:
  22402. + usbcfg.b.hnpcap = (core_if->core_params->otg_cap ==
  22403. + DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
  22404. + usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
  22405. + DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
  22406. + break;
  22407. +
  22408. + case DWC_MODE_SRP_ONLY_CAPABLE:
  22409. + usbcfg.b.hnpcap = 0;
  22410. + usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
  22411. + DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
  22412. + break;
  22413. +
  22414. + case DWC_MODE_NO_HNP_SRP_CAPABLE:
  22415. + usbcfg.b.hnpcap = 0;
  22416. + usbcfg.b.srpcap = 0;
  22417. + break;
  22418. +
  22419. + case DWC_MODE_SRP_CAPABLE_DEVICE:
  22420. + usbcfg.b.hnpcap = 0;
  22421. + usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
  22422. + DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
  22423. + break;
  22424. +
  22425. + case DWC_MODE_NO_SRP_CAPABLE_DEVICE:
  22426. + usbcfg.b.hnpcap = 0;
  22427. + usbcfg.b.srpcap = 0;
  22428. + break;
  22429. +
  22430. + case DWC_MODE_SRP_CAPABLE_HOST:
  22431. + usbcfg.b.hnpcap = 0;
  22432. + usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
  22433. + DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
  22434. + break;
  22435. +
  22436. + case DWC_MODE_NO_SRP_CAPABLE_HOST:
  22437. + usbcfg.b.hnpcap = 0;
  22438. + usbcfg.b.srpcap = 0;
  22439. + break;
  22440. + }
  22441. +
  22442. + DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
  22443. +
  22444. +#ifdef CONFIG_USB_DWC_OTG_LPM
  22445. + if (core_if->core_params->lpm_enable) {
  22446. + glpmcfg_data_t lpmcfg = {.d32 = 0 };
  22447. +
  22448. + /* To enable LPM support set lpm_cap_en bit */
  22449. + lpmcfg.b.lpm_cap_en = 1;
  22450. +
  22451. + /* Make AppL1Res ACK */
  22452. + lpmcfg.b.appl_resp = 1;
  22453. +
  22454. + /* Retry 3 times */
  22455. + lpmcfg.b.retry_count = 3;
  22456. +
  22457. + DWC_MODIFY_REG32(&core_if->core_global_regs->glpmcfg,
  22458. + 0, lpmcfg.d32);
  22459. +
  22460. + }
  22461. +#endif
  22462. + if (core_if->core_params->ic_usb_cap) {
  22463. + gusbcfg_data_t gusbcfg = {.d32 = 0 };
  22464. + gusbcfg.b.ic_usb_cap = 1;
  22465. + DWC_MODIFY_REG32(&core_if->core_global_regs->gusbcfg,
  22466. + 0, gusbcfg.d32);
  22467. + }
  22468. + {
  22469. + gotgctl_data_t gotgctl = {.d32 = 0 };
  22470. + gotgctl.b.otgver = core_if->core_params->otg_ver;
  22471. + DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, 0,
  22472. + gotgctl.d32);
  22473. + /* Set OTG version supported */
  22474. + core_if->otg_ver = core_if->core_params->otg_ver;
  22475. + DWC_PRINTF("OTG VER PARAM: %d, OTG VER FLAG: %d\n",
  22476. + core_if->core_params->otg_ver, core_if->otg_ver);
  22477. + }
  22478. +
  22479. +
  22480. + /* Enable common interrupts */
  22481. + dwc_otg_enable_common_interrupts(core_if);
  22482. +
  22483. + /* Do device or host intialization based on mode during PCD
  22484. + * and HCD initialization */
  22485. + if (dwc_otg_is_host_mode(core_if)) {
  22486. + DWC_DEBUGPL(DBG_ANY, "Host Mode\n");
  22487. + core_if->op_state = A_HOST;
  22488. + } else {
  22489. + DWC_DEBUGPL(DBG_ANY, "Device Mode\n");
  22490. + core_if->op_state = B_PERIPHERAL;
  22491. +#ifdef DWC_DEVICE_ONLY
  22492. + dwc_otg_core_dev_init(core_if);
  22493. +#endif
  22494. + }
  22495. +}
  22496. +
  22497. +/**
  22498. + * This function enables the Device mode interrupts.
  22499. + *
  22500. + * @param core_if Programming view of DWC_otg controller
  22501. + */
  22502. +void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if)
  22503. +{
  22504. + gintmsk_data_t intr_mask = {.d32 = 0 };
  22505. + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
  22506. +
  22507. + DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__);
  22508. +
  22509. + /* Disable all interrupts. */
  22510. + DWC_WRITE_REG32(&global_regs->gintmsk, 0);
  22511. +
  22512. + /* Clear any pending interrupts */
  22513. + DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
  22514. +
  22515. + /* Enable the common interrupts */
  22516. + dwc_otg_enable_common_interrupts(core_if);
  22517. +
  22518. + /* Enable interrupts */
  22519. + intr_mask.b.usbreset = 1;
  22520. + intr_mask.b.enumdone = 1;
  22521. + /* Disable Disconnect interrupt in Device mode */
  22522. + intr_mask.b.disconnect = 0;
  22523. +
  22524. + if (!core_if->multiproc_int_enable) {
  22525. + intr_mask.b.inepintr = 1;
  22526. + intr_mask.b.outepintr = 1;
  22527. + }
  22528. +
  22529. + intr_mask.b.erlysuspend = 1;
  22530. +
  22531. + if (core_if->en_multiple_tx_fifo == 0) {
  22532. + intr_mask.b.epmismatch = 1;
  22533. + }
  22534. +
  22535. + //intr_mask.b.incomplisoout = 1;
  22536. + intr_mask.b.incomplisoin = 1;
  22537. +
  22538. +/* Enable the ignore frame number for ISOC xfers - MAS */
  22539. +/* Disable to support high bandwith ISOC transfers - manukz */
  22540. +#if 0
  22541. +#ifdef DWC_UTE_PER_IO
  22542. + if (core_if->dma_enable) {
  22543. + if (core_if->dma_desc_enable) {
  22544. + dctl_data_t dctl1 = {.d32 = 0 };
  22545. + dctl1.b.ifrmnum = 1;
  22546. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
  22547. + dctl, 0, dctl1.d32);
  22548. + DWC_DEBUG("----Enabled Ignore frame number (0x%08x)",
  22549. + DWC_READ_REG32(&core_if->dev_if->
  22550. + dev_global_regs->dctl));
  22551. + }
  22552. + }
  22553. +#endif
  22554. +#endif
  22555. +#ifdef DWC_EN_ISOC
  22556. + if (core_if->dma_enable) {
  22557. + if (core_if->dma_desc_enable == 0) {
  22558. + if (core_if->pti_enh_enable) {
  22559. + dctl_data_t dctl = {.d32 = 0 };
  22560. + dctl.b.ifrmnum = 1;
  22561. + DWC_MODIFY_REG32(&core_if->
  22562. + dev_if->dev_global_regs->dctl,
  22563. + 0, dctl.d32);
  22564. + } else {
  22565. + intr_mask.b.incomplisoin = 1;
  22566. + intr_mask.b.incomplisoout = 1;
  22567. + }
  22568. + }
  22569. + } else {
  22570. + intr_mask.b.incomplisoin = 1;
  22571. + intr_mask.b.incomplisoout = 1;
  22572. + }
  22573. +#endif /* DWC_EN_ISOC */
  22574. +
  22575. + /** @todo NGS: Should this be a module parameter? */
  22576. +#ifdef USE_PERIODIC_EP
  22577. + intr_mask.b.isooutdrop = 1;
  22578. + intr_mask.b.eopframe = 1;
  22579. + intr_mask.b.incomplisoin = 1;
  22580. + intr_mask.b.incomplisoout = 1;
  22581. +#endif
  22582. +
  22583. + DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
  22584. +
  22585. + DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__,
  22586. + DWC_READ_REG32(&global_regs->gintmsk));
  22587. +}
  22588. +
  22589. +/**
  22590. + * This function initializes the DWC_otg controller registers for
  22591. + * device mode.
  22592. + *
  22593. + * @param core_if Programming view of DWC_otg controller
  22594. + *
  22595. + */
  22596. +void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if)
  22597. +{
  22598. + int i;
  22599. + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
  22600. + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
  22601. + dwc_otg_core_params_t *params = core_if->core_params;
  22602. + dcfg_data_t dcfg = {.d32 = 0 };
  22603. + depctl_data_t diepctl = {.d32 = 0 };
  22604. + grstctl_t resetctl = {.d32 = 0 };
  22605. + uint32_t rx_fifo_size;
  22606. + fifosize_data_t nptxfifosize;
  22607. + fifosize_data_t txfifosize;
  22608. + dthrctl_data_t dthrctl;
  22609. + fifosize_data_t ptxfifosize;
  22610. + uint16_t rxfsiz, nptxfsiz;
  22611. + gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
  22612. + hwcfg3_data_t hwcfg3 = {.d32 = 0 };
  22613. +
  22614. + /* Restart the Phy Clock */
  22615. + DWC_WRITE_REG32(core_if->pcgcctl, 0);
  22616. +
  22617. + /* Device configuration register */
  22618. + init_devspd(core_if);
  22619. + dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
  22620. + dcfg.b.descdma = (core_if->dma_desc_enable) ? 1 : 0;
  22621. + dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80;
  22622. + /* Enable Device OUT NAK in case of DDMA mode*/
  22623. + if (core_if->core_params->dev_out_nak) {
  22624. + dcfg.b.endevoutnak = 1;
  22625. + }
  22626. +
  22627. + if (core_if->core_params->cont_on_bna) {
  22628. + dctl_data_t dctl = {.d32 = 0 };
  22629. + dctl.b.encontonbna = 1;
  22630. + DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32);
  22631. + }
  22632. +
  22633. +
  22634. + DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
  22635. +
  22636. + /* Configure data FIFO sizes */
  22637. + if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
  22638. + DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n",
  22639. + core_if->total_fifo_size);
  22640. + DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n",
  22641. + params->dev_rx_fifo_size);
  22642. + DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n",
  22643. + params->dev_nperio_tx_fifo_size);
  22644. +
  22645. + /* Rx FIFO */
  22646. + DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",
  22647. + DWC_READ_REG32(&global_regs->grxfsiz));
  22648. +
  22649. +#ifdef DWC_UTE_CFI
  22650. + core_if->pwron_rxfsiz = DWC_READ_REG32(&global_regs->grxfsiz);
  22651. + core_if->init_rxfsiz = params->dev_rx_fifo_size;
  22652. +#endif
  22653. + rx_fifo_size = params->dev_rx_fifo_size;
  22654. + DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size);
  22655. +
  22656. + DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n",
  22657. + DWC_READ_REG32(&global_regs->grxfsiz));
  22658. +
  22659. + /** Set Periodic Tx FIFO Mask all bits 0 */
  22660. + core_if->p_tx_msk = 0;
  22661. +
  22662. + /** Set Tx FIFO Mask all bits 0 */
  22663. + core_if->tx_msk = 0;
  22664. +
  22665. + if (core_if->en_multiple_tx_fifo == 0) {
  22666. + /* Non-periodic Tx FIFO */
  22667. + DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
  22668. + DWC_READ_REG32(&global_regs->gnptxfsiz));
  22669. +
  22670. + nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
  22671. + nptxfifosize.b.startaddr = params->dev_rx_fifo_size;
  22672. +
  22673. + DWC_WRITE_REG32(&global_regs->gnptxfsiz,
  22674. + nptxfifosize.d32);
  22675. +
  22676. + DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
  22677. + DWC_READ_REG32(&global_regs->gnptxfsiz));
  22678. +
  22679. + /**@todo NGS: Fix Periodic FIFO Sizing! */
  22680. + /*
  22681. + * Periodic Tx FIFOs These FIFOs are numbered from 1 to 15.
  22682. + * Indexes of the FIFO size module parameters in the
  22683. + * dev_perio_tx_fifo_size array and the FIFO size registers in
  22684. + * the dptxfsiz array run from 0 to 14.
  22685. + */
  22686. + /** @todo Finish debug of this */
  22687. + ptxfifosize.b.startaddr =
  22688. + nptxfifosize.b.startaddr + nptxfifosize.b.depth;
  22689. + for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) {
  22690. + ptxfifosize.b.depth =
  22691. + params->dev_perio_tx_fifo_size[i];
  22692. + DWC_DEBUGPL(DBG_CIL,
  22693. + "initial dtxfsiz[%d]=%08x\n", i,
  22694. + DWC_READ_REG32(&global_regs->dtxfsiz
  22695. + [i]));
  22696. + DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
  22697. + ptxfifosize.d32);
  22698. + DWC_DEBUGPL(DBG_CIL, "new dtxfsiz[%d]=%08x\n",
  22699. + i,
  22700. + DWC_READ_REG32(&global_regs->dtxfsiz
  22701. + [i]));
  22702. + ptxfifosize.b.startaddr += ptxfifosize.b.depth;
  22703. + }
  22704. + } else {
  22705. + /*
  22706. + * Tx FIFOs These FIFOs are numbered from 1 to 15.
  22707. + * Indexes of the FIFO size module parameters in the
  22708. + * dev_tx_fifo_size array and the FIFO size registers in
  22709. + * the dtxfsiz array run from 0 to 14.
  22710. + */
  22711. +
  22712. + /* Non-periodic Tx FIFO */
  22713. + DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
  22714. + DWC_READ_REG32(&global_regs->gnptxfsiz));
  22715. +
  22716. +#ifdef DWC_UTE_CFI
  22717. + core_if->pwron_gnptxfsiz =
  22718. + (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);
  22719. + core_if->init_gnptxfsiz =
  22720. + params->dev_nperio_tx_fifo_size;
  22721. +#endif
  22722. + nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size;
  22723. + nptxfifosize.b.startaddr = params->dev_rx_fifo_size;
  22724. +
  22725. + DWC_WRITE_REG32(&global_regs->gnptxfsiz,
  22726. + nptxfifosize.d32);
  22727. +
  22728. + DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
  22729. + DWC_READ_REG32(&global_regs->gnptxfsiz));
  22730. +
  22731. + txfifosize.b.startaddr =
  22732. + nptxfifosize.b.startaddr + nptxfifosize.b.depth;
  22733. +
  22734. + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) {
  22735. +
  22736. + txfifosize.b.depth =
  22737. + params->dev_tx_fifo_size[i];
  22738. +
  22739. + DWC_DEBUGPL(DBG_CIL,
  22740. + "initial dtxfsiz[%d]=%08x\n",
  22741. + i,
  22742. + DWC_READ_REG32(&global_regs->dtxfsiz
  22743. + [i]));
  22744. +
  22745. +#ifdef DWC_UTE_CFI
  22746. + core_if->pwron_txfsiz[i] =
  22747. + (DWC_READ_REG32
  22748. + (&global_regs->dtxfsiz[i]) >> 16);
  22749. + core_if->init_txfsiz[i] =
  22750. + params->dev_tx_fifo_size[i];
  22751. +#endif
  22752. + DWC_WRITE_REG32(&global_regs->dtxfsiz[i],
  22753. + txfifosize.d32);
  22754. +
  22755. + DWC_DEBUGPL(DBG_CIL,
  22756. + "new dtxfsiz[%d]=%08x\n",
  22757. + i,
  22758. + DWC_READ_REG32(&global_regs->dtxfsiz
  22759. + [i]));
  22760. +
  22761. + txfifosize.b.startaddr += txfifosize.b.depth;
  22762. + }
  22763. + if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
  22764. + /* Calculating DFIFOCFG for Device mode to include RxFIFO and NPTXFIFO */
  22765. + gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg);
  22766. + hwcfg3.d32 = DWC_READ_REG32(&global_regs->ghwcfg3);
  22767. + gdfifocfg.b.gdfifocfg = (DWC_READ_REG32(&global_regs->ghwcfg3) >> 16);
  22768. + DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);
  22769. + rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff);
  22770. + nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);
  22771. + gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz;
  22772. + DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);
  22773. + }
  22774. + }
  22775. +
  22776. + /* Flush the FIFOs */
  22777. + dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */
  22778. + dwc_otg_flush_rx_fifo(core_if);
  22779. +
  22780. + /* Flush the Learning Queue. */
  22781. + resetctl.b.intknqflsh = 1;
  22782. + DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
  22783. +
  22784. + if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) {
  22785. + core_if->start_predict = 0;
  22786. + for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) {
  22787. + core_if->nextep_seq[i] = 0xff; // 0xff - EP not active
  22788. + }
  22789. + core_if->nextep_seq[0] = 0;
  22790. + core_if->first_in_nextep_seq = 0;
  22791. + diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
  22792. + diepctl.b.nextep = 0;
  22793. + DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
  22794. +
  22795. + /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */
  22796. + dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
  22797. + dcfg.b.epmscnt = 2;
  22798. + DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
  22799. +
  22800. + DWC_DEBUGPL(DBG_CILV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
  22801. + __func__, core_if->first_in_nextep_seq);
  22802. + for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
  22803. + DWC_DEBUGPL(DBG_CILV, "%2d ", core_if->nextep_seq[i]);
  22804. + }
  22805. + DWC_DEBUGPL(DBG_CILV,"\n");
  22806. + }
  22807. +
  22808. + /* Clear all pending Device Interrupts */
  22809. + /** @todo - if the condition needed to be checked
  22810. + * or in any case all pending interrutps should be cleared?
  22811. + */
  22812. + if (core_if->multiproc_int_enable) {
  22813. + for (i = 0; i < core_if->dev_if->num_in_eps; ++i) {
  22814. + DWC_WRITE_REG32(&dev_if->
  22815. + dev_global_regs->diepeachintmsk[i], 0);
  22816. + }
  22817. + }
  22818. +
  22819. + for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
  22820. + DWC_WRITE_REG32(&dev_if->
  22821. + dev_global_regs->doepeachintmsk[i], 0);
  22822. + }
  22823. +
  22824. + DWC_WRITE_REG32(&dev_if->dev_global_regs->deachint, 0xFFFFFFFF);
  22825. + DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, 0);
  22826. + } else {
  22827. + DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, 0);
  22828. + DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, 0);
  22829. + DWC_WRITE_REG32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF);
  22830. + DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, 0);
  22831. + }
  22832. +
  22833. + for (i = 0; i <= dev_if->num_in_eps; i++) {
  22834. + depctl_data_t depctl;
  22835. + depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
  22836. + if (depctl.b.epena) {
  22837. + depctl.d32 = 0;
  22838. + depctl.b.epdis = 1;
  22839. + depctl.b.snak = 1;
  22840. + } else {
  22841. + depctl.d32 = 0;
  22842. + }
  22843. +
  22844. + DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
  22845. +
  22846. + DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, 0);
  22847. + DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, 0);
  22848. + DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepint, 0xFF);
  22849. + }
  22850. +
  22851. + for (i = 0; i <= dev_if->num_out_eps; i++) {
  22852. + depctl_data_t depctl;
  22853. + depctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
  22854. + if (depctl.b.epena) {
  22855. + dctl_data_t dctl = {.d32 = 0 };
  22856. + gintmsk_data_t gintsts = {.d32 = 0 };
  22857. + doepint_data_t doepint = {.d32 = 0 };
  22858. + dctl.b.sgoutnak = 1;
  22859. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
  22860. + do {
  22861. + dwc_udelay(10);
  22862. + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
  22863. + } while (!gintsts.b.goutnakeff);
  22864. + gintsts.d32 = 0;
  22865. + gintsts.b.goutnakeff = 1;
  22866. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
  22867. +
  22868. + depctl.d32 = 0;
  22869. + depctl.b.epdis = 1;
  22870. + depctl.b.snak = 1;
  22871. + DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepctl, depctl.d32);
  22872. + do {
  22873. + dwc_udelay(10);
  22874. + doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
  22875. + out_ep_regs[i]->doepint);
  22876. + } while (!doepint.b.epdisabled);
  22877. +
  22878. + doepint.b.epdisabled = 1;
  22879. + DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepint, doepint.d32);
  22880. +
  22881. + dctl.d32 = 0;
  22882. + dctl.b.cgoutnak = 1;
  22883. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
  22884. + } else {
  22885. + depctl.d32 = 0;
  22886. + }
  22887. +
  22888. + DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32);
  22889. +
  22890. + DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doeptsiz, 0);
  22891. + DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepdma, 0);
  22892. + DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepint, 0xFF);
  22893. + }
  22894. +
  22895. + if (core_if->en_multiple_tx_fifo && core_if->dma_enable) {
  22896. + dev_if->non_iso_tx_thr_en = params->thr_ctl & 0x1;
  22897. + dev_if->iso_tx_thr_en = (params->thr_ctl >> 1) & 0x1;
  22898. + dev_if->rx_thr_en = (params->thr_ctl >> 2) & 0x1;
  22899. +
  22900. + dev_if->rx_thr_length = params->rx_thr_length;
  22901. + dev_if->tx_thr_length = params->tx_thr_length;
  22902. +
  22903. + dev_if->setup_desc_index = 0;
  22904. +
  22905. + dthrctl.d32 = 0;
  22906. + dthrctl.b.non_iso_thr_en = dev_if->non_iso_tx_thr_en;
  22907. + dthrctl.b.iso_thr_en = dev_if->iso_tx_thr_en;
  22908. + dthrctl.b.tx_thr_len = dev_if->tx_thr_length;
  22909. + dthrctl.b.rx_thr_en = dev_if->rx_thr_en;
  22910. + dthrctl.b.rx_thr_len = dev_if->rx_thr_length;
  22911. + dthrctl.b.ahb_thr_ratio = params->ahb_thr_ratio;
  22912. +
  22913. + DWC_WRITE_REG32(&dev_if->dev_global_regs->dtknqr3_dthrctl,
  22914. + dthrctl.d32);
  22915. +
  22916. + DWC_DEBUGPL(DBG_CIL,
  22917. + "Non ISO Tx Thr - %d\nISO Tx Thr - %d\nRx Thr - %d\nTx Thr Len - %d\nRx Thr Len - %d\n",
  22918. + dthrctl.b.non_iso_thr_en, dthrctl.b.iso_thr_en,
  22919. + dthrctl.b.rx_thr_en, dthrctl.b.tx_thr_len,
  22920. + dthrctl.b.rx_thr_len);
  22921. +
  22922. + }
  22923. +
  22924. + dwc_otg_enable_device_interrupts(core_if);
  22925. +
  22926. + {
  22927. + diepmsk_data_t msk = {.d32 = 0 };
  22928. + msk.b.txfifoundrn = 1;
  22929. + if (core_if->multiproc_int_enable) {
  22930. + DWC_MODIFY_REG32(&dev_if->dev_global_regs->
  22931. + diepeachintmsk[0], msk.d32, msk.d32);
  22932. + } else {
  22933. + DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk,
  22934. + msk.d32, msk.d32);
  22935. + }
  22936. + }
  22937. +
  22938. + if (core_if->multiproc_int_enable) {
  22939. + /* Set NAK on Babble */
  22940. + dctl_data_t dctl = {.d32 = 0 };
  22941. + dctl.b.nakonbble = 1;
  22942. + DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32);
  22943. + }
  22944. +
  22945. + if (core_if->snpsid >= OTG_CORE_REV_2_94a) {
  22946. + dctl_data_t dctl = {.d32 = 0 };
  22947. + dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
  22948. + dctl.b.sftdiscon = 0;
  22949. + DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32);
  22950. + }
  22951. +}
  22952. +
  22953. +/**
  22954. + * This function enables the Host mode interrupts.
  22955. + *
  22956. + * @param core_if Programming view of DWC_otg controller
  22957. + */
  22958. +void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * core_if)
  22959. +{
  22960. + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
  22961. + gintmsk_data_t intr_mask = {.d32 = 0 };
  22962. +
  22963. + DWC_DEBUGPL(DBG_CIL, "%s(%p)\n", __func__, core_if);
  22964. +
  22965. + /* Disable all interrupts. */
  22966. + DWC_WRITE_REG32(&global_regs->gintmsk, 0);
  22967. +
  22968. + /* Clear any pending interrupts. */
  22969. + DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF);
  22970. +
  22971. + /* Enable the common interrupts */
  22972. + dwc_otg_enable_common_interrupts(core_if);
  22973. +
  22974. + /*
  22975. + * Enable host mode interrupts without disturbing common
  22976. + * interrupts.
  22977. + */
  22978. +
  22979. + intr_mask.b.disconnect = 1;
  22980. + intr_mask.b.portintr = 1;
  22981. + intr_mask.b.hcintr = 1;
  22982. +
  22983. + DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
  22984. +}
  22985. +
  22986. +/**
  22987. + * This function disables the Host Mode interrupts.
  22988. + *
  22989. + * @param core_if Programming view of DWC_otg controller
  22990. + */
  22991. +void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * core_if)
  22992. +{
  22993. + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
  22994. + gintmsk_data_t intr_mask = {.d32 = 0 };
  22995. +
  22996. + DWC_DEBUGPL(DBG_CILV, "%s()\n", __func__);
  22997. +
  22998. + /*
  22999. + * Disable host mode interrupts without disturbing common
  23000. + * interrupts.
  23001. + */
  23002. + intr_mask.b.sofintr = 1;
  23003. + intr_mask.b.portintr = 1;
  23004. + intr_mask.b.hcintr = 1;
  23005. + intr_mask.b.ptxfempty = 1;
  23006. + intr_mask.b.nptxfempty = 1;
  23007. +
  23008. + DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, 0);
  23009. +}
  23010. +
  23011. +/**
  23012. + * This function initializes the DWC_otg controller registers for
  23013. + * host mode.
  23014. + *
  23015. + * This function flushes the Tx and Rx FIFOs and it flushes any entries in the
  23016. + * request queues. Host channels are reset to ensure that they are ready for
  23017. + * performing transfers.
  23018. + *
  23019. + * @param core_if Programming view of DWC_otg controller
  23020. + *
  23021. + */
  23022. +void dwc_otg_core_host_init(dwc_otg_core_if_t * core_if)
  23023. +{
  23024. + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
  23025. + dwc_otg_host_if_t *host_if = core_if->host_if;
  23026. + dwc_otg_core_params_t *params = core_if->core_params;
  23027. + hprt0_data_t hprt0 = {.d32 = 0 };
  23028. + fifosize_data_t nptxfifosize;
  23029. + fifosize_data_t ptxfifosize;
  23030. + uint16_t rxfsiz, nptxfsiz, hptxfsiz;
  23031. + gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
  23032. + int i;
  23033. + hcchar_data_t hcchar;
  23034. + hcfg_data_t hcfg;
  23035. + hfir_data_t hfir;
  23036. + dwc_otg_hc_regs_t *hc_regs;
  23037. + int num_channels;
  23038. + gotgctl_data_t gotgctl = {.d32 = 0 };
  23039. +
  23040. + DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if);
  23041. +
  23042. + /* Restart the Phy Clock */
  23043. + DWC_WRITE_REG32(core_if->pcgcctl, 0);
  23044. +
  23045. + /* Initialize Host Configuration Register */
  23046. + init_fslspclksel(core_if);
  23047. + if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
  23048. + hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg);
  23049. + hcfg.b.fslssupp = 1;
  23050. + DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32);
  23051. +
  23052. + }
  23053. +
  23054. + /* This bit allows dynamic reloading of the HFIR register
  23055. + * during runtime. This bit needs to be programmed during
  23056. + * initial configuration and its value must not be changed
  23057. + * during runtime.*/
  23058. + if (core_if->core_params->reload_ctl == 1) {
  23059. + hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir);
  23060. + hfir.b.hfirrldctrl = 1;
  23061. + DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32);
  23062. + }
  23063. +
  23064. + if (core_if->core_params->dma_desc_enable) {
  23065. + uint8_t op_mode = core_if->hwcfg2.b.op_mode;
  23066. + if (!
  23067. + (core_if->hwcfg4.b.desc_dma
  23068. + && (core_if->snpsid >= OTG_CORE_REV_2_90a)
  23069. + && ((op_mode == DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
  23070. + || (op_mode == DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
  23071. + || (op_mode ==
  23072. + DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG)
  23073. + || (op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)
  23074. + || (op_mode ==
  23075. + DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST)))) {
  23076. +
  23077. + DWC_ERROR("Host can't operate in Descriptor DMA mode.\n"
  23078. + "Either core version is below 2.90a or "
  23079. + "GHWCFG2, GHWCFG4 registers' values do not allow Descriptor DMA in host mode.\n"
  23080. + "To run the driver in Buffer DMA host mode set dma_desc_enable "
  23081. + "module parameter to 0.\n");
  23082. + return;
  23083. + }
  23084. + hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg);
  23085. + hcfg.b.descdma = 1;
  23086. + DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32);
  23087. + }
  23088. +
  23089. + /* Configure data FIFO sizes */
  23090. + if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
  23091. + DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n",
  23092. + core_if->total_fifo_size);
  23093. + DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n",
  23094. + params->host_rx_fifo_size);
  23095. + DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n",
  23096. + params->host_nperio_tx_fifo_size);
  23097. + DWC_DEBUGPL(DBG_CIL, "P Tx FIFO Size=%d\n",
  23098. + params->host_perio_tx_fifo_size);
  23099. +
  23100. + /* Rx FIFO */
  23101. + DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n",
  23102. + DWC_READ_REG32(&global_regs->grxfsiz));
  23103. + DWC_WRITE_REG32(&global_regs->grxfsiz,
  23104. + params->host_rx_fifo_size);
  23105. + DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n",
  23106. + DWC_READ_REG32(&global_regs->grxfsiz));
  23107. +
  23108. + /* Non-periodic Tx FIFO */
  23109. + DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n",
  23110. + DWC_READ_REG32(&global_regs->gnptxfsiz));
  23111. + nptxfifosize.b.depth = params->host_nperio_tx_fifo_size;
  23112. + nptxfifosize.b.startaddr = params->host_rx_fifo_size;
  23113. + DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32);
  23114. + DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n",
  23115. + DWC_READ_REG32(&global_regs->gnptxfsiz));
  23116. +
  23117. + /* Periodic Tx FIFO */
  23118. + DWC_DEBUGPL(DBG_CIL, "initial hptxfsiz=%08x\n",
  23119. + DWC_READ_REG32(&global_regs->hptxfsiz));
  23120. + ptxfifosize.b.depth = params->host_perio_tx_fifo_size;
  23121. + ptxfifosize.b.startaddr =
  23122. + nptxfifosize.b.startaddr + nptxfifosize.b.depth;
  23123. + DWC_WRITE_REG32(&global_regs->hptxfsiz, ptxfifosize.d32);
  23124. + DWC_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n",
  23125. + DWC_READ_REG32(&global_regs->hptxfsiz));
  23126. +
  23127. + if (core_if->en_multiple_tx_fifo
  23128. + && core_if->snpsid <= OTG_CORE_REV_2_94a) {
  23129. + /* Global DFIFOCFG calculation for Host mode - include RxFIFO, NPTXFIFO and HPTXFIFO */
  23130. + gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg);
  23131. + rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff);
  23132. + nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16);
  23133. + hptxfsiz = (DWC_READ_REG32(&global_regs->hptxfsiz) >> 16);
  23134. + gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz + hptxfsiz;
  23135. + DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32);
  23136. + }
  23137. + }
  23138. +
  23139. + /* TODO - check this */
  23140. + /* Clear Host Set HNP Enable in the OTG Control Register */
  23141. + gotgctl.b.hstsethnpen = 1;
  23142. + DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
  23143. + /* Make sure the FIFOs are flushed. */
  23144. + dwc_otg_flush_tx_fifo(core_if, 0x10 /* all TX FIFOs */ );
  23145. + dwc_otg_flush_rx_fifo(core_if);
  23146. +
  23147. + /* Clear Host Set HNP Enable in the OTG Control Register */
  23148. + gotgctl.b.hstsethnpen = 1;
  23149. + DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
  23150. +
  23151. + if (!core_if->core_params->dma_desc_enable) {
  23152. + /* Flush out any leftover queued requests. */
  23153. + num_channels = core_if->core_params->host_channels;
  23154. +
  23155. + for (i = 0; i < num_channels; i++) {
  23156. + hc_regs = core_if->host_if->hc_regs[i];
  23157. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  23158. + hcchar.b.chen = 0;
  23159. + hcchar.b.chdis = 1;
  23160. + hcchar.b.epdir = 0;
  23161. + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
  23162. + }
  23163. +
  23164. + /* Halt all channels to put them into a known state. */
  23165. + for (i = 0; i < num_channels; i++) {
  23166. + int count = 0;
  23167. + hc_regs = core_if->host_if->hc_regs[i];
  23168. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  23169. + hcchar.b.chen = 1;
  23170. + hcchar.b.chdis = 1;
  23171. + hcchar.b.epdir = 0;
  23172. + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
  23173. + DWC_DEBUGPL(DBG_HCDV, "%s: Halt channel %d regs %p\n", __func__, i, hc_regs);
  23174. + do {
  23175. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  23176. + if (++count > 1000) {
  23177. + DWC_ERROR
  23178. + ("%s: Unable to clear halt on channel %d (timeout HCCHAR 0x%X @%p)\n",
  23179. + __func__, i, hcchar.d32, &hc_regs->hcchar);
  23180. + break;
  23181. + }
  23182. + dwc_udelay(1);
  23183. + } while (hcchar.b.chen);
  23184. + }
  23185. + }
  23186. +
  23187. + /* Turn on the vbus power. */
  23188. + DWC_PRINTF("Init: Port Power? op_state=%d\n", core_if->op_state);
  23189. + if (core_if->op_state == A_HOST) {
  23190. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  23191. + DWC_PRINTF("Init: Power Port (%d)\n", hprt0.b.prtpwr);
  23192. + if (hprt0.b.prtpwr == 0) {
  23193. + hprt0.b.prtpwr = 1;
  23194. + DWC_WRITE_REG32(host_if->hprt0, hprt0.d32);
  23195. + }
  23196. + }
  23197. +
  23198. + dwc_otg_enable_host_interrupts(core_if);
  23199. +}
  23200. +
  23201. +/**
  23202. + * Prepares a host channel for transferring packets to/from a specific
  23203. + * endpoint. The HCCHARn register is set up with the characteristics specified
  23204. + * in _hc. Host channel interrupts that may need to be serviced while this
  23205. + * transfer is in progress are enabled.
  23206. + *
  23207. + * @param core_if Programming view of DWC_otg controller
  23208. + * @param hc Information needed to initialize the host channel
  23209. + */
  23210. +void dwc_otg_hc_init(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
  23211. +{
  23212. + uint32_t intr_enable;
  23213. + hcintmsk_data_t hc_intr_mask;
  23214. + gintmsk_data_t gintmsk = {.d32 = 0 };
  23215. + hcchar_data_t hcchar;
  23216. + hcsplt_data_t hcsplt;
  23217. +
  23218. + uint8_t hc_num = hc->hc_num;
  23219. + dwc_otg_host_if_t *host_if = core_if->host_if;
  23220. + dwc_otg_hc_regs_t *hc_regs = host_if->hc_regs[hc_num];
  23221. +
  23222. + /* Clear old interrupt conditions for this host channel. */
  23223. + hc_intr_mask.d32 = 0xFFFFFFFF;
  23224. + hc_intr_mask.b.reserved14_31 = 0;
  23225. + DWC_WRITE_REG32(&hc_regs->hcint, hc_intr_mask.d32);
  23226. +
  23227. + /* Enable channel interrupts required for this transfer. */
  23228. + hc_intr_mask.d32 = 0;
  23229. + hc_intr_mask.b.chhltd = 1;
  23230. + if (core_if->dma_enable) {
  23231. + /* For Descriptor DMA mode core halts the channel on AHB error. Interrupt is not required */
  23232. + if (!core_if->dma_desc_enable)
  23233. + hc_intr_mask.b.ahberr = 1;
  23234. + else {
  23235. + if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
  23236. + hc_intr_mask.b.xfercompl = 1;
  23237. + }
  23238. +
  23239. + if (hc->error_state && !hc->do_split &&
  23240. + hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
  23241. + hc_intr_mask.b.ack = 1;
  23242. + if (hc->ep_is_in) {
  23243. + hc_intr_mask.b.datatglerr = 1;
  23244. + if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) {
  23245. + hc_intr_mask.b.nak = 1;
  23246. + }
  23247. + }
  23248. + }
  23249. + } else {
  23250. + switch (hc->ep_type) {
  23251. + case DWC_OTG_EP_TYPE_CONTROL:
  23252. + case DWC_OTG_EP_TYPE_BULK:
  23253. + hc_intr_mask.b.xfercompl = 1;
  23254. + hc_intr_mask.b.stall = 1;
  23255. + hc_intr_mask.b.xacterr = 1;
  23256. + hc_intr_mask.b.datatglerr = 1;
  23257. + if (hc->ep_is_in) {
  23258. + hc_intr_mask.b.bblerr = 1;
  23259. + } else {
  23260. + hc_intr_mask.b.nak = 1;
  23261. + hc_intr_mask.b.nyet = 1;
  23262. + if (hc->do_ping) {
  23263. + hc_intr_mask.b.ack = 1;
  23264. + }
  23265. + }
  23266. +
  23267. + if (hc->do_split) {
  23268. + hc_intr_mask.b.nak = 1;
  23269. + if (hc->complete_split) {
  23270. + hc_intr_mask.b.nyet = 1;
  23271. + } else {
  23272. + hc_intr_mask.b.ack = 1;
  23273. + }
  23274. + }
  23275. +
  23276. + if (hc->error_state) {
  23277. + hc_intr_mask.b.ack = 1;
  23278. + }
  23279. + break;
  23280. + case DWC_OTG_EP_TYPE_INTR:
  23281. + hc_intr_mask.b.xfercompl = 1;
  23282. + hc_intr_mask.b.nak = 1;
  23283. + hc_intr_mask.b.stall = 1;
  23284. + hc_intr_mask.b.xacterr = 1;
  23285. + hc_intr_mask.b.datatglerr = 1;
  23286. + hc_intr_mask.b.frmovrun = 1;
  23287. +
  23288. + if (hc->ep_is_in) {
  23289. + hc_intr_mask.b.bblerr = 1;
  23290. + }
  23291. + if (hc->error_state) {
  23292. + hc_intr_mask.b.ack = 1;
  23293. + }
  23294. + if (hc->do_split) {
  23295. + if (hc->complete_split) {
  23296. + hc_intr_mask.b.nyet = 1;
  23297. + } else {
  23298. + hc_intr_mask.b.ack = 1;
  23299. + }
  23300. + }
  23301. + break;
  23302. + case DWC_OTG_EP_TYPE_ISOC:
  23303. + hc_intr_mask.b.xfercompl = 1;
  23304. + hc_intr_mask.b.frmovrun = 1;
  23305. + hc_intr_mask.b.ack = 1;
  23306. +
  23307. + if (hc->ep_is_in) {
  23308. + hc_intr_mask.b.xacterr = 1;
  23309. + hc_intr_mask.b.bblerr = 1;
  23310. + }
  23311. + break;
  23312. + }
  23313. + }
  23314. + DWC_WRITE_REG32(&hc_regs->hcintmsk, hc_intr_mask.d32);
  23315. +
  23316. + /* Enable the top level host channel interrupt. */
  23317. + intr_enable = (1 << hc_num);
  23318. + DWC_MODIFY_REG32(&host_if->host_global_regs->haintmsk, 0, intr_enable);
  23319. +
  23320. + /* Make sure host channel interrupts are enabled. */
  23321. + gintmsk.b.hcintr = 1;
  23322. + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
  23323. +
  23324. + /*
  23325. + * Program the HCCHARn register with the endpoint characteristics for
  23326. + * the current transfer.
  23327. + */
  23328. + hcchar.d32 = 0;
  23329. + hcchar.b.devaddr = hc->dev_addr;
  23330. + hcchar.b.epnum = hc->ep_num;
  23331. + hcchar.b.epdir = hc->ep_is_in;
  23332. + hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
  23333. + hcchar.b.eptype = hc->ep_type;
  23334. + hcchar.b.mps = hc->max_packet;
  23335. +
  23336. + DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32);
  23337. +
  23338. + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d, Dev Addr %d, EP #%d\n",
  23339. + __func__, hc->hc_num, hcchar.b.devaddr, hcchar.b.epnum);
  23340. + DWC_DEBUGPL(DBG_HCDV, " Is In %d, Is Low Speed %d, EP Type %d, "
  23341. + "Max Pkt %d, Multi Cnt %d\n",
  23342. + hcchar.b.epdir, hcchar.b.lspddev, hcchar.b.eptype,
  23343. + hcchar.b.mps, hcchar.b.multicnt);
  23344. +
  23345. + /*
  23346. + * Program the HCSPLIT register for SPLITs
  23347. + */
  23348. + hcsplt.d32 = 0;
  23349. + if (hc->do_split) {
  23350. + DWC_DEBUGPL(DBG_HCDV, "Programming HC %d with split --> %s\n",
  23351. + hc->hc_num,
  23352. + hc->complete_split ? "CSPLIT" : "SSPLIT");
  23353. + hcsplt.b.compsplt = hc->complete_split;
  23354. + hcsplt.b.xactpos = hc->xact_pos;
  23355. + hcsplt.b.hubaddr = hc->hub_addr;
  23356. + hcsplt.b.prtaddr = hc->port_addr;
  23357. + DWC_DEBUGPL(DBG_HCDV, "\t comp split %d\n", hc->complete_split);
  23358. + DWC_DEBUGPL(DBG_HCDV, "\t xact pos %d\n", hc->xact_pos);
  23359. + DWC_DEBUGPL(DBG_HCDV, "\t hub addr %d\n", hc->hub_addr);
  23360. + DWC_DEBUGPL(DBG_HCDV, "\t port addr %d\n", hc->port_addr);
  23361. + DWC_DEBUGPL(DBG_HCDV, "\t is_in %d\n", hc->ep_is_in);
  23362. + DWC_DEBUGPL(DBG_HCDV, "\t Max Pkt: %d\n", hcchar.b.mps);
  23363. + DWC_DEBUGPL(DBG_HCDV, "\t xferlen: %d\n", hc->xfer_len);
  23364. + }
  23365. + DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32);
  23366. +
  23367. +}
  23368. +
  23369. +/**
  23370. + * Attempts to halt a host channel. This function should only be called in
  23371. + * Slave mode or to abort a transfer in either Slave mode or DMA mode. Under
  23372. + * normal circumstances in DMA mode, the controller halts the channel when the
  23373. + * transfer is complete or a condition occurs that requires application
  23374. + * intervention.
  23375. + *
  23376. + * In slave mode, checks for a free request queue entry, then sets the Channel
  23377. + * Enable and Channel Disable bits of the Host Channel Characteristics
  23378. + * register of the specified channel to intiate the halt. If there is no free
  23379. + * request queue entry, sets only the Channel Disable bit of the HCCHARn
  23380. + * register to flush requests for this channel. In the latter case, sets a
  23381. + * flag to indicate that the host channel needs to be halted when a request
  23382. + * queue slot is open.
  23383. + *
  23384. + * In DMA mode, always sets the Channel Enable and Channel Disable bits of the
  23385. + * HCCHARn register. The controller ensures there is space in the request
  23386. + * queue before submitting the halt request.
  23387. + *
  23388. + * Some time may elapse before the core flushes any posted requests for this
  23389. + * host channel and halts. The Channel Halted interrupt handler completes the
  23390. + * deactivation of the host channel.
  23391. + *
  23392. + * @param core_if Controller register interface.
  23393. + * @param hc Host channel to halt.
  23394. + * @param halt_status Reason for halting the channel.
  23395. + */
  23396. +void dwc_otg_hc_halt(dwc_otg_core_if_t * core_if,
  23397. + dwc_hc_t * hc, dwc_otg_halt_status_e halt_status)
  23398. +{
  23399. + gnptxsts_data_t nptxsts;
  23400. + hptxsts_data_t hptxsts;
  23401. + hcchar_data_t hcchar;
  23402. + dwc_otg_hc_regs_t *hc_regs;
  23403. + dwc_otg_core_global_regs_t *global_regs;
  23404. + dwc_otg_host_global_regs_t *host_global_regs;
  23405. +
  23406. + hc_regs = core_if->host_if->hc_regs[hc->hc_num];
  23407. + global_regs = core_if->core_global_regs;
  23408. + host_global_regs = core_if->host_if->host_global_regs;
  23409. +
  23410. + DWC_ASSERT(!(halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS),
  23411. + "halt_status = %d\n", halt_status);
  23412. +
  23413. + if (halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||
  23414. + halt_status == DWC_OTG_HC_XFER_AHB_ERR) {
  23415. + /*
  23416. + * Disable all channel interrupts except Ch Halted. The QTD
  23417. + * and QH state associated with this transfer has been cleared
  23418. + * (in the case of URB_DEQUEUE), so the channel needs to be
  23419. + * shut down carefully to prevent crashes.
  23420. + */
  23421. + hcintmsk_data_t hcintmsk;
  23422. + hcintmsk.d32 = 0;
  23423. + hcintmsk.b.chhltd = 1;
  23424. + DWC_WRITE_REG32(&hc_regs->hcintmsk, hcintmsk.d32);
  23425. +
  23426. + /*
  23427. + * Make sure no other interrupts besides halt are currently
  23428. + * pending. Handling another interrupt could cause a crash due
  23429. + * to the QTD and QH state.
  23430. + */
  23431. + DWC_WRITE_REG32(&hc_regs->hcint, ~hcintmsk.d32);
  23432. +
  23433. + /*
  23434. + * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR
  23435. + * even if the channel was already halted for some other
  23436. + * reason.
  23437. + */
  23438. + hc->halt_status = halt_status;
  23439. +
  23440. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  23441. + if (hcchar.b.chen == 0) {
  23442. + /*
  23443. + * The channel is either already halted or it hasn't
  23444. + * started yet. In DMA mode, the transfer may halt if
  23445. + * it finishes normally or a condition occurs that
  23446. + * requires driver intervention. Don't want to halt
  23447. + * the channel again. In either Slave or DMA mode,
  23448. + * it's possible that the transfer has been assigned
  23449. + * to a channel, but not started yet when an URB is
  23450. + * dequeued. Don't want to halt a channel that hasn't
  23451. + * started yet.
  23452. + */
  23453. + return;
  23454. + }
  23455. + }
  23456. + if (hc->halt_pending) {
  23457. + /*
  23458. + * A halt has already been issued for this channel. This might
  23459. + * happen when a transfer is aborted by a higher level in
  23460. + * the stack.
  23461. + */
  23462. +#ifdef DEBUG
  23463. + DWC_PRINTF
  23464. + ("*** %s: Channel %d, _hc->halt_pending already set ***\n",
  23465. + __func__, hc->hc_num);
  23466. +
  23467. +#endif
  23468. + return;
  23469. + }
  23470. +
  23471. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  23472. +
  23473. + /* No need to set the bit in DDMA for disabling the channel */
  23474. + //TODO check it everywhere channel is disabled
  23475. + if (!core_if->core_params->dma_desc_enable)
  23476. + hcchar.b.chen = 1;
  23477. + hcchar.b.chdis = 1;
  23478. +
  23479. + if (!core_if->dma_enable) {
  23480. + /* Check for space in the request queue to issue the halt. */
  23481. + if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
  23482. + hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
  23483. + nptxsts.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
  23484. + if (nptxsts.b.nptxqspcavail == 0) {
  23485. + hcchar.b.chen = 0;
  23486. + }
  23487. + } else {
  23488. + hptxsts.d32 =
  23489. + DWC_READ_REG32(&host_global_regs->hptxsts);
  23490. + if ((hptxsts.b.ptxqspcavail == 0)
  23491. + || (core_if->queuing_high_bandwidth)) {
  23492. + hcchar.b.chen = 0;
  23493. + }
  23494. + }
  23495. + }
  23496. + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
  23497. +
  23498. + hc->halt_status = halt_status;
  23499. +
  23500. + if (hcchar.b.chen) {
  23501. + hc->halt_pending = 1;
  23502. + hc->halt_on_queue = 0;
  23503. + } else {
  23504. + hc->halt_on_queue = 1;
  23505. + }
  23506. +
  23507. + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
  23508. + DWC_DEBUGPL(DBG_HCDV, " hcchar: 0x%08x\n", hcchar.d32);
  23509. + DWC_DEBUGPL(DBG_HCDV, " halt_pending: %d\n", hc->halt_pending);
  23510. + DWC_DEBUGPL(DBG_HCDV, " halt_on_queue: %d\n", hc->halt_on_queue);
  23511. + DWC_DEBUGPL(DBG_HCDV, " halt_status: %d\n", hc->halt_status);
  23512. +
  23513. + return;
  23514. +}
  23515. +
  23516. +/**
  23517. + * Clears the transfer state for a host channel. This function is normally
  23518. + * called after a transfer is done and the host channel is being released.
  23519. + *
  23520. + * @param core_if Programming view of DWC_otg controller.
  23521. + * @param hc Identifies the host channel to clean up.
  23522. + */
  23523. +void dwc_otg_hc_cleanup(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
  23524. +{
  23525. + dwc_otg_hc_regs_t *hc_regs;
  23526. +
  23527. + hc->xfer_started = 0;
  23528. +
  23529. + /*
  23530. + * Clear channel interrupt enables and any unhandled channel interrupt
  23531. + * conditions.
  23532. + */
  23533. + hc_regs = core_if->host_if->hc_regs[hc->hc_num];
  23534. + DWC_WRITE_REG32(&hc_regs->hcintmsk, 0);
  23535. + DWC_WRITE_REG32(&hc_regs->hcint, 0xFFFFFFFF);
  23536. +#ifdef DEBUG
  23537. + DWC_TIMER_CANCEL(core_if->hc_xfer_timer[hc->hc_num]);
  23538. +#endif
  23539. +}
  23540. +
  23541. +/**
  23542. + * Sets the channel property that indicates in which frame a periodic transfer
  23543. + * should occur. This is always set to the _next_ frame. This function has no
  23544. + * effect on non-periodic transfers.
  23545. + *
  23546. + * @param core_if Programming view of DWC_otg controller.
  23547. + * @param hc Identifies the host channel to set up and its properties.
  23548. + * @param hcchar Current value of the HCCHAR register for the specified host
  23549. + * channel.
  23550. + */
  23551. +static inline void hc_set_even_odd_frame(dwc_otg_core_if_t * core_if,
  23552. + dwc_hc_t * hc, hcchar_data_t * hcchar)
  23553. +{
  23554. + if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
  23555. + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
  23556. + hfnum_data_t hfnum;
  23557. + hfnum.d32 =
  23558. + DWC_READ_REG32(&core_if->host_if->host_global_regs->hfnum);
  23559. +
  23560. + /* 1 if _next_ frame is odd, 0 if it's even */
  23561. + hcchar->b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1;
  23562. +#ifdef DEBUG
  23563. + if (hc->ep_type == DWC_OTG_EP_TYPE_INTR && hc->do_split
  23564. + && !hc->complete_split) {
  23565. + switch (hfnum.b.frnum & 0x7) {
  23566. + case 7:
  23567. + core_if->hfnum_7_samples++;
  23568. + core_if->hfnum_7_frrem_accum += hfnum.b.frrem;
  23569. + break;
  23570. + case 0:
  23571. + core_if->hfnum_0_samples++;
  23572. + core_if->hfnum_0_frrem_accum += hfnum.b.frrem;
  23573. + break;
  23574. + default:
  23575. + core_if->hfnum_other_samples++;
  23576. + core_if->hfnum_other_frrem_accum +=
  23577. + hfnum.b.frrem;
  23578. + break;
  23579. + }
  23580. + }
  23581. +#endif
  23582. + }
  23583. +}
  23584. +
  23585. +#ifdef DEBUG
  23586. +void hc_xfer_timeout(void *ptr)
  23587. +{
  23588. + hc_xfer_info_t *xfer_info = NULL;
  23589. + int hc_num = 0;
  23590. +
  23591. + if (ptr)
  23592. + xfer_info = (hc_xfer_info_t *) ptr;
  23593. +
  23594. + if (!xfer_info->hc) {
  23595. + DWC_ERROR("xfer_info->hc = %p\n", xfer_info->hc);
  23596. + return;
  23597. + }
  23598. +
  23599. + hc_num = xfer_info->hc->hc_num;
  23600. + DWC_WARN("%s: timeout on channel %d\n", __func__, hc_num);
  23601. + DWC_WARN(" start_hcchar_val 0x%08x\n",
  23602. + xfer_info->core_if->start_hcchar_val[hc_num]);
  23603. +}
  23604. +#endif
  23605. +
  23606. +void ep_xfer_timeout(void *ptr)
  23607. +{
  23608. + ep_xfer_info_t *xfer_info = NULL;
  23609. + int ep_num = 0;
  23610. + dctl_data_t dctl = {.d32 = 0 };
  23611. + gintsts_data_t gintsts = {.d32 = 0 };
  23612. + gintmsk_data_t gintmsk = {.d32 = 0 };
  23613. +
  23614. + if (ptr)
  23615. + xfer_info = (ep_xfer_info_t *) ptr;
  23616. +
  23617. + if (!xfer_info->ep) {
  23618. + DWC_ERROR("xfer_info->ep = %p\n", xfer_info->ep);
  23619. + return;
  23620. + }
  23621. +
  23622. + ep_num = xfer_info->ep->num;
  23623. + DWC_WARN("%s: timeout on endpoit %d\n", __func__, ep_num);
  23624. + /* Put the sate to 2 as it was time outed */
  23625. + xfer_info->state = 2;
  23626. +
  23627. + dctl.d32 =
  23628. + DWC_READ_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl);
  23629. + gintsts.d32 =
  23630. + DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintsts);
  23631. + gintmsk.d32 =
  23632. + DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintmsk);
  23633. +
  23634. + if (!gintmsk.b.goutnakeff) {
  23635. + /* Unmask it */
  23636. + gintmsk.b.goutnakeff = 1;
  23637. + DWC_WRITE_REG32(&xfer_info->core_if->core_global_regs->gintmsk,
  23638. + gintmsk.d32);
  23639. +
  23640. + }
  23641. +
  23642. + if (!gintsts.b.goutnakeff) {
  23643. + dctl.b.sgoutnak = 1;
  23644. + }
  23645. + DWC_WRITE_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl,
  23646. + dctl.d32);
  23647. +
  23648. +}
  23649. +
  23650. +void set_pid_isoc(dwc_hc_t * hc)
  23651. +{
  23652. + /* Set up the initial PID for the transfer. */
  23653. + if (hc->speed == DWC_OTG_EP_SPEED_HIGH) {
  23654. + if (hc->ep_is_in) {
  23655. + if (hc->multi_count == 1) {
  23656. + hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
  23657. + } else if (hc->multi_count == 2) {
  23658. + hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
  23659. + } else {
  23660. + hc->data_pid_start = DWC_OTG_HC_PID_DATA2;
  23661. + }
  23662. + } else {
  23663. + if (hc->multi_count == 1) {
  23664. + hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
  23665. + } else {
  23666. + hc->data_pid_start = DWC_OTG_HC_PID_MDATA;
  23667. + }
  23668. + }
  23669. + } else {
  23670. + hc->data_pid_start = DWC_OTG_HC_PID_DATA0;
  23671. + }
  23672. +}
  23673. +
  23674. +/**
  23675. + * This function does the setup for a data transfer for a host channel and
  23676. + * starts the transfer. May be called in either Slave mode or DMA mode. In
  23677. + * Slave mode, the caller must ensure that there is sufficient space in the
  23678. + * request queue and Tx Data FIFO.
  23679. + *
  23680. + * For an OUT transfer in Slave mode, it loads a data packet into the
  23681. + * appropriate FIFO. If necessary, additional data packets will be loaded in
  23682. + * the Host ISR.
  23683. + *
  23684. + * For an IN transfer in Slave mode, a data packet is requested. The data
  23685. + * packets are unloaded from the Rx FIFO in the Host ISR. If necessary,
  23686. + * additional data packets are requested in the Host ISR.
  23687. + *
  23688. + * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ
  23689. + * register along with a packet count of 1 and the channel is enabled. This
  23690. + * causes a single PING transaction to occur. Other fields in HCTSIZ are
  23691. + * simply set to 0 since no data transfer occurs in this case.
  23692. + *
  23693. + * For a PING transfer in DMA mode, the HCTSIZ register is initialized with
  23694. + * all the information required to perform the subsequent data transfer. In
  23695. + * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the
  23696. + * controller performs the entire PING protocol, then starts the data
  23697. + * transfer.
  23698. + *
  23699. + * @param core_if Programming view of DWC_otg controller.
  23700. + * @param hc Information needed to initialize the host channel. The xfer_len
  23701. + * value may be reduced to accommodate the max widths of the XferSize and
  23702. + * PktCnt fields in the HCTSIZn register. The multi_count value may be changed
  23703. + * to reflect the final xfer_len value.
  23704. + */
  23705. +void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
  23706. +{
  23707. + hcchar_data_t hcchar;
  23708. + hctsiz_data_t hctsiz;
  23709. + uint16_t num_packets;
  23710. + uint32_t max_hc_xfer_size = core_if->core_params->max_transfer_size;
  23711. + uint16_t max_hc_pkt_count = core_if->core_params->max_packet_count;
  23712. + dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
  23713. +
  23714. + hctsiz.d32 = 0;
  23715. +
  23716. + if (hc->do_ping) {
  23717. + if (!core_if->dma_enable) {
  23718. + dwc_otg_hc_do_ping(core_if, hc);
  23719. + hc->xfer_started = 1;
  23720. + return;
  23721. + } else {
  23722. + hctsiz.b.dopng = 1;
  23723. + }
  23724. + }
  23725. +
  23726. + if (hc->do_split) {
  23727. + num_packets = 1;
  23728. +
  23729. + if (hc->complete_split && !hc->ep_is_in) {
  23730. + /* For CSPLIT OUT Transfer, set the size to 0 so the
  23731. + * core doesn't expect any data written to the FIFO */
  23732. + hc->xfer_len = 0;
  23733. + } else if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) {
  23734. + hc->xfer_len = hc->max_packet;
  23735. + } else if (!hc->ep_is_in && (hc->xfer_len > 188)) {
  23736. + hc->xfer_len = 188;
  23737. + }
  23738. +
  23739. + hctsiz.b.xfersize = hc->xfer_len;
  23740. + } else {
  23741. + /*
  23742. + * Ensure that the transfer length and packet count will fit
  23743. + * in the widths allocated for them in the HCTSIZn register.
  23744. + */
  23745. + if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
  23746. + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
  23747. + /*
  23748. + * Make sure the transfer size is no larger than one
  23749. + * (micro)frame's worth of data. (A check was done
  23750. + * when the periodic transfer was accepted to ensure
  23751. + * that a (micro)frame's worth of data can be
  23752. + * programmed into a channel.)
  23753. + */
  23754. + uint32_t max_periodic_len =
  23755. + hc->multi_count * hc->max_packet;
  23756. + if (hc->xfer_len > max_periodic_len) {
  23757. + hc->xfer_len = max_periodic_len;
  23758. + } else {
  23759. + }
  23760. + } else if (hc->xfer_len > max_hc_xfer_size) {
  23761. + /* Make sure that xfer_len is a multiple of max packet size. */
  23762. + hc->xfer_len = max_hc_xfer_size - hc->max_packet + 1;
  23763. + }
  23764. +
  23765. + if (hc->xfer_len > 0) {
  23766. + num_packets =
  23767. + (hc->xfer_len + hc->max_packet -
  23768. + 1) / hc->max_packet;
  23769. + if (num_packets > max_hc_pkt_count) {
  23770. + num_packets = max_hc_pkt_count;
  23771. + hc->xfer_len = num_packets * hc->max_packet;
  23772. + }
  23773. + } else {
  23774. + /* Need 1 packet for transfer length of 0. */
  23775. + num_packets = 1;
  23776. + }
  23777. +
  23778. + if (hc->ep_is_in) {
  23779. + /* Always program an integral # of max packets for IN transfers. */
  23780. + hc->xfer_len = num_packets * hc->max_packet;
  23781. + }
  23782. +
  23783. + if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
  23784. + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
  23785. + /*
  23786. + * Make sure that the multi_count field matches the
  23787. + * actual transfer length.
  23788. + */
  23789. + hc->multi_count = num_packets;
  23790. + }
  23791. +
  23792. + if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
  23793. + set_pid_isoc(hc);
  23794. +
  23795. + hctsiz.b.xfersize = hc->xfer_len;
  23796. + }
  23797. +
  23798. + hc->start_pkt_count = num_packets;
  23799. + hctsiz.b.pktcnt = num_packets;
  23800. + hctsiz.b.pid = hc->data_pid_start;
  23801. + DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
  23802. +
  23803. + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
  23804. + DWC_DEBUGPL(DBG_HCDV, " Xfer Size: %d\n", hctsiz.b.xfersize);
  23805. + DWC_DEBUGPL(DBG_HCDV, " Num Pkts: %d\n", hctsiz.b.pktcnt);
  23806. + DWC_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid);
  23807. +
  23808. + if (core_if->dma_enable) {
  23809. + dwc_dma_t dma_addr;
  23810. + if (hc->align_buff) {
  23811. + dma_addr = hc->align_buff;
  23812. + } else {
  23813. + dma_addr = ((unsigned long)hc->xfer_buff & 0xffffffff);
  23814. + }
  23815. + DWC_WRITE_REG32(&hc_regs->hcdma, dma_addr);
  23816. + }
  23817. +
  23818. + /* Start the split */
  23819. + if (hc->do_split) {
  23820. + hcsplt_data_t hcsplt;
  23821. + hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
  23822. + hcsplt.b.spltena = 1;
  23823. + DWC_WRITE_REG32(&hc_regs->hcsplt, hcsplt.d32);
  23824. + }
  23825. +
  23826. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  23827. + hcchar.b.multicnt = hc->multi_count;
  23828. + hc_set_even_odd_frame(core_if, hc, &hcchar);
  23829. +#ifdef DEBUG
  23830. + core_if->start_hcchar_val[hc->hc_num] = hcchar.d32;
  23831. + if (hcchar.b.chdis) {
  23832. + DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
  23833. + __func__, hc->hc_num, hcchar.d32);
  23834. + }
  23835. +#endif
  23836. +
  23837. + /* Set host channel enable after all other setup is complete. */
  23838. + hcchar.b.chen = 1;
  23839. + hcchar.b.chdis = 0;
  23840. + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
  23841. +
  23842. + hc->xfer_started = 1;
  23843. + hc->requests++;
  23844. +
  23845. + if (!core_if->dma_enable && !hc->ep_is_in && hc->xfer_len > 0) {
  23846. + /* Load OUT packet into the appropriate Tx FIFO. */
  23847. + dwc_otg_hc_write_packet(core_if, hc);
  23848. + }
  23849. +#ifdef DEBUG
  23850. + if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) {
  23851. + DWC_DEBUGPL(DBG_HCDV, "transfer %d from core_if %p\n",
  23852. + hc->hc_num, core_if);//GRAYG
  23853. + core_if->hc_xfer_info[hc->hc_num].core_if = core_if;
  23854. + core_if->hc_xfer_info[hc->hc_num].hc = hc;
  23855. +
  23856. + /* Start a timer for this transfer. */
  23857. + DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000);
  23858. + }
  23859. +#endif
  23860. +}
  23861. +
  23862. +/**
  23863. + * This function does the setup for a data transfer for a host channel
  23864. + * and starts the transfer in Descriptor DMA mode.
  23865. + *
  23866. + * Initializes HCTSIZ register. For a PING transfer the Do Ping bit is set.
  23867. + * Sets PID and NTD values. For periodic transfers
  23868. + * initializes SCHED_INFO field with micro-frame bitmap.
  23869. + *
  23870. + * Initializes HCDMA register with descriptor list address and CTD value
  23871. + * then starts the transfer via enabling the channel.
  23872. + *
  23873. + * @param core_if Programming view of DWC_otg controller.
  23874. + * @param hc Information needed to initialize the host channel.
  23875. + */
  23876. +void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
  23877. +{
  23878. + dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
  23879. + hcchar_data_t hcchar;
  23880. + hctsiz_data_t hctsiz;
  23881. + hcdma_data_t hcdma;
  23882. +
  23883. + hctsiz.d32 = 0;
  23884. +
  23885. + if (hc->do_ping)
  23886. + hctsiz.b_ddma.dopng = 1;
  23887. +
  23888. + if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
  23889. + set_pid_isoc(hc);
  23890. +
  23891. + /* Packet Count and Xfer Size are not used in Descriptor DMA mode */
  23892. + hctsiz.b_ddma.pid = hc->data_pid_start;
  23893. + hctsiz.b_ddma.ntd = hc->ntd - 1; /* 0 - 1 descriptor, 1 - 2 descriptors, etc. */
  23894. + hctsiz.b_ddma.schinfo = hc->schinfo; /* Non-zero only for high-speed interrupt endpoints */
  23895. +
  23896. + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
  23897. + DWC_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid);
  23898. + DWC_DEBUGPL(DBG_HCDV, " NTD: %d\n", hctsiz.b_ddma.ntd);
  23899. +
  23900. + DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
  23901. +
  23902. + hcdma.d32 = 0;
  23903. + hcdma.b.dma_addr = ((uint32_t) hc->desc_list_addr) >> 11;
  23904. +
  23905. + /* Always start from first descriptor. */
  23906. + hcdma.b.ctd = 0;
  23907. + DWC_WRITE_REG32(&hc_regs->hcdma, hcdma.d32);
  23908. +
  23909. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  23910. + hcchar.b.multicnt = hc->multi_count;
  23911. +
  23912. +#ifdef DEBUG
  23913. + core_if->start_hcchar_val[hc->hc_num] = hcchar.d32;
  23914. + if (hcchar.b.chdis) {
  23915. + DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
  23916. + __func__, hc->hc_num, hcchar.d32);
  23917. + }
  23918. +#endif
  23919. +
  23920. + /* Set host channel enable after all other setup is complete. */
  23921. + hcchar.b.chen = 1;
  23922. + hcchar.b.chdis = 0;
  23923. +
  23924. + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
  23925. +
  23926. + hc->xfer_started = 1;
  23927. + hc->requests++;
  23928. +
  23929. +#ifdef DEBUG
  23930. + if ((hc->ep_type != DWC_OTG_EP_TYPE_INTR)
  23931. + && (hc->ep_type != DWC_OTG_EP_TYPE_ISOC)) {
  23932. + DWC_DEBUGPL(DBG_HCDV, "DMA transfer %d from core_if %p\n",
  23933. + hc->hc_num, core_if);//GRAYG
  23934. + core_if->hc_xfer_info[hc->hc_num].core_if = core_if;
  23935. + core_if->hc_xfer_info[hc->hc_num].hc = hc;
  23936. + /* Start a timer for this transfer. */
  23937. + DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000);
  23938. + }
  23939. +#endif
  23940. +
  23941. +}
  23942. +
  23943. +/**
  23944. + * This function continues a data transfer that was started by previous call
  23945. + * to <code>dwc_otg_hc_start_transfer</code>. The caller must ensure there is
  23946. + * sufficient space in the request queue and Tx Data FIFO. This function
  23947. + * should only be called in Slave mode. In DMA mode, the controller acts
  23948. + * autonomously to complete transfers programmed to a host channel.
  23949. + *
  23950. + * For an OUT transfer, a new data packet is loaded into the appropriate FIFO
  23951. + * if there is any data remaining to be queued. For an IN transfer, another
  23952. + * data packet is always requested. For the SETUP phase of a control transfer,
  23953. + * this function does nothing.
  23954. + *
  23955. + * @return 1 if a new request is queued, 0 if no more requests are required
  23956. + * for this transfer.
  23957. + */
  23958. +int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
  23959. +{
  23960. + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
  23961. +
  23962. + if (hc->do_split) {
  23963. + /* SPLITs always queue just once per channel */
  23964. + return 0;
  23965. + } else if (hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
  23966. + /* SETUPs are queued only once since they can't be NAKed. */
  23967. + return 0;
  23968. + } else if (hc->ep_is_in) {
  23969. + /*
  23970. + * Always queue another request for other IN transfers. If
  23971. + * back-to-back INs are issued and NAKs are received for both,
  23972. + * the driver may still be processing the first NAK when the
  23973. + * second NAK is received. When the interrupt handler clears
  23974. + * the NAK interrupt for the first NAK, the second NAK will
  23975. + * not be seen. So we can't depend on the NAK interrupt
  23976. + * handler to requeue a NAKed request. Instead, IN requests
  23977. + * are issued each time this function is called. When the
  23978. + * transfer completes, the extra requests for the channel will
  23979. + * be flushed.
  23980. + */
  23981. + hcchar_data_t hcchar;
  23982. + dwc_otg_hc_regs_t *hc_regs =
  23983. + core_if->host_if->hc_regs[hc->hc_num];
  23984. +
  23985. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  23986. + hc_set_even_odd_frame(core_if, hc, &hcchar);
  23987. + hcchar.b.chen = 1;
  23988. + hcchar.b.chdis = 0;
  23989. + DWC_DEBUGPL(DBG_HCDV, " IN xfer: hcchar = 0x%08x\n",
  23990. + hcchar.d32);
  23991. + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
  23992. + hc->requests++;
  23993. + return 1;
  23994. + } else {
  23995. + /* OUT transfers. */
  23996. + if (hc->xfer_count < hc->xfer_len) {
  23997. + if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
  23998. + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
  23999. + hcchar_data_t hcchar;
  24000. + dwc_otg_hc_regs_t *hc_regs;
  24001. + hc_regs = core_if->host_if->hc_regs[hc->hc_num];
  24002. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  24003. + hc_set_even_odd_frame(core_if, hc, &hcchar);
  24004. + }
  24005. +
  24006. + /* Load OUT packet into the appropriate Tx FIFO. */
  24007. + dwc_otg_hc_write_packet(core_if, hc);
  24008. + hc->requests++;
  24009. + return 1;
  24010. + } else {
  24011. + return 0;
  24012. + }
  24013. + }
  24014. +}
  24015. +
  24016. +/**
  24017. + * Starts a PING transfer. This function should only be called in Slave mode.
  24018. + * The Do Ping bit is set in the HCTSIZ register, then the channel is enabled.
  24019. + */
  24020. +void dwc_otg_hc_do_ping(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
  24021. +{
  24022. + hcchar_data_t hcchar;
  24023. + hctsiz_data_t hctsiz;
  24024. + dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num];
  24025. +
  24026. + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num);
  24027. +
  24028. + hctsiz.d32 = 0;
  24029. + hctsiz.b.dopng = 1;
  24030. + hctsiz.b.pktcnt = 1;
  24031. + DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
  24032. +
  24033. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  24034. + hcchar.b.chen = 1;
  24035. + hcchar.b.chdis = 0;
  24036. + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
  24037. +}
  24038. +
  24039. +/*
  24040. + * This function writes a packet into the Tx FIFO associated with the Host
  24041. + * Channel. For a channel associated with a non-periodic EP, the non-periodic
  24042. + * Tx FIFO is written. For a channel associated with a periodic EP, the
  24043. + * periodic Tx FIFO is written. This function should only be called in Slave
  24044. + * mode.
  24045. + *
  24046. + * Upon return the xfer_buff and xfer_count fields in _hc are incremented by
  24047. + * then number of bytes written to the Tx FIFO.
  24048. + */
  24049. +void dwc_otg_hc_write_packet(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
  24050. +{
  24051. + uint32_t i;
  24052. + uint32_t remaining_count;
  24053. + uint32_t byte_count;
  24054. + uint32_t dword_count;
  24055. +
  24056. + uint32_t *data_buff = (uint32_t *) (hc->xfer_buff);
  24057. + uint32_t *data_fifo = core_if->data_fifo[hc->hc_num];
  24058. +
  24059. + remaining_count = hc->xfer_len - hc->xfer_count;
  24060. + if (remaining_count > hc->max_packet) {
  24061. + byte_count = hc->max_packet;
  24062. + } else {
  24063. + byte_count = remaining_count;
  24064. + }
  24065. +
  24066. + dword_count = (byte_count + 3) / 4;
  24067. +
  24068. + if ((((unsigned long)data_buff) & 0x3) == 0) {
  24069. + /* xfer_buff is DWORD aligned. */
  24070. + for (i = 0; i < dword_count; i++, data_buff++) {
  24071. + DWC_WRITE_REG32(data_fifo, *data_buff);
  24072. + }
  24073. + } else {
  24074. + /* xfer_buff is not DWORD aligned. */
  24075. + for (i = 0; i < dword_count; i++, data_buff++) {
  24076. + uint32_t data;
  24077. + data =
  24078. + (data_buff[0] | data_buff[1] << 8 | data_buff[2] <<
  24079. + 16 | data_buff[3] << 24);
  24080. + DWC_WRITE_REG32(data_fifo, data);
  24081. + }
  24082. + }
  24083. +
  24084. + hc->xfer_count += byte_count;
  24085. + hc->xfer_buff += byte_count;
  24086. +}
  24087. +
  24088. +/**
  24089. + * Gets the current USB frame number. This is the frame number from the last
  24090. + * SOF packet.
  24091. + */
  24092. +uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * core_if)
  24093. +{
  24094. + dsts_data_t dsts;
  24095. + dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
  24096. +
  24097. + /* read current frame/microframe number from DSTS register */
  24098. + return dsts.b.soffn;
  24099. +}
  24100. +
  24101. +/**
  24102. + * Calculates and gets the frame Interval value of HFIR register according PHY
  24103. + * type and speed.The application can modify a value of HFIR register only after
  24104. + * the Port Enable bit of the Host Port Control and Status register
  24105. + * (HPRT.PrtEnaPort) has been set.
  24106. +*/
  24107. +
  24108. +uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if)
  24109. +{
  24110. + gusbcfg_data_t usbcfg;
  24111. + hwcfg2_data_t hwcfg2;
  24112. + hprt0_data_t hprt0;
  24113. + int clock = 60; // default value
  24114. + usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
  24115. + hwcfg2.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2);
  24116. + hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
  24117. + if (!usbcfg.b.physel && usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif)
  24118. + clock = 60;
  24119. + if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 3)
  24120. + clock = 48;
  24121. + if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&
  24122. + !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif)
  24123. + clock = 30;
  24124. + if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&
  24125. + !usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif)
  24126. + clock = 60;
  24127. + if (usbcfg.b.phylpwrclksel && !usbcfg.b.physel &&
  24128. + !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif)
  24129. + clock = 48;
  24130. + if (usbcfg.b.physel && !usbcfg.b.phyif && hwcfg2.b.fs_phy_type == 2)
  24131. + clock = 48;
  24132. + if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 1)
  24133. + clock = 48;
  24134. + if (hprt0.b.prtspd == 0)
  24135. + /* High speed case */
  24136. + return 125 * clock;
  24137. + else
  24138. + /* FS/LS case */
  24139. + return 1000 * clock;
  24140. +}
  24141. +
  24142. +/**
  24143. + * This function reads a setup packet from the Rx FIFO into the destination
  24144. + * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl)
  24145. + * Interrupt routine when a SETUP packet has been received in Slave mode.
  24146. + *
  24147. + * @param core_if Programming view of DWC_otg controller.
  24148. + * @param dest Destination buffer for packet data.
  24149. + */
  24150. +void dwc_otg_read_setup_packet(dwc_otg_core_if_t * core_if, uint32_t * dest)
  24151. +{
  24152. + device_grxsts_data_t status;
  24153. + /* Get the 8 bytes of a setup transaction data */
  24154. +
  24155. + /* Pop 2 DWORDS off the receive data FIFO into memory */
  24156. + dest[0] = DWC_READ_REG32(core_if->data_fifo[0]);
  24157. + dest[1] = DWC_READ_REG32(core_if->data_fifo[0]);
  24158. + if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
  24159. + status.d32 =
  24160. + DWC_READ_REG32(&core_if->core_global_regs->grxstsp);
  24161. + DWC_DEBUGPL(DBG_ANY,
  24162. + "EP:%d BCnt:%d " "pktsts:%x Frame:%d(0x%0x)\n",
  24163. + status.b.epnum, status.b.bcnt, status.b.pktsts,
  24164. + status.b.fn, status.b.fn);
  24165. + }
  24166. +}
  24167. +
  24168. +/**
  24169. + * This function enables EP0 OUT to receive SETUP packets and configures EP0
  24170. + * IN for transmitting packets. It is normally called when the
  24171. + * "Enumeration Done" interrupt occurs.
  24172. + *
  24173. + * @param core_if Programming view of DWC_otg controller.
  24174. + * @param ep The EP0 data.
  24175. + */
  24176. +void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
  24177. +{
  24178. + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
  24179. + dsts_data_t dsts;
  24180. + depctl_data_t diepctl;
  24181. + depctl_data_t doepctl;
  24182. + dctl_data_t dctl = {.d32 = 0 };
  24183. +
  24184. + ep->stp_rollover = 0;
  24185. + /* Read the Device Status and Endpoint 0 Control registers */
  24186. + dsts.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dsts);
  24187. + diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
  24188. + doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl);
  24189. +
  24190. + /* Set the MPS of the IN EP based on the enumeration speed */
  24191. + switch (dsts.b.enumspd) {
  24192. + case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
  24193. + case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
  24194. + case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
  24195. + diepctl.b.mps = DWC_DEP0CTL_MPS_64;
  24196. + break;
  24197. + case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
  24198. + diepctl.b.mps = DWC_DEP0CTL_MPS_8;
  24199. + break;
  24200. + }
  24201. +
  24202. + DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
  24203. +
  24204. + /* Enable OUT EP for receive */
  24205. + if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
  24206. + doepctl.b.epena = 1;
  24207. + DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);
  24208. + }
  24209. +#ifdef VERBOSE
  24210. + DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n",
  24211. + DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
  24212. + DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n",
  24213. + DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl));
  24214. +#endif
  24215. + dctl.b.cgnpinnak = 1;
  24216. +
  24217. + DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
  24218. + DWC_DEBUGPL(DBG_PCDV, "dctl=%0x\n",
  24219. + DWC_READ_REG32(&dev_if->dev_global_regs->dctl));
  24220. +
  24221. +}
  24222. +
  24223. +/**
  24224. + * This function activates an EP. The Device EP control register for
  24225. + * the EP is configured as defined in the ep structure. Note: This
  24226. + * function is not used for EP0.
  24227. + *
  24228. + * @param core_if Programming view of DWC_otg controller.
  24229. + * @param ep The EP to activate.
  24230. + */
  24231. +void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
  24232. +{
  24233. + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
  24234. + depctl_data_t depctl;
  24235. + volatile uint32_t *addr;
  24236. + daint_data_t daintmsk = {.d32 = 0 };
  24237. + dcfg_data_t dcfg;
  24238. + uint8_t i;
  24239. +
  24240. + DWC_DEBUGPL(DBG_PCDV, "%s() EP%d-%s\n", __func__, ep->num,
  24241. + (ep->is_in ? "IN" : "OUT"));
  24242. +
  24243. +#ifdef DWC_UTE_PER_IO
  24244. + ep->xiso_frame_num = 0xFFFFFFFF;
  24245. + ep->xiso_active_xfers = 0;
  24246. + ep->xiso_queued_xfers = 0;
  24247. +#endif
  24248. + /* Read DEPCTLn register */
  24249. + if (ep->is_in == 1) {
  24250. + addr = &dev_if->in_ep_regs[ep->num]->diepctl;
  24251. + daintmsk.ep.in = 1 << ep->num;
  24252. + } else {
  24253. + addr = &dev_if->out_ep_regs[ep->num]->doepctl;
  24254. + daintmsk.ep.out = 1 << ep->num;
  24255. + }
  24256. +
  24257. + /* If the EP is already active don't change the EP Control
  24258. + * register. */
  24259. + depctl.d32 = DWC_READ_REG32(addr);
  24260. + if (!depctl.b.usbactep) {
  24261. + depctl.b.mps = ep->maxpacket;
  24262. + depctl.b.eptype = ep->type;
  24263. + depctl.b.txfnum = ep->tx_fifo_num;
  24264. +
  24265. + if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
  24266. + depctl.b.setd0pid = 1; // ???
  24267. + } else {
  24268. + depctl.b.setd0pid = 1;
  24269. + }
  24270. + depctl.b.usbactep = 1;
  24271. +
  24272. + /* Update nextep_seq array and EPMSCNT in DCFG*/
  24273. + if (!(depctl.b.eptype & 1) && (ep->is_in == 1)) { // NP IN EP
  24274. + for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
  24275. + if (core_if->nextep_seq[i] == core_if->first_in_nextep_seq)
  24276. + break;
  24277. + }
  24278. + core_if->nextep_seq[i] = ep->num;
  24279. + core_if->nextep_seq[ep->num] = core_if->first_in_nextep_seq;
  24280. + depctl.b.nextep = core_if->nextep_seq[ep->num];
  24281. + dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
  24282. + dcfg.b.epmscnt++;
  24283. + DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
  24284. +
  24285. + DWC_DEBUGPL(DBG_PCDV,
  24286. + "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
  24287. + __func__, core_if->first_in_nextep_seq);
  24288. + for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
  24289. + DWC_DEBUGPL(DBG_PCDV, "%2d\n",
  24290. + core_if->nextep_seq[i]);
  24291. + }
  24292. +
  24293. + }
  24294. +
  24295. +
  24296. + DWC_WRITE_REG32(addr, depctl.d32);
  24297. + DWC_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", DWC_READ_REG32(addr));
  24298. + }
  24299. +
  24300. + /* Enable the Interrupt for this EP */
  24301. + if (core_if->multiproc_int_enable) {
  24302. + if (ep->is_in == 1) {
  24303. + diepmsk_data_t diepmsk = {.d32 = 0 };
  24304. + diepmsk.b.xfercompl = 1;
  24305. + diepmsk.b.timeout = 1;
  24306. + diepmsk.b.epdisabled = 1;
  24307. + diepmsk.b.ahberr = 1;
  24308. + diepmsk.b.intknepmis = 1;
  24309. + if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
  24310. + diepmsk.b.intknepmis = 0;
  24311. + diepmsk.b.txfifoundrn = 1; //?????
  24312. + if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
  24313. + diepmsk.b.nak = 1;
  24314. + }
  24315. +
  24316. +
  24317. +
  24318. +/*
  24319. + if (core_if->dma_desc_enable) {
  24320. + diepmsk.b.bna = 1;
  24321. + }
  24322. +*/
  24323. +/*
  24324. + if (core_if->dma_enable) {
  24325. + doepmsk.b.nak = 1;
  24326. + }
  24327. +*/
  24328. + DWC_WRITE_REG32(&dev_if->dev_global_regs->
  24329. + diepeachintmsk[ep->num], diepmsk.d32);
  24330. +
  24331. + } else {
  24332. + doepmsk_data_t doepmsk = {.d32 = 0 };
  24333. + doepmsk.b.xfercompl = 1;
  24334. + doepmsk.b.ahberr = 1;
  24335. + doepmsk.b.epdisabled = 1;
  24336. + if (ep->type == DWC_OTG_EP_TYPE_ISOC)
  24337. + doepmsk.b.outtknepdis = 1;
  24338. +
  24339. +/*
  24340. +
  24341. + if (core_if->dma_desc_enable) {
  24342. + doepmsk.b.bna = 1;
  24343. + }
  24344. +*/
  24345. +/*
  24346. + doepmsk.b.babble = 1;
  24347. + doepmsk.b.nyet = 1;
  24348. + doepmsk.b.nak = 1;
  24349. +*/
  24350. + DWC_WRITE_REG32(&dev_if->dev_global_regs->
  24351. + doepeachintmsk[ep->num], doepmsk.d32);
  24352. + }
  24353. + DWC_MODIFY_REG32(&dev_if->dev_global_regs->deachintmsk,
  24354. + 0, daintmsk.d32);
  24355. + } else {
  24356. + if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
  24357. + if (ep->is_in) {
  24358. + diepmsk_data_t diepmsk = {.d32 = 0 };
  24359. + diepmsk.b.nak = 1;
  24360. + DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32);
  24361. + } else {
  24362. + doepmsk_data_t doepmsk = {.d32 = 0 };
  24363. + doepmsk.b.outtknepdis = 1;
  24364. + DWC_MODIFY_REG32(&dev_if->dev_global_regs->doepmsk, 0, doepmsk.d32);
  24365. + }
  24366. + }
  24367. + DWC_MODIFY_REG32(&dev_if->dev_global_regs->daintmsk,
  24368. + 0, daintmsk.d32);
  24369. + }
  24370. +
  24371. + DWC_DEBUGPL(DBG_PCDV, "DAINTMSK=%0x\n",
  24372. + DWC_READ_REG32(&dev_if->dev_global_regs->daintmsk));
  24373. +
  24374. + ep->stall_clear_flag = 0;
  24375. +
  24376. + return;
  24377. +}
  24378. +
  24379. +/**
  24380. + * This function deactivates an EP. This is done by clearing the USB Active
  24381. + * EP bit in the Device EP control register. Note: This function is not used
  24382. + * for EP0. EP0 cannot be deactivated.
  24383. + *
  24384. + * @param core_if Programming view of DWC_otg controller.
  24385. + * @param ep The EP to deactivate.
  24386. + */
  24387. +void dwc_otg_ep_deactivate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
  24388. +{
  24389. + depctl_data_t depctl = {.d32 = 0 };
  24390. + volatile uint32_t *addr;
  24391. + daint_data_t daintmsk = {.d32 = 0 };
  24392. + dcfg_data_t dcfg;
  24393. + uint8_t i = 0;
  24394. +
  24395. +#ifdef DWC_UTE_PER_IO
  24396. + ep->xiso_frame_num = 0xFFFFFFFF;
  24397. + ep->xiso_active_xfers = 0;
  24398. + ep->xiso_queued_xfers = 0;
  24399. +#endif
  24400. +
  24401. + /* Read DEPCTLn register */
  24402. + if (ep->is_in == 1) {
  24403. + addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
  24404. + daintmsk.ep.in = 1 << ep->num;
  24405. + } else {
  24406. + addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
  24407. + daintmsk.ep.out = 1 << ep->num;
  24408. + }
  24409. +
  24410. + depctl.d32 = DWC_READ_REG32(addr);
  24411. +
  24412. + depctl.b.usbactep = 0;
  24413. +
  24414. + /* Update nextep_seq array and EPMSCNT in DCFG*/
  24415. + if (!(depctl.b.eptype & 1) && ep->is_in == 1) { // NP EP IN
  24416. + for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
  24417. + if (core_if->nextep_seq[i] == ep->num)
  24418. + break;
  24419. + }
  24420. + core_if->nextep_seq[i] = core_if->nextep_seq[ep->num];
  24421. + if (core_if->first_in_nextep_seq == ep->num)
  24422. + core_if->first_in_nextep_seq = i;
  24423. + core_if->nextep_seq[ep->num] = 0xff;
  24424. + depctl.b.nextep = 0;
  24425. + dcfg.d32 =
  24426. + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
  24427. + dcfg.b.epmscnt--;
  24428. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
  24429. + dcfg.d32);
  24430. +
  24431. + DWC_DEBUGPL(DBG_PCDV,
  24432. + "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
  24433. + __func__, core_if->first_in_nextep_seq);
  24434. + for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
  24435. + DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]);
  24436. + }
  24437. + }
  24438. +
  24439. + if (ep->is_in == 1)
  24440. + depctl.b.txfnum = 0;
  24441. +
  24442. + if (core_if->dma_desc_enable)
  24443. + depctl.b.epdis = 1;
  24444. +
  24445. + DWC_WRITE_REG32(addr, depctl.d32);
  24446. + depctl.d32 = DWC_READ_REG32(addr);
  24447. + if (core_if->dma_enable && ep->type == DWC_OTG_EP_TYPE_ISOC
  24448. + && depctl.b.epena) {
  24449. + depctl_data_t depctl = {.d32 = 0};
  24450. + if (ep->is_in) {
  24451. + diepint_data_t diepint = {.d32 = 0};
  24452. +
  24453. + depctl.b.snak = 1;
  24454. + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
  24455. + diepctl, depctl.d32);
  24456. + do {
  24457. + dwc_udelay(10);
  24458. + diepint.d32 =
  24459. + DWC_READ_REG32(&core_if->
  24460. + dev_if->in_ep_regs[ep->num]->
  24461. + diepint);
  24462. + } while (!diepint.b.inepnakeff);
  24463. + diepint.b.inepnakeff = 1;
  24464. + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
  24465. + diepint, diepint.d32);
  24466. + depctl.d32 = 0;
  24467. + depctl.b.epdis = 1;
  24468. + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
  24469. + diepctl, depctl.d32);
  24470. + do {
  24471. + dwc_udelay(10);
  24472. + diepint.d32 =
  24473. + DWC_READ_REG32(&core_if->
  24474. + dev_if->in_ep_regs[ep->num]->
  24475. + diepint);
  24476. + } while (!diepint.b.epdisabled);
  24477. + diepint.b.epdisabled = 1;
  24478. + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
  24479. + diepint, diepint.d32);
  24480. + } else {
  24481. + dctl_data_t dctl = {.d32 = 0};
  24482. + gintmsk_data_t gintsts = {.d32 = 0};
  24483. + doepint_data_t doepint = {.d32 = 0};
  24484. + dctl.b.sgoutnak = 1;
  24485. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
  24486. + dctl, 0, dctl.d32);
  24487. + do {
  24488. + dwc_udelay(10);
  24489. + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
  24490. + } while (!gintsts.b.goutnakeff);
  24491. + gintsts.d32 = 0;
  24492. + gintsts.b.goutnakeff = 1;
  24493. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
  24494. +
  24495. + depctl.d32 = 0;
  24496. + depctl.b.epdis = 1;
  24497. + depctl.b.snak = 1;
  24498. + DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepctl, depctl.d32);
  24499. + do
  24500. + {
  24501. + dwc_udelay(10);
  24502. + doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
  24503. + out_ep_regs[ep->num]->doepint);
  24504. + } while (!doepint.b.epdisabled);
  24505. +
  24506. + doepint.b.epdisabled = 1;
  24507. + DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepint, doepint.d32);
  24508. +
  24509. + dctl.d32 = 0;
  24510. + dctl.b.cgoutnak = 1;
  24511. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
  24512. + }
  24513. + }
  24514. +
  24515. + /* Disable the Interrupt for this EP */
  24516. + if (core_if->multiproc_int_enable) {
  24517. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->deachintmsk,
  24518. + daintmsk.d32, 0);
  24519. +
  24520. + if (ep->is_in == 1) {
  24521. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
  24522. + diepeachintmsk[ep->num], 0);
  24523. + } else {
  24524. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->
  24525. + doepeachintmsk[ep->num], 0);
  24526. + }
  24527. + } else {
  24528. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->daintmsk,
  24529. + daintmsk.d32, 0);
  24530. + }
  24531. +
  24532. +}
  24533. +
  24534. +/**
  24535. + * This function initializes dma descriptor chain.
  24536. + *
  24537. + * @param core_if Programming view of DWC_otg controller.
  24538. + * @param ep The EP to start the transfer on.
  24539. + */
  24540. +static void init_dma_desc_chain(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
  24541. +{
  24542. + dwc_otg_dev_dma_desc_t *dma_desc;
  24543. + uint32_t offset;
  24544. + uint32_t xfer_est;
  24545. + int i;
  24546. + unsigned maxxfer_local, total_len;
  24547. +
  24548. + if (!ep->is_in && ep->type == DWC_OTG_EP_TYPE_INTR &&
  24549. + (ep->maxpacket%4)) {
  24550. + maxxfer_local = ep->maxpacket;
  24551. + total_len = ep->xfer_len;
  24552. + } else {
  24553. + maxxfer_local = ep->maxxfer;
  24554. + total_len = ep->total_len;
  24555. + }
  24556. +
  24557. + ep->desc_cnt = (total_len / maxxfer_local) +
  24558. + ((total_len % maxxfer_local) ? 1 : 0);
  24559. +
  24560. + if (!ep->desc_cnt)
  24561. + ep->desc_cnt = 1;
  24562. +
  24563. + if (ep->desc_cnt > MAX_DMA_DESC_CNT)
  24564. + ep->desc_cnt = MAX_DMA_DESC_CNT;
  24565. +
  24566. + dma_desc = ep->desc_addr;
  24567. + if (maxxfer_local == ep->maxpacket) {
  24568. + if ((total_len % maxxfer_local) &&
  24569. + (total_len/maxxfer_local < MAX_DMA_DESC_CNT)) {
  24570. + xfer_est = (ep->desc_cnt - 1) * maxxfer_local +
  24571. + (total_len % maxxfer_local);
  24572. + } else
  24573. + xfer_est = ep->desc_cnt * maxxfer_local;
  24574. + } else
  24575. + xfer_est = total_len;
  24576. + offset = 0;
  24577. + for (i = 0; i < ep->desc_cnt; ++i) {
  24578. + /** DMA Descriptor Setup */
  24579. + if (xfer_est > maxxfer_local) {
  24580. + dma_desc->status.b.bs = BS_HOST_BUSY;
  24581. + dma_desc->status.b.l = 0;
  24582. + dma_desc->status.b.ioc = 0;
  24583. + dma_desc->status.b.sp = 0;
  24584. + dma_desc->status.b.bytes = maxxfer_local;
  24585. + dma_desc->buf = ep->dma_addr + offset;
  24586. + dma_desc->status.b.sts = 0;
  24587. + dma_desc->status.b.bs = BS_HOST_READY;
  24588. +
  24589. + xfer_est -= maxxfer_local;
  24590. + offset += maxxfer_local;
  24591. + } else {
  24592. + dma_desc->status.b.bs = BS_HOST_BUSY;
  24593. + dma_desc->status.b.l = 1;
  24594. + dma_desc->status.b.ioc = 1;
  24595. + if (ep->is_in) {
  24596. + dma_desc->status.b.sp =
  24597. + (xfer_est %
  24598. + ep->maxpacket) ? 1 : ((ep->
  24599. + sent_zlp) ? 1 : 0);
  24600. + dma_desc->status.b.bytes = xfer_est;
  24601. + } else {
  24602. + if (maxxfer_local == ep->maxpacket)
  24603. + dma_desc->status.b.bytes = xfer_est;
  24604. + else
  24605. + dma_desc->status.b.bytes =
  24606. + xfer_est + ((4 - (xfer_est & 0x3)) & 0x3);
  24607. + }
  24608. +
  24609. + dma_desc->buf = ep->dma_addr + offset;
  24610. + dma_desc->status.b.sts = 0;
  24611. + dma_desc->status.b.bs = BS_HOST_READY;
  24612. + }
  24613. + dma_desc++;
  24614. + }
  24615. +}
  24616. +/**
  24617. + * This function is called when to write ISOC data into appropriate dedicated
  24618. + * periodic FIFO.
  24619. + */
  24620. +static int32_t write_isoc_tx_fifo(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep)
  24621. +{
  24622. + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
  24623. + dwc_otg_dev_in_ep_regs_t *ep_regs;
  24624. + dtxfsts_data_t txstatus = {.d32 = 0 };
  24625. + uint32_t len = 0;
  24626. + int epnum = dwc_ep->num;
  24627. + int dwords;
  24628. +
  24629. + DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum);
  24630. +
  24631. + ep_regs = core_if->dev_if->in_ep_regs[epnum];
  24632. +
  24633. + len = dwc_ep->xfer_len - dwc_ep->xfer_count;
  24634. +
  24635. + if (len > dwc_ep->maxpacket) {
  24636. + len = dwc_ep->maxpacket;
  24637. + }
  24638. +
  24639. + dwords = (len + 3) / 4;
  24640. +
  24641. + /* While there is space in the queue and space in the FIFO and
  24642. + * More data to tranfer, Write packets to the Tx FIFO */
  24643. + txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
  24644. + DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);
  24645. +
  24646. + while (txstatus.b.txfspcavail > dwords &&
  24647. + dwc_ep->xfer_count < dwc_ep->xfer_len && dwc_ep->xfer_len != 0) {
  24648. + /* Write the FIFO */
  24649. + dwc_otg_ep_write_packet(core_if, dwc_ep, 0);
  24650. +
  24651. + len = dwc_ep->xfer_len - dwc_ep->xfer_count;
  24652. + if (len > dwc_ep->maxpacket) {
  24653. + len = dwc_ep->maxpacket;
  24654. + }
  24655. +
  24656. + dwords = (len + 3) / 4;
  24657. + txstatus.d32 =
  24658. + DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
  24659. + DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum,
  24660. + txstatus.d32);
  24661. + }
  24662. +
  24663. + DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum,
  24664. + DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts));
  24665. +
  24666. + return 1;
  24667. +}
  24668. +/**
  24669. + * This function does the setup for a data transfer for an EP and
  24670. + * starts the transfer. For an IN transfer, the packets will be
  24671. + * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,
  24672. + * the packets are unloaded from the Rx FIFO in the ISR. the ISR.
  24673. + *
  24674. + * @param core_if Programming view of DWC_otg controller.
  24675. + * @param ep The EP to start the transfer on.
  24676. + */
  24677. +
  24678. +void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
  24679. +{
  24680. + depctl_data_t depctl;
  24681. + deptsiz_data_t deptsiz;
  24682. + gintmsk_data_t intr_mask = {.d32 = 0 };
  24683. +
  24684. + DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__);
  24685. + DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "
  24686. + "xfer_buff=%p start_xfer_buff=%p, total_len = %d\n",
  24687. + ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len,
  24688. + ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff,
  24689. + ep->total_len);
  24690. + /* IN endpoint */
  24691. + if (ep->is_in == 1) {
  24692. + dwc_otg_dev_in_ep_regs_t *in_regs =
  24693. + core_if->dev_if->in_ep_regs[ep->num];
  24694. +
  24695. + gnptxsts_data_t gtxstatus;
  24696. +
  24697. + gtxstatus.d32 =
  24698. + DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);
  24699. +
  24700. + if (core_if->en_multiple_tx_fifo == 0
  24701. + && gtxstatus.b.nptxqspcavail == 0 && !core_if->dma_enable) {
  24702. +#ifdef DEBUG
  24703. + DWC_PRINTF("TX Queue Full (0x%0x)\n", gtxstatus.d32);
  24704. +#endif
  24705. + return;
  24706. + }
  24707. +
  24708. + depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
  24709. + deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
  24710. +
  24711. + if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT)
  24712. + ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?
  24713. + ep->maxxfer : (ep->total_len - ep->xfer_len);
  24714. + else
  24715. + ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ?
  24716. + MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
  24717. +
  24718. +
  24719. + /* Zero Length Packet? */
  24720. + if ((ep->xfer_len - ep->xfer_count) == 0) {
  24721. + deptsiz.b.xfersize = 0;
  24722. + deptsiz.b.pktcnt = 1;
  24723. + } else {
  24724. + /* Program the transfer size and packet count
  24725. + * as follows: xfersize = N * maxpacket +
  24726. + * short_packet pktcnt = N + (short_packet
  24727. + * exist ? 1 : 0)
  24728. + */
  24729. + deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
  24730. + deptsiz.b.pktcnt =
  24731. + (ep->xfer_len - ep->xfer_count - 1 +
  24732. + ep->maxpacket) / ep->maxpacket;
  24733. + if (deptsiz.b.pktcnt > MAX_PKT_CNT) {
  24734. + deptsiz.b.pktcnt = MAX_PKT_CNT;
  24735. + deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
  24736. + }
  24737. + if (ep->type == DWC_OTG_EP_TYPE_ISOC)
  24738. + deptsiz.b.mc = deptsiz.b.pktcnt;
  24739. + }
  24740. +
  24741. + /* Write the DMA register */
  24742. + if (core_if->dma_enable) {
  24743. + if (core_if->dma_desc_enable == 0) {
  24744. + if (ep->type != DWC_OTG_EP_TYPE_ISOC)
  24745. + deptsiz.b.mc = 1;
  24746. + DWC_WRITE_REG32(&in_regs->dieptsiz,
  24747. + deptsiz.d32);
  24748. + DWC_WRITE_REG32(&(in_regs->diepdma),
  24749. + (uint32_t) ep->dma_addr);
  24750. + } else {
  24751. +#ifdef DWC_UTE_CFI
  24752. + /* The descriptor chain should be already initialized by now */
  24753. + if (ep->buff_mode != BM_STANDARD) {
  24754. + DWC_WRITE_REG32(&in_regs->diepdma,
  24755. + ep->descs_dma_addr);
  24756. + } else {
  24757. +#endif
  24758. + init_dma_desc_chain(core_if, ep);
  24759. + /** DIEPDMAn Register write */
  24760. + DWC_WRITE_REG32(&in_regs->diepdma,
  24761. + ep->dma_desc_addr);
  24762. +#ifdef DWC_UTE_CFI
  24763. + }
  24764. +#endif
  24765. + }
  24766. + } else {
  24767. + DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
  24768. + if (ep->type != DWC_OTG_EP_TYPE_ISOC) {
  24769. + /**
  24770. + * Enable the Non-Periodic Tx FIFO empty interrupt,
  24771. + * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode,
  24772. + * the data will be written into the fifo by the ISR.
  24773. + */
  24774. + if (core_if->en_multiple_tx_fifo == 0) {
  24775. + intr_mask.b.nptxfempty = 1;
  24776. + DWC_MODIFY_REG32
  24777. + (&core_if->core_global_regs->gintmsk,
  24778. + intr_mask.d32, intr_mask.d32);
  24779. + } else {
  24780. + /* Enable the Tx FIFO Empty Interrupt for this EP */
  24781. + if (ep->xfer_len > 0) {
  24782. + uint32_t fifoemptymsk = 0;
  24783. + fifoemptymsk = 1 << ep->num;
  24784. + DWC_MODIFY_REG32
  24785. + (&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
  24786. + 0, fifoemptymsk);
  24787. +
  24788. + }
  24789. + }
  24790. + } else {
  24791. + write_isoc_tx_fifo(core_if, ep);
  24792. + }
  24793. + }
  24794. + if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
  24795. + depctl.b.nextep = core_if->nextep_seq[ep->num];
  24796. +
  24797. + if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
  24798. + dsts_data_t dsts = {.d32 = 0};
  24799. + if (ep->bInterval == 1) {
  24800. + dsts.d32 =
  24801. + DWC_READ_REG32(&core_if->dev_if->
  24802. + dev_global_regs->dsts);
  24803. + ep->frame_num = dsts.b.soffn + ep->bInterval;
  24804. + if (ep->frame_num > 0x3FFF) {
  24805. + ep->frm_overrun = 1;
  24806. + ep->frame_num &= 0x3FFF;
  24807. + } else
  24808. + ep->frm_overrun = 0;
  24809. + if (ep->frame_num & 0x1) {
  24810. + depctl.b.setd1pid = 1;
  24811. + } else {
  24812. + depctl.b.setd0pid = 1;
  24813. + }
  24814. + }
  24815. + }
  24816. + /* EP enable, IN data in FIFO */
  24817. + depctl.b.cnak = 1;
  24818. + depctl.b.epena = 1;
  24819. + DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
  24820. +
  24821. + } else {
  24822. + /* OUT endpoint */
  24823. + dwc_otg_dev_out_ep_regs_t *out_regs =
  24824. + core_if->dev_if->out_ep_regs[ep->num];
  24825. +
  24826. + depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
  24827. + deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
  24828. +
  24829. + if (!core_if->dma_desc_enable) {
  24830. + if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT)
  24831. + ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ?
  24832. + ep->maxxfer : (ep->total_len - ep->xfer_len);
  24833. + else
  24834. + ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len
  24835. + - ep->xfer_len)) ? MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len);
  24836. + }
  24837. +
  24838. + /* Program the transfer size and packet count as follows:
  24839. + *
  24840. + * pktcnt = N
  24841. + * xfersize = N * maxpacket
  24842. + */
  24843. + if ((ep->xfer_len - ep->xfer_count) == 0) {
  24844. + /* Zero Length Packet */
  24845. + deptsiz.b.xfersize = ep->maxpacket;
  24846. + deptsiz.b.pktcnt = 1;
  24847. + } else {
  24848. + deptsiz.b.pktcnt =
  24849. + (ep->xfer_len - ep->xfer_count +
  24850. + (ep->maxpacket - 1)) / ep->maxpacket;
  24851. + if (deptsiz.b.pktcnt > MAX_PKT_CNT) {
  24852. + deptsiz.b.pktcnt = MAX_PKT_CNT;
  24853. + }
  24854. + if (!core_if->dma_desc_enable) {
  24855. + ep->xfer_len =
  24856. + deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count;
  24857. + }
  24858. + deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count;
  24859. + }
  24860. +
  24861. + DWC_DEBUGPL(DBG_PCDV, "ep%d xfersize=%d pktcnt=%d\n",
  24862. + ep->num, deptsiz.b.xfersize, deptsiz.b.pktcnt);
  24863. +
  24864. + if (core_if->dma_enable) {
  24865. + if (!core_if->dma_desc_enable) {
  24866. + DWC_WRITE_REG32(&out_regs->doeptsiz,
  24867. + deptsiz.d32);
  24868. +
  24869. + DWC_WRITE_REG32(&(out_regs->doepdma),
  24870. + (uint32_t) ep->dma_addr);
  24871. + } else {
  24872. +#ifdef DWC_UTE_CFI
  24873. + /* The descriptor chain should be already initialized by now */
  24874. + if (ep->buff_mode != BM_STANDARD) {
  24875. + DWC_WRITE_REG32(&out_regs->doepdma,
  24876. + ep->descs_dma_addr);
  24877. + } else {
  24878. +#endif
  24879. + /** This is used for interrupt out transfers*/
  24880. + if (!ep->xfer_len)
  24881. + ep->xfer_len = ep->total_len;
  24882. + init_dma_desc_chain(core_if, ep);
  24883. +
  24884. + if (core_if->core_params->dev_out_nak) {
  24885. + if (ep->type == DWC_OTG_EP_TYPE_BULK) {
  24886. + deptsiz.b.pktcnt = (ep->total_len +
  24887. + (ep->maxpacket - 1)) / ep->maxpacket;
  24888. + deptsiz.b.xfersize = ep->total_len;
  24889. + /* Remember initial value of doeptsiz */
  24890. + core_if->start_doeptsiz_val[ep->num] = deptsiz.d32;
  24891. + DWC_WRITE_REG32(&out_regs->doeptsiz,
  24892. + deptsiz.d32);
  24893. + }
  24894. + }
  24895. + /** DOEPDMAn Register write */
  24896. + DWC_WRITE_REG32(&out_regs->doepdma,
  24897. + ep->dma_desc_addr);
  24898. +#ifdef DWC_UTE_CFI
  24899. + }
  24900. +#endif
  24901. + }
  24902. + } else {
  24903. + DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
  24904. + }
  24905. +
  24906. + if (ep->type == DWC_OTG_EP_TYPE_ISOC) {
  24907. + dsts_data_t dsts = {.d32 = 0};
  24908. + if (ep->bInterval == 1) {
  24909. + dsts.d32 =
  24910. + DWC_READ_REG32(&core_if->dev_if->
  24911. + dev_global_regs->dsts);
  24912. + ep->frame_num = dsts.b.soffn + ep->bInterval;
  24913. + if (ep->frame_num > 0x3FFF) {
  24914. + ep->frm_overrun = 1;
  24915. + ep->frame_num &= 0x3FFF;
  24916. + } else
  24917. + ep->frm_overrun = 0;
  24918. +
  24919. + if (ep->frame_num & 0x1) {
  24920. + depctl.b.setd1pid = 1;
  24921. + } else {
  24922. + depctl.b.setd0pid = 1;
  24923. + }
  24924. + }
  24925. + }
  24926. +
  24927. + /* EP enable */
  24928. + depctl.b.cnak = 1;
  24929. + depctl.b.epena = 1;
  24930. +
  24931. + DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
  24932. +
  24933. + DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n",
  24934. + DWC_READ_REG32(&out_regs->doepctl),
  24935. + DWC_READ_REG32(&out_regs->doeptsiz));
  24936. + DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n",
  24937. + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->
  24938. + daintmsk),
  24939. + DWC_READ_REG32(&core_if->core_global_regs->
  24940. + gintmsk));
  24941. +
  24942. + /* Timer is scheduling only for out bulk transfers for
  24943. + * "Device DDMA OUT NAK Enhancement" feature to inform user
  24944. + * about received data payload in case of timeout
  24945. + */
  24946. + if (core_if->core_params->dev_out_nak) {
  24947. + if (ep->type == DWC_OTG_EP_TYPE_BULK) {
  24948. + core_if->ep_xfer_info[ep->num].core_if = core_if;
  24949. + core_if->ep_xfer_info[ep->num].ep = ep;
  24950. + core_if->ep_xfer_info[ep->num].state = 1;
  24951. +
  24952. + /* Start a timer for this transfer. */
  24953. + DWC_TIMER_SCHEDULE(core_if->ep_xfer_timer[ep->num], 10000);
  24954. + }
  24955. + }
  24956. + }
  24957. +}
  24958. +
  24959. +/**
  24960. + * This function setup a zero length transfer in Buffer DMA and
  24961. + * Slave modes for usb requests with zero field set
  24962. + *
  24963. + * @param core_if Programming view of DWC_otg controller.
  24964. + * @param ep The EP to start the transfer on.
  24965. + *
  24966. + */
  24967. +void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
  24968. +{
  24969. +
  24970. + depctl_data_t depctl;
  24971. + deptsiz_data_t deptsiz;
  24972. + gintmsk_data_t intr_mask = {.d32 = 0 };
  24973. +
  24974. + DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__);
  24975. + DWC_PRINTF("zero length transfer is called\n");
  24976. +
  24977. + /* IN endpoint */
  24978. + if (ep->is_in == 1) {
  24979. + dwc_otg_dev_in_ep_regs_t *in_regs =
  24980. + core_if->dev_if->in_ep_regs[ep->num];
  24981. +
  24982. + depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl));
  24983. + deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz));
  24984. +
  24985. + deptsiz.b.xfersize = 0;
  24986. + deptsiz.b.pktcnt = 1;
  24987. +
  24988. + /* Write the DMA register */
  24989. + if (core_if->dma_enable) {
  24990. + if (core_if->dma_desc_enable == 0) {
  24991. + deptsiz.b.mc = 1;
  24992. + DWC_WRITE_REG32(&in_regs->dieptsiz,
  24993. + deptsiz.d32);
  24994. + DWC_WRITE_REG32(&(in_regs->diepdma),
  24995. + (uint32_t) ep->dma_addr);
  24996. + }
  24997. + } else {
  24998. + DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
  24999. + /**
  25000. + * Enable the Non-Periodic Tx FIFO empty interrupt,
  25001. + * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode,
  25002. + * the data will be written into the fifo by the ISR.
  25003. + */
  25004. + if (core_if->en_multiple_tx_fifo == 0) {
  25005. + intr_mask.b.nptxfempty = 1;
  25006. + DWC_MODIFY_REG32(&core_if->
  25007. + core_global_regs->gintmsk,
  25008. + intr_mask.d32, intr_mask.d32);
  25009. + } else {
  25010. + /* Enable the Tx FIFO Empty Interrupt for this EP */
  25011. + if (ep->xfer_len > 0) {
  25012. + uint32_t fifoemptymsk = 0;
  25013. + fifoemptymsk = 1 << ep->num;
  25014. + DWC_MODIFY_REG32(&core_if->
  25015. + dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
  25016. + 0, fifoemptymsk);
  25017. + }
  25018. + }
  25019. + }
  25020. +
  25021. + if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
  25022. + depctl.b.nextep = core_if->nextep_seq[ep->num];
  25023. + /* EP enable, IN data in FIFO */
  25024. + depctl.b.cnak = 1;
  25025. + depctl.b.epena = 1;
  25026. + DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
  25027. +
  25028. + } else {
  25029. + /* OUT endpoint */
  25030. + dwc_otg_dev_out_ep_regs_t *out_regs =
  25031. + core_if->dev_if->out_ep_regs[ep->num];
  25032. +
  25033. + depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl));
  25034. + deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz));
  25035. +
  25036. + /* Zero Length Packet */
  25037. + deptsiz.b.xfersize = ep->maxpacket;
  25038. + deptsiz.b.pktcnt = 1;
  25039. +
  25040. + if (core_if->dma_enable) {
  25041. + if (!core_if->dma_desc_enable) {
  25042. + DWC_WRITE_REG32(&out_regs->doeptsiz,
  25043. + deptsiz.d32);
  25044. +
  25045. + DWC_WRITE_REG32(&(out_regs->doepdma),
  25046. + (uint32_t) ep->dma_addr);
  25047. + }
  25048. + } else {
  25049. + DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
  25050. + }
  25051. +
  25052. + /* EP enable */
  25053. + depctl.b.cnak = 1;
  25054. + depctl.b.epena = 1;
  25055. +
  25056. + DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
  25057. +
  25058. + }
  25059. +}
  25060. +
  25061. +/**
  25062. + * This function does the setup for a data transfer for EP0 and starts
  25063. + * the transfer. For an IN transfer, the packets will be loaded into
  25064. + * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are
  25065. + * unloaded from the Rx FIFO in the ISR.
  25066. + *
  25067. + * @param core_if Programming view of DWC_otg controller.
  25068. + * @param ep The EP0 data.
  25069. + */
  25070. +void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
  25071. +{
  25072. + depctl_data_t depctl;
  25073. + deptsiz0_data_t deptsiz;
  25074. + gintmsk_data_t intr_mask = {.d32 = 0 };
  25075. + dwc_otg_dev_dma_desc_t *dma_desc;
  25076. +
  25077. + DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d "
  25078. + "xfer_buff=%p start_xfer_buff=%p \n",
  25079. + ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len,
  25080. + ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff);
  25081. +
  25082. + ep->total_len = ep->xfer_len;
  25083. +
  25084. + /* IN endpoint */
  25085. + if (ep->is_in == 1) {
  25086. + dwc_otg_dev_in_ep_regs_t *in_regs =
  25087. + core_if->dev_if->in_ep_regs[0];
  25088. +
  25089. + gnptxsts_data_t gtxstatus;
  25090. +
  25091. + if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
  25092. + depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
  25093. + if (depctl.b.epena)
  25094. + return;
  25095. + }
  25096. +
  25097. + gtxstatus.d32 =
  25098. + DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);
  25099. +
  25100. + /* If dedicated FIFO every time flush fifo before enable ep*/
  25101. + if (core_if->en_multiple_tx_fifo && core_if->snpsid >= OTG_CORE_REV_3_00a)
  25102. + dwc_otg_flush_tx_fifo(core_if, ep->tx_fifo_num);
  25103. +
  25104. + if (core_if->en_multiple_tx_fifo == 0
  25105. + && gtxstatus.b.nptxqspcavail == 0
  25106. + && !core_if->dma_enable) {
  25107. +#ifdef DEBUG
  25108. + deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
  25109. + DWC_DEBUGPL(DBG_PCD, "DIEPCTL0=%0x\n",
  25110. + DWC_READ_REG32(&in_regs->diepctl));
  25111. + DWC_DEBUGPL(DBG_PCD, "DIEPTSIZ0=%0x (sz=%d, pcnt=%d)\n",
  25112. + deptsiz.d32,
  25113. + deptsiz.b.xfersize, deptsiz.b.pktcnt);
  25114. + DWC_PRINTF("TX Queue or FIFO Full (0x%0x)\n",
  25115. + gtxstatus.d32);
  25116. +#endif
  25117. + return;
  25118. + }
  25119. +
  25120. + depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
  25121. + deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
  25122. +
  25123. + /* Zero Length Packet? */
  25124. + if (ep->xfer_len == 0) {
  25125. + deptsiz.b.xfersize = 0;
  25126. + deptsiz.b.pktcnt = 1;
  25127. + } else {
  25128. + /* Program the transfer size and packet count
  25129. + * as follows: xfersize = N * maxpacket +
  25130. + * short_packet pktcnt = N + (short_packet
  25131. + * exist ? 1 : 0)
  25132. + */
  25133. + if (ep->xfer_len > ep->maxpacket) {
  25134. + ep->xfer_len = ep->maxpacket;
  25135. + deptsiz.b.xfersize = ep->maxpacket;
  25136. + } else {
  25137. + deptsiz.b.xfersize = ep->xfer_len;
  25138. + }
  25139. + deptsiz.b.pktcnt = 1;
  25140. +
  25141. + }
  25142. + DWC_DEBUGPL(DBG_PCDV,
  25143. + "IN len=%d xfersize=%d pktcnt=%d [%08x]\n",
  25144. + ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
  25145. + deptsiz.d32);
  25146. +
  25147. + /* Write the DMA register */
  25148. + if (core_if->dma_enable) {
  25149. + if (core_if->dma_desc_enable == 0) {
  25150. + DWC_WRITE_REG32(&in_regs->dieptsiz,
  25151. + deptsiz.d32);
  25152. +
  25153. + DWC_WRITE_REG32(&(in_regs->diepdma),
  25154. + (uint32_t) ep->dma_addr);
  25155. + } else {
  25156. + dma_desc = core_if->dev_if->in_desc_addr;
  25157. +
  25158. + /** DMA Descriptor Setup */
  25159. + dma_desc->status.b.bs = BS_HOST_BUSY;
  25160. + dma_desc->status.b.l = 1;
  25161. + dma_desc->status.b.ioc = 1;
  25162. + dma_desc->status.b.sp =
  25163. + (ep->xfer_len == ep->maxpacket) ? 0 : 1;
  25164. + dma_desc->status.b.bytes = ep->xfer_len;
  25165. + dma_desc->buf = ep->dma_addr;
  25166. + dma_desc->status.b.sts = 0;
  25167. + dma_desc->status.b.bs = BS_HOST_READY;
  25168. +
  25169. + /** DIEPDMA0 Register write */
  25170. + DWC_WRITE_REG32(&in_regs->diepdma,
  25171. + core_if->
  25172. + dev_if->dma_in_desc_addr);
  25173. + }
  25174. + } else {
  25175. + DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
  25176. + }
  25177. +
  25178. + if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
  25179. + depctl.b.nextep = core_if->nextep_seq[ep->num];
  25180. + /* EP enable, IN data in FIFO */
  25181. + depctl.b.cnak = 1;
  25182. + depctl.b.epena = 1;
  25183. + DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
  25184. +
  25185. + /**
  25186. + * Enable the Non-Periodic Tx FIFO empty interrupt, the
  25187. + * data will be written into the fifo by the ISR.
  25188. + */
  25189. + if (!core_if->dma_enable) {
  25190. + if (core_if->en_multiple_tx_fifo == 0) {
  25191. + intr_mask.b.nptxfempty = 1;
  25192. + DWC_MODIFY_REG32(&core_if->
  25193. + core_global_regs->gintmsk,
  25194. + intr_mask.d32, intr_mask.d32);
  25195. + } else {
  25196. + /* Enable the Tx FIFO Empty Interrupt for this EP */
  25197. + if (ep->xfer_len > 0) {
  25198. + uint32_t fifoemptymsk = 0;
  25199. + fifoemptymsk |= 1 << ep->num;
  25200. + DWC_MODIFY_REG32(&core_if->
  25201. + dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
  25202. + 0, fifoemptymsk);
  25203. + }
  25204. + }
  25205. + }
  25206. + } else {
  25207. + /* OUT endpoint */
  25208. + dwc_otg_dev_out_ep_regs_t *out_regs =
  25209. + core_if->dev_if->out_ep_regs[0];
  25210. +
  25211. + depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);
  25212. + deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);
  25213. +
  25214. + /* Program the transfer size and packet count as follows:
  25215. + * xfersize = N * (maxpacket + 4 - (maxpacket % 4))
  25216. + * pktcnt = N */
  25217. + /* Zero Length Packet */
  25218. + deptsiz.b.xfersize = ep->maxpacket;
  25219. + deptsiz.b.pktcnt = 1;
  25220. + if (core_if->snpsid >= OTG_CORE_REV_3_00a)
  25221. + deptsiz.b.supcnt = 3;
  25222. +
  25223. + DWC_DEBUGPL(DBG_PCDV, "len=%d xfersize=%d pktcnt=%d\n",
  25224. + ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt);
  25225. +
  25226. + if (core_if->dma_enable) {
  25227. + if (!core_if->dma_desc_enable) {
  25228. + DWC_WRITE_REG32(&out_regs->doeptsiz,
  25229. + deptsiz.d32);
  25230. +
  25231. + DWC_WRITE_REG32(&(out_regs->doepdma),
  25232. + (uint32_t) ep->dma_addr);
  25233. + } else {
  25234. + dma_desc = core_if->dev_if->out_desc_addr;
  25235. +
  25236. + /** DMA Descriptor Setup */
  25237. + dma_desc->status.b.bs = BS_HOST_BUSY;
  25238. + if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
  25239. + dma_desc->status.b.mtrf = 0;
  25240. + dma_desc->status.b.sr = 0;
  25241. + }
  25242. + dma_desc->status.b.l = 1;
  25243. + dma_desc->status.b.ioc = 1;
  25244. + dma_desc->status.b.bytes = ep->maxpacket;
  25245. + dma_desc->buf = ep->dma_addr;
  25246. + dma_desc->status.b.sts = 0;
  25247. + dma_desc->status.b.bs = BS_HOST_READY;
  25248. +
  25249. + /** DOEPDMA0 Register write */
  25250. + DWC_WRITE_REG32(&out_regs->doepdma,
  25251. + core_if->dev_if->
  25252. + dma_out_desc_addr);
  25253. + }
  25254. + } else {
  25255. + DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
  25256. + }
  25257. +
  25258. + /* EP enable */
  25259. + depctl.b.cnak = 1;
  25260. + depctl.b.epena = 1;
  25261. + DWC_WRITE_REG32(&(out_regs->doepctl), depctl.d32);
  25262. + }
  25263. +}
  25264. +
  25265. +/**
  25266. + * This function continues control IN transfers started by
  25267. + * dwc_otg_ep0_start_transfer, when the transfer does not fit in a
  25268. + * single packet. NOTE: The DIEPCTL0/DOEPCTL0 registers only have one
  25269. + * bit for the packet count.
  25270. + *
  25271. + * @param core_if Programming view of DWC_otg controller.
  25272. + * @param ep The EP0 data.
  25273. + */
  25274. +void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
  25275. +{
  25276. + depctl_data_t depctl;
  25277. + deptsiz0_data_t deptsiz;
  25278. + gintmsk_data_t intr_mask = {.d32 = 0 };
  25279. + dwc_otg_dev_dma_desc_t *dma_desc;
  25280. +
  25281. + if (ep->is_in == 1) {
  25282. + dwc_otg_dev_in_ep_regs_t *in_regs =
  25283. + core_if->dev_if->in_ep_regs[0];
  25284. + gnptxsts_data_t tx_status = {.d32 = 0 };
  25285. +
  25286. + tx_status.d32 =
  25287. + DWC_READ_REG32(&core_if->core_global_regs->gnptxsts);
  25288. + /** @todo Should there be check for room in the Tx
  25289. + * Status Queue. If not remove the code above this comment. */
  25290. +
  25291. + depctl.d32 = DWC_READ_REG32(&in_regs->diepctl);
  25292. + deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz);
  25293. +
  25294. + /* Program the transfer size and packet count
  25295. + * as follows: xfersize = N * maxpacket +
  25296. + * short_packet pktcnt = N + (short_packet
  25297. + * exist ? 1 : 0)
  25298. + */
  25299. +
  25300. + if (core_if->dma_desc_enable == 0) {
  25301. + deptsiz.b.xfersize =
  25302. + (ep->total_len - ep->xfer_count) >
  25303. + ep->maxpacket ? ep->maxpacket : (ep->total_len -
  25304. + ep->xfer_count);
  25305. + deptsiz.b.pktcnt = 1;
  25306. + if (core_if->dma_enable == 0) {
  25307. + ep->xfer_len += deptsiz.b.xfersize;
  25308. + } else {
  25309. + ep->xfer_len = deptsiz.b.xfersize;
  25310. + }
  25311. + DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32);
  25312. + } else {
  25313. + ep->xfer_len =
  25314. + (ep->total_len - ep->xfer_count) >
  25315. + ep->maxpacket ? ep->maxpacket : (ep->total_len -
  25316. + ep->xfer_count);
  25317. +
  25318. + dma_desc = core_if->dev_if->in_desc_addr;
  25319. +
  25320. + /** DMA Descriptor Setup */
  25321. + dma_desc->status.b.bs = BS_HOST_BUSY;
  25322. + dma_desc->status.b.l = 1;
  25323. + dma_desc->status.b.ioc = 1;
  25324. + dma_desc->status.b.sp =
  25325. + (ep->xfer_len == ep->maxpacket) ? 0 : 1;
  25326. + dma_desc->status.b.bytes = ep->xfer_len;
  25327. + dma_desc->buf = ep->dma_addr;
  25328. + dma_desc->status.b.sts = 0;
  25329. + dma_desc->status.b.bs = BS_HOST_READY;
  25330. +
  25331. + /** DIEPDMA0 Register write */
  25332. + DWC_WRITE_REG32(&in_regs->diepdma,
  25333. + core_if->dev_if->dma_in_desc_addr);
  25334. + }
  25335. +
  25336. + DWC_DEBUGPL(DBG_PCDV,
  25337. + "IN len=%d xfersize=%d pktcnt=%d [%08x]\n",
  25338. + ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
  25339. + deptsiz.d32);
  25340. +
  25341. + /* Write the DMA register */
  25342. + if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) {
  25343. + if (core_if->dma_desc_enable == 0)
  25344. + DWC_WRITE_REG32(&(in_regs->diepdma),
  25345. + (uint32_t) ep->dma_addr);
  25346. + }
  25347. + if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable)
  25348. + depctl.b.nextep = core_if->nextep_seq[ep->num];
  25349. + /* EP enable, IN data in FIFO */
  25350. + depctl.b.cnak = 1;
  25351. + depctl.b.epena = 1;
  25352. + DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32);
  25353. +
  25354. + /**
  25355. + * Enable the Non-Periodic Tx FIFO empty interrupt, the
  25356. + * data will be written into the fifo by the ISR.
  25357. + */
  25358. + if (!core_if->dma_enable) {
  25359. + if (core_if->en_multiple_tx_fifo == 0) {
  25360. + /* First clear it from GINTSTS */
  25361. + intr_mask.b.nptxfempty = 1;
  25362. + DWC_MODIFY_REG32(&core_if->
  25363. + core_global_regs->gintmsk,
  25364. + intr_mask.d32, intr_mask.d32);
  25365. +
  25366. + } else {
  25367. + /* Enable the Tx FIFO Empty Interrupt for this EP */
  25368. + if (ep->xfer_len > 0) {
  25369. + uint32_t fifoemptymsk = 0;
  25370. + fifoemptymsk |= 1 << ep->num;
  25371. + DWC_MODIFY_REG32(&core_if->
  25372. + dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
  25373. + 0, fifoemptymsk);
  25374. + }
  25375. + }
  25376. + }
  25377. + } else {
  25378. + dwc_otg_dev_out_ep_regs_t *out_regs =
  25379. + core_if->dev_if->out_ep_regs[0];
  25380. +
  25381. + depctl.d32 = DWC_READ_REG32(&out_regs->doepctl);
  25382. + deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz);
  25383. +
  25384. + /* Program the transfer size and packet count
  25385. + * as follows: xfersize = N * maxpacket +
  25386. + * short_packet pktcnt = N + (short_packet
  25387. + * exist ? 1 : 0)
  25388. + */
  25389. + deptsiz.b.xfersize = ep->maxpacket;
  25390. + deptsiz.b.pktcnt = 1;
  25391. +
  25392. + if (core_if->dma_desc_enable == 0) {
  25393. + DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32);
  25394. + } else {
  25395. + dma_desc = core_if->dev_if->out_desc_addr;
  25396. +
  25397. + /** DMA Descriptor Setup */
  25398. + dma_desc->status.b.bs = BS_HOST_BUSY;
  25399. + dma_desc->status.b.l = 1;
  25400. + dma_desc->status.b.ioc = 1;
  25401. + dma_desc->status.b.bytes = ep->maxpacket;
  25402. + dma_desc->buf = ep->dma_addr;
  25403. + dma_desc->status.b.sts = 0;
  25404. + dma_desc->status.b.bs = BS_HOST_READY;
  25405. +
  25406. + /** DOEPDMA0 Register write */
  25407. + DWC_WRITE_REG32(&out_regs->doepdma,
  25408. + core_if->dev_if->dma_out_desc_addr);
  25409. + }
  25410. +
  25411. + DWC_DEBUGPL(DBG_PCDV,
  25412. + "IN len=%d xfersize=%d pktcnt=%d [%08x]\n",
  25413. + ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt,
  25414. + deptsiz.d32);
  25415. +
  25416. + /* Write the DMA register */
  25417. + if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) {
  25418. + if (core_if->dma_desc_enable == 0)
  25419. + DWC_WRITE_REG32(&(out_regs->doepdma),
  25420. + (uint32_t) ep->dma_addr);
  25421. +
  25422. + }
  25423. +
  25424. + /* EP enable, IN data in FIFO */
  25425. + depctl.b.cnak = 1;
  25426. + depctl.b.epena = 1;
  25427. + DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32);
  25428. +
  25429. + }
  25430. +}
  25431. +
  25432. +#ifdef DEBUG
  25433. +void dump_msg(const u8 * buf, unsigned int length)
  25434. +{
  25435. + unsigned int start, num, i;
  25436. + char line[52], *p;
  25437. +
  25438. + if (length >= 512)
  25439. + return;
  25440. + start = 0;
  25441. + while (length > 0) {
  25442. + num = length < 16u ? length : 16u;
  25443. + p = line;
  25444. + for (i = 0; i < num; ++i) {
  25445. + if (i == 8)
  25446. + *p++ = ' ';
  25447. + DWC_SPRINTF(p, " %02x", buf[i]);
  25448. + p += 3;
  25449. + }
  25450. + *p = 0;
  25451. + DWC_PRINTF("%6x: %s\n", start, line);
  25452. + buf += num;
  25453. + start += num;
  25454. + length -= num;
  25455. + }
  25456. +}
  25457. +#else
  25458. +static inline void dump_msg(const u8 * buf, unsigned int length)
  25459. +{
  25460. +}
  25461. +#endif
  25462. +
  25463. +/**
  25464. + * This function writes a packet into the Tx FIFO associated with the
  25465. + * EP. For non-periodic EPs the non-periodic Tx FIFO is written. For
  25466. + * periodic EPs the periodic Tx FIFO associated with the EP is written
  25467. + * with all packets for the next micro-frame.
  25468. + *
  25469. + * @param core_if Programming view of DWC_otg controller.
  25470. + * @param ep The EP to write packet for.
  25471. + * @param dma Indicates if DMA is being used.
  25472. + */
  25473. +void dwc_otg_ep_write_packet(dwc_otg_core_if_t * core_if, dwc_ep_t * ep,
  25474. + int dma)
  25475. +{
  25476. + /**
  25477. + * The buffer is padded to DWORD on a per packet basis in
  25478. + * slave/dma mode if the MPS is not DWORD aligned. The last
  25479. + * packet, if short, is also padded to a multiple of DWORD.
  25480. + *
  25481. + * ep->xfer_buff always starts DWORD aligned in memory and is a
  25482. + * multiple of DWORD in length
  25483. + *
  25484. + * ep->xfer_len can be any number of bytes
  25485. + *
  25486. + * ep->xfer_count is a multiple of ep->maxpacket until the last
  25487. + * packet
  25488. + *
  25489. + * FIFO access is DWORD */
  25490. +
  25491. + uint32_t i;
  25492. + uint32_t byte_count;
  25493. + uint32_t dword_count;
  25494. + uint32_t *fifo;
  25495. + uint32_t *data_buff = (uint32_t *) ep->xfer_buff;
  25496. +
  25497. + DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p)\n", __func__, core_if,
  25498. + ep);
  25499. + if (ep->xfer_count >= ep->xfer_len) {
  25500. + DWC_WARN("%s() No data for EP%d!!!\n", __func__, ep->num);
  25501. + return;
  25502. + }
  25503. +
  25504. + /* Find the byte length of the packet either short packet or MPS */
  25505. + if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket) {
  25506. + byte_count = ep->xfer_len - ep->xfer_count;
  25507. + } else {
  25508. + byte_count = ep->maxpacket;
  25509. + }
  25510. +
  25511. + /* Find the DWORD length, padded by extra bytes as neccessary if MPS
  25512. + * is not a multiple of DWORD */
  25513. + dword_count = (byte_count + 3) / 4;
  25514. +
  25515. +#ifdef VERBOSE
  25516. + dump_msg(ep->xfer_buff, byte_count);
  25517. +#endif
  25518. +
  25519. + /**@todo NGS Where are the Periodic Tx FIFO addresses
  25520. + * intialized? What should this be? */
  25521. +
  25522. + fifo = core_if->data_fifo[ep->num];
  25523. +
  25524. + DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "fifo=%p buff=%p *p=%08x bc=%d\n",
  25525. + fifo, data_buff, *data_buff, byte_count);
  25526. +
  25527. + if (!dma) {
  25528. + for (i = 0; i < dword_count; i++, data_buff++) {
  25529. + DWC_WRITE_REG32(fifo, *data_buff);
  25530. + }
  25531. + }
  25532. +
  25533. + ep->xfer_count += byte_count;
  25534. + ep->xfer_buff += byte_count;
  25535. + ep->dma_addr += byte_count;
  25536. +}
  25537. +
  25538. +/**
  25539. + * Set the EP STALL.
  25540. + *
  25541. + * @param core_if Programming view of DWC_otg controller.
  25542. + * @param ep The EP to set the stall on.
  25543. + */
  25544. +void dwc_otg_ep_set_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
  25545. +{
  25546. + depctl_data_t depctl;
  25547. + volatile uint32_t *depctl_addr;
  25548. +
  25549. + DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num,
  25550. + (ep->is_in ? "IN" : "OUT"));
  25551. +
  25552. + if (ep->is_in == 1) {
  25553. + depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
  25554. + depctl.d32 = DWC_READ_REG32(depctl_addr);
  25555. +
  25556. + /* set the disable and stall bits */
  25557. + if (depctl.b.epena) {
  25558. + depctl.b.epdis = 1;
  25559. + }
  25560. + depctl.b.stall = 1;
  25561. + DWC_WRITE_REG32(depctl_addr, depctl.d32);
  25562. + } else {
  25563. + depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
  25564. + depctl.d32 = DWC_READ_REG32(depctl_addr);
  25565. +
  25566. + /* set the stall bit */
  25567. + depctl.b.stall = 1;
  25568. + DWC_WRITE_REG32(depctl_addr, depctl.d32);
  25569. + }
  25570. +
  25571. + DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr));
  25572. +
  25573. + return;
  25574. +}
  25575. +
  25576. +/**
  25577. + * Clear the EP STALL.
  25578. + *
  25579. + * @param core_if Programming view of DWC_otg controller.
  25580. + * @param ep The EP to clear stall from.
  25581. + */
  25582. +void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
  25583. +{
  25584. + depctl_data_t depctl;
  25585. + volatile uint32_t *depctl_addr;
  25586. +
  25587. + DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num,
  25588. + (ep->is_in ? "IN" : "OUT"));
  25589. +
  25590. + if (ep->is_in == 1) {
  25591. + depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl);
  25592. + } else {
  25593. + depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl);
  25594. + }
  25595. +
  25596. + depctl.d32 = DWC_READ_REG32(depctl_addr);
  25597. +
  25598. + /* clear the stall bits */
  25599. + depctl.b.stall = 0;
  25600. +
  25601. + /*
  25602. + * USB Spec 9.4.5: For endpoints using data toggle, regardless
  25603. + * of whether an endpoint has the Halt feature set, a
  25604. + * ClearFeature(ENDPOINT_HALT) request always results in the
  25605. + * data toggle being reinitialized to DATA0.
  25606. + */
  25607. + if (ep->type == DWC_OTG_EP_TYPE_INTR ||
  25608. + ep->type == DWC_OTG_EP_TYPE_BULK) {
  25609. + depctl.b.setd0pid = 1; /* DATA0 */
  25610. + }
  25611. +
  25612. + DWC_WRITE_REG32(depctl_addr, depctl.d32);
  25613. + DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr));
  25614. + return;
  25615. +}
  25616. +
  25617. +/**
  25618. + * This function reads a packet from the Rx FIFO into the destination
  25619. + * buffer. To read SETUP data use dwc_otg_read_setup_packet.
  25620. + *
  25621. + * @param core_if Programming view of DWC_otg controller.
  25622. + * @param dest Destination buffer for the packet.
  25623. + * @param bytes Number of bytes to copy to the destination.
  25624. + */
  25625. +void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,
  25626. + uint8_t * dest, uint16_t bytes)
  25627. +{
  25628. + int i;
  25629. + int word_count = (bytes + 3) / 4;
  25630. +
  25631. + volatile uint32_t *fifo = core_if->data_fifo[0];
  25632. + uint32_t *data_buff = (uint32_t *) dest;
  25633. +
  25634. + /**
  25635. + * @todo Account for the case where _dest is not dword aligned. This
  25636. + * requires reading data from the FIFO into a uint32_t temp buffer,
  25637. + * then moving it into the data buffer.
  25638. + */
  25639. +
  25640. + DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p,%d)\n", __func__,
  25641. + core_if, dest, bytes);
  25642. +
  25643. + for (i = 0; i < word_count; i++, data_buff++) {
  25644. + *data_buff = DWC_READ_REG32(fifo);
  25645. + }
  25646. +
  25647. + return;
  25648. +}
  25649. +
  25650. +/**
  25651. + * This functions reads the device registers and prints them
  25652. + *
  25653. + * @param core_if Programming view of DWC_otg controller.
  25654. + */
  25655. +void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * core_if)
  25656. +{
  25657. + int i;
  25658. + volatile uint32_t *addr;
  25659. +
  25660. + DWC_PRINTF("Device Global Registers\n");
  25661. + addr = &core_if->dev_if->dev_global_regs->dcfg;
  25662. + DWC_PRINTF("DCFG @0x%08lX : 0x%08X\n",
  25663. + (unsigned long)addr, DWC_READ_REG32(addr));
  25664. + addr = &core_if->dev_if->dev_global_regs->dctl;
  25665. + DWC_PRINTF("DCTL @0x%08lX : 0x%08X\n",
  25666. + (unsigned long)addr, DWC_READ_REG32(addr));
  25667. + addr = &core_if->dev_if->dev_global_regs->dsts;
  25668. + DWC_PRINTF("DSTS @0x%08lX : 0x%08X\n",
  25669. + (unsigned long)addr, DWC_READ_REG32(addr));
  25670. + addr = &core_if->dev_if->dev_global_regs->diepmsk;
  25671. + DWC_PRINTF("DIEPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25672. + DWC_READ_REG32(addr));
  25673. + addr = &core_if->dev_if->dev_global_regs->doepmsk;
  25674. + DWC_PRINTF("DOEPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25675. + DWC_READ_REG32(addr));
  25676. + addr = &core_if->dev_if->dev_global_regs->daint;
  25677. + DWC_PRINTF("DAINT @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25678. + DWC_READ_REG32(addr));
  25679. + addr = &core_if->dev_if->dev_global_regs->daintmsk;
  25680. + DWC_PRINTF("DAINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25681. + DWC_READ_REG32(addr));
  25682. + addr = &core_if->dev_if->dev_global_regs->dtknqr1;
  25683. + DWC_PRINTF("DTKNQR1 @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25684. + DWC_READ_REG32(addr));
  25685. + if (core_if->hwcfg2.b.dev_token_q_depth > 6) {
  25686. + addr = &core_if->dev_if->dev_global_regs->dtknqr2;
  25687. + DWC_PRINTF("DTKNQR2 @0x%08lX : 0x%08X\n",
  25688. + (unsigned long)addr, DWC_READ_REG32(addr));
  25689. + }
  25690. +
  25691. + addr = &core_if->dev_if->dev_global_regs->dvbusdis;
  25692. + DWC_PRINTF("DVBUSID @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25693. + DWC_READ_REG32(addr));
  25694. +
  25695. + addr = &core_if->dev_if->dev_global_regs->dvbuspulse;
  25696. + DWC_PRINTF("DVBUSPULSE @0x%08lX : 0x%08X\n",
  25697. + (unsigned long)addr, DWC_READ_REG32(addr));
  25698. +
  25699. + addr = &core_if->dev_if->dev_global_regs->dtknqr3_dthrctl;
  25700. + DWC_PRINTF("DTKNQR3_DTHRCTL @0x%08lX : 0x%08X\n",
  25701. + (unsigned long)addr, DWC_READ_REG32(addr));
  25702. +
  25703. + if (core_if->hwcfg2.b.dev_token_q_depth > 22) {
  25704. + addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk;
  25705. + DWC_PRINTF("DTKNQR4 @0x%08lX : 0x%08X\n",
  25706. + (unsigned long)addr, DWC_READ_REG32(addr));
  25707. + }
  25708. +
  25709. + addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk;
  25710. + DWC_PRINTF("FIFOEMPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25711. + DWC_READ_REG32(addr));
  25712. +
  25713. + if (core_if->hwcfg2.b.multi_proc_int) {
  25714. +
  25715. + addr = &core_if->dev_if->dev_global_regs->deachint;
  25716. + DWC_PRINTF("DEACHINT @0x%08lX : 0x%08X\n",
  25717. + (unsigned long)addr, DWC_READ_REG32(addr));
  25718. + addr = &core_if->dev_if->dev_global_regs->deachintmsk;
  25719. + DWC_PRINTF("DEACHINTMSK @0x%08lX : 0x%08X\n",
  25720. + (unsigned long)addr, DWC_READ_REG32(addr));
  25721. +
  25722. + for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
  25723. + addr =
  25724. + &core_if->dev_if->
  25725. + dev_global_regs->diepeachintmsk[i];
  25726. + DWC_PRINTF("DIEPEACHINTMSK[%d] @0x%08lX : 0x%08X\n",
  25727. + i, (unsigned long)addr,
  25728. + DWC_READ_REG32(addr));
  25729. + }
  25730. +
  25731. + for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
  25732. + addr =
  25733. + &core_if->dev_if->
  25734. + dev_global_regs->doepeachintmsk[i];
  25735. + DWC_PRINTF("DOEPEACHINTMSK[%d] @0x%08lX : 0x%08X\n",
  25736. + i, (unsigned long)addr,
  25737. + DWC_READ_REG32(addr));
  25738. + }
  25739. + }
  25740. +
  25741. + for (i = 0; i <= core_if->dev_if->num_in_eps; i++) {
  25742. + DWC_PRINTF("Device IN EP %d Registers\n", i);
  25743. + addr = &core_if->dev_if->in_ep_regs[i]->diepctl;
  25744. + DWC_PRINTF("DIEPCTL @0x%08lX : 0x%08X\n",
  25745. + (unsigned long)addr, DWC_READ_REG32(addr));
  25746. + addr = &core_if->dev_if->in_ep_regs[i]->diepint;
  25747. + DWC_PRINTF("DIEPINT @0x%08lX : 0x%08X\n",
  25748. + (unsigned long)addr, DWC_READ_REG32(addr));
  25749. + addr = &core_if->dev_if->in_ep_regs[i]->dieptsiz;
  25750. + DWC_PRINTF("DIETSIZ @0x%08lX : 0x%08X\n",
  25751. + (unsigned long)addr, DWC_READ_REG32(addr));
  25752. + addr = &core_if->dev_if->in_ep_regs[i]->diepdma;
  25753. + DWC_PRINTF("DIEPDMA @0x%08lX : 0x%08X\n",
  25754. + (unsigned long)addr, DWC_READ_REG32(addr));
  25755. + addr = &core_if->dev_if->in_ep_regs[i]->dtxfsts;
  25756. + DWC_PRINTF("DTXFSTS @0x%08lX : 0x%08X\n",
  25757. + (unsigned long)addr, DWC_READ_REG32(addr));
  25758. + addr = &core_if->dev_if->in_ep_regs[i]->diepdmab;
  25759. + DWC_PRINTF("DIEPDMAB @0x%08lX : 0x%08X\n",
  25760. + (unsigned long)addr, 0 /*DWC_READ_REG32(addr) */ );
  25761. + }
  25762. +
  25763. + for (i = 0; i <= core_if->dev_if->num_out_eps; i++) {
  25764. + DWC_PRINTF("Device OUT EP %d Registers\n", i);
  25765. + addr = &core_if->dev_if->out_ep_regs[i]->doepctl;
  25766. + DWC_PRINTF("DOEPCTL @0x%08lX : 0x%08X\n",
  25767. + (unsigned long)addr, DWC_READ_REG32(addr));
  25768. + addr = &core_if->dev_if->out_ep_regs[i]->doepint;
  25769. + DWC_PRINTF("DOEPINT @0x%08lX : 0x%08X\n",
  25770. + (unsigned long)addr, DWC_READ_REG32(addr));
  25771. + addr = &core_if->dev_if->out_ep_regs[i]->doeptsiz;
  25772. + DWC_PRINTF("DOETSIZ @0x%08lX : 0x%08X\n",
  25773. + (unsigned long)addr, DWC_READ_REG32(addr));
  25774. + addr = &core_if->dev_if->out_ep_regs[i]->doepdma;
  25775. + DWC_PRINTF("DOEPDMA @0x%08lX : 0x%08X\n",
  25776. + (unsigned long)addr, DWC_READ_REG32(addr));
  25777. + if (core_if->dma_enable) { /* Don't access this register in SLAVE mode */
  25778. + addr = &core_if->dev_if->out_ep_regs[i]->doepdmab;
  25779. + DWC_PRINTF("DOEPDMAB @0x%08lX : 0x%08X\n",
  25780. + (unsigned long)addr, DWC_READ_REG32(addr));
  25781. + }
  25782. +
  25783. + }
  25784. +}
  25785. +
  25786. +/**
  25787. + * This functions reads the SPRAM and prints its content
  25788. + *
  25789. + * @param core_if Programming view of DWC_otg controller.
  25790. + */
  25791. +void dwc_otg_dump_spram(dwc_otg_core_if_t * core_if)
  25792. +{
  25793. + volatile uint8_t *addr, *start_addr, *end_addr;
  25794. +
  25795. + DWC_PRINTF("SPRAM Data:\n");
  25796. + start_addr = (void *)core_if->core_global_regs;
  25797. + DWC_PRINTF("Base Address: 0x%8lX\n", (unsigned long)start_addr);
  25798. + start_addr += 0x00028000;
  25799. + end_addr = (void *)core_if->core_global_regs;
  25800. + end_addr += 0x000280e0;
  25801. +
  25802. + for (addr = start_addr; addr < end_addr; addr += 16) {
  25803. + DWC_PRINTF
  25804. + ("0x%8lX:\t%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\n",
  25805. + (unsigned long)addr, addr[0], addr[1], addr[2], addr[3],
  25806. + addr[4], addr[5], addr[6], addr[7], addr[8], addr[9],
  25807. + addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]
  25808. + );
  25809. + }
  25810. +
  25811. + return;
  25812. +}
  25813. +
  25814. +/**
  25815. + * This function reads the host registers and prints them
  25816. + *
  25817. + * @param core_if Programming view of DWC_otg controller.
  25818. + */
  25819. +void dwc_otg_dump_host_registers(dwc_otg_core_if_t * core_if)
  25820. +{
  25821. + int i;
  25822. + volatile uint32_t *addr;
  25823. +
  25824. + DWC_PRINTF("Host Global Registers\n");
  25825. + addr = &core_if->host_if->host_global_regs->hcfg;
  25826. + DWC_PRINTF("HCFG @0x%08lX : 0x%08X\n",
  25827. + (unsigned long)addr, DWC_READ_REG32(addr));
  25828. + addr = &core_if->host_if->host_global_regs->hfir;
  25829. + DWC_PRINTF("HFIR @0x%08lX : 0x%08X\n",
  25830. + (unsigned long)addr, DWC_READ_REG32(addr));
  25831. + addr = &core_if->host_if->host_global_regs->hfnum;
  25832. + DWC_PRINTF("HFNUM @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25833. + DWC_READ_REG32(addr));
  25834. + addr = &core_if->host_if->host_global_regs->hptxsts;
  25835. + DWC_PRINTF("HPTXSTS @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25836. + DWC_READ_REG32(addr));
  25837. + addr = &core_if->host_if->host_global_regs->haint;
  25838. + DWC_PRINTF("HAINT @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25839. + DWC_READ_REG32(addr));
  25840. + addr = &core_if->host_if->host_global_regs->haintmsk;
  25841. + DWC_PRINTF("HAINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25842. + DWC_READ_REG32(addr));
  25843. + if (core_if->dma_desc_enable) {
  25844. + addr = &core_if->host_if->host_global_regs->hflbaddr;
  25845. + DWC_PRINTF("HFLBADDR @0x%08lX : 0x%08X\n",
  25846. + (unsigned long)addr, DWC_READ_REG32(addr));
  25847. + }
  25848. +
  25849. + addr = core_if->host_if->hprt0;
  25850. + DWC_PRINTF("HPRT0 @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25851. + DWC_READ_REG32(addr));
  25852. +
  25853. + for (i = 0; i < core_if->core_params->host_channels; i++) {
  25854. + DWC_PRINTF("Host Channel %d Specific Registers\n", i);
  25855. + addr = &core_if->host_if->hc_regs[i]->hcchar;
  25856. + DWC_PRINTF("HCCHAR @0x%08lX : 0x%08X\n",
  25857. + (unsigned long)addr, DWC_READ_REG32(addr));
  25858. + addr = &core_if->host_if->hc_regs[i]->hcsplt;
  25859. + DWC_PRINTF("HCSPLT @0x%08lX : 0x%08X\n",
  25860. + (unsigned long)addr, DWC_READ_REG32(addr));
  25861. + addr = &core_if->host_if->hc_regs[i]->hcint;
  25862. + DWC_PRINTF("HCINT @0x%08lX : 0x%08X\n",
  25863. + (unsigned long)addr, DWC_READ_REG32(addr));
  25864. + addr = &core_if->host_if->hc_regs[i]->hcintmsk;
  25865. + DWC_PRINTF("HCINTMSK @0x%08lX : 0x%08X\n",
  25866. + (unsigned long)addr, DWC_READ_REG32(addr));
  25867. + addr = &core_if->host_if->hc_regs[i]->hctsiz;
  25868. + DWC_PRINTF("HCTSIZ @0x%08lX : 0x%08X\n",
  25869. + (unsigned long)addr, DWC_READ_REG32(addr));
  25870. + addr = &core_if->host_if->hc_regs[i]->hcdma;
  25871. + DWC_PRINTF("HCDMA @0x%08lX : 0x%08X\n",
  25872. + (unsigned long)addr, DWC_READ_REG32(addr));
  25873. + if (core_if->dma_desc_enable) {
  25874. + addr = &core_if->host_if->hc_regs[i]->hcdmab;
  25875. + DWC_PRINTF("HCDMAB @0x%08lX : 0x%08X\n",
  25876. + (unsigned long)addr, DWC_READ_REG32(addr));
  25877. + }
  25878. +
  25879. + }
  25880. + return;
  25881. +}
  25882. +
  25883. +/**
  25884. + * This function reads the core global registers and prints them
  25885. + *
  25886. + * @param core_if Programming view of DWC_otg controller.
  25887. + */
  25888. +void dwc_otg_dump_global_registers(dwc_otg_core_if_t * core_if)
  25889. +{
  25890. + int i, ep_num;
  25891. + volatile uint32_t *addr;
  25892. + char *txfsiz;
  25893. +
  25894. + DWC_PRINTF("Core Global Registers\n");
  25895. + addr = &core_if->core_global_regs->gotgctl;
  25896. + DWC_PRINTF("GOTGCTL @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25897. + DWC_READ_REG32(addr));
  25898. + addr = &core_if->core_global_regs->gotgint;
  25899. + DWC_PRINTF("GOTGINT @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25900. + DWC_READ_REG32(addr));
  25901. + addr = &core_if->core_global_regs->gahbcfg;
  25902. + DWC_PRINTF("GAHBCFG @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25903. + DWC_READ_REG32(addr));
  25904. + addr = &core_if->core_global_regs->gusbcfg;
  25905. + DWC_PRINTF("GUSBCFG @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25906. + DWC_READ_REG32(addr));
  25907. + addr = &core_if->core_global_regs->grstctl;
  25908. + DWC_PRINTF("GRSTCTL @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25909. + DWC_READ_REG32(addr));
  25910. + addr = &core_if->core_global_regs->gintsts;
  25911. + DWC_PRINTF("GINTSTS @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25912. + DWC_READ_REG32(addr));
  25913. + addr = &core_if->core_global_regs->gintmsk;
  25914. + DWC_PRINTF("GINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25915. + DWC_READ_REG32(addr));
  25916. + addr = &core_if->core_global_regs->grxstsr;
  25917. + DWC_PRINTF("GRXSTSR @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25918. + DWC_READ_REG32(addr));
  25919. + addr = &core_if->core_global_regs->grxfsiz;
  25920. + DWC_PRINTF("GRXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25921. + DWC_READ_REG32(addr));
  25922. + addr = &core_if->core_global_regs->gnptxfsiz;
  25923. + DWC_PRINTF("GNPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25924. + DWC_READ_REG32(addr));
  25925. + addr = &core_if->core_global_regs->gnptxsts;
  25926. + DWC_PRINTF("GNPTXSTS @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25927. + DWC_READ_REG32(addr));
  25928. + addr = &core_if->core_global_regs->gi2cctl;
  25929. + DWC_PRINTF("GI2CCTL @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25930. + DWC_READ_REG32(addr));
  25931. + addr = &core_if->core_global_regs->gpvndctl;
  25932. + DWC_PRINTF("GPVNDCTL @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25933. + DWC_READ_REG32(addr));
  25934. + addr = &core_if->core_global_regs->ggpio;
  25935. + DWC_PRINTF("GGPIO @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25936. + DWC_READ_REG32(addr));
  25937. + addr = &core_if->core_global_regs->guid;
  25938. + DWC_PRINTF("GUID @0x%08lX : 0x%08X\n",
  25939. + (unsigned long)addr, DWC_READ_REG32(addr));
  25940. + addr = &core_if->core_global_regs->gsnpsid;
  25941. + DWC_PRINTF("GSNPSID @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25942. + DWC_READ_REG32(addr));
  25943. + addr = &core_if->core_global_regs->ghwcfg1;
  25944. + DWC_PRINTF("GHWCFG1 @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25945. + DWC_READ_REG32(addr));
  25946. + addr = &core_if->core_global_regs->ghwcfg2;
  25947. + DWC_PRINTF("GHWCFG2 @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25948. + DWC_READ_REG32(addr));
  25949. + addr = &core_if->core_global_regs->ghwcfg3;
  25950. + DWC_PRINTF("GHWCFG3 @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25951. + DWC_READ_REG32(addr));
  25952. + addr = &core_if->core_global_regs->ghwcfg4;
  25953. + DWC_PRINTF("GHWCFG4 @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25954. + DWC_READ_REG32(addr));
  25955. + addr = &core_if->core_global_regs->glpmcfg;
  25956. + DWC_PRINTF("GLPMCFG @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25957. + DWC_READ_REG32(addr));
  25958. + addr = &core_if->core_global_regs->gpwrdn;
  25959. + DWC_PRINTF("GPWRDN @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25960. + DWC_READ_REG32(addr));
  25961. + addr = &core_if->core_global_regs->gdfifocfg;
  25962. + DWC_PRINTF("GDFIFOCFG @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25963. + DWC_READ_REG32(addr));
  25964. + addr = &core_if->core_global_regs->adpctl;
  25965. + DWC_PRINTF("ADPCTL @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25966. + dwc_otg_adp_read_reg(core_if));
  25967. + addr = &core_if->core_global_regs->hptxfsiz;
  25968. + DWC_PRINTF("HPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25969. + DWC_READ_REG32(addr));
  25970. +
  25971. + if (core_if->en_multiple_tx_fifo == 0) {
  25972. + ep_num = core_if->hwcfg4.b.num_dev_perio_in_ep;
  25973. + txfsiz = "DPTXFSIZ";
  25974. + } else {
  25975. + ep_num = core_if->hwcfg4.b.num_in_eps;
  25976. + txfsiz = "DIENPTXF";
  25977. + }
  25978. + for (i = 0; i < ep_num; i++) {
  25979. + addr = &core_if->core_global_regs->dtxfsiz[i];
  25980. + DWC_PRINTF("%s[%d] @0x%08lX : 0x%08X\n", txfsiz, i + 1,
  25981. + (unsigned long)addr, DWC_READ_REG32(addr));
  25982. + }
  25983. + addr = core_if->pcgcctl;
  25984. + DWC_PRINTF("PCGCCTL @0x%08lX : 0x%08X\n", (unsigned long)addr,
  25985. + DWC_READ_REG32(addr));
  25986. +}
  25987. +
  25988. +/**
  25989. + * Flush a Tx FIFO.
  25990. + *
  25991. + * @param core_if Programming view of DWC_otg controller.
  25992. + * @param num Tx FIFO to flush.
  25993. + */
  25994. +void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * core_if, const int num)
  25995. +{
  25996. + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
  25997. + volatile grstctl_t greset = {.d32 = 0 };
  25998. + int count = 0;
  25999. +
  26000. + DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "Flush Tx FIFO %d\n", num);
  26001. +
  26002. + greset.b.txfflsh = 1;
  26003. + greset.b.txfnum = num;
  26004. + DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
  26005. +
  26006. + do {
  26007. + greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
  26008. + if (++count > 10000) {
  26009. + DWC_WARN("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n",
  26010. + __func__, greset.d32,
  26011. + DWC_READ_REG32(&global_regs->gnptxsts));
  26012. + break;
  26013. + }
  26014. + dwc_udelay(1);
  26015. + } while (greset.b.txfflsh == 1);
  26016. +
  26017. + /* Wait for 3 PHY Clocks */
  26018. + dwc_udelay(1);
  26019. +}
  26020. +
  26021. +/**
  26022. + * Flush Rx FIFO.
  26023. + *
  26024. + * @param core_if Programming view of DWC_otg controller.
  26025. + */
  26026. +void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * core_if)
  26027. +{
  26028. + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
  26029. + volatile grstctl_t greset = {.d32 = 0 };
  26030. + int count = 0;
  26031. +
  26032. + DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "%s\n", __func__);
  26033. + /*
  26034. + *
  26035. + */
  26036. + greset.b.rxfflsh = 1;
  26037. + DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
  26038. +
  26039. + do {
  26040. + greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
  26041. + if (++count > 10000) {
  26042. + DWC_WARN("%s() HANG! GRSTCTL=%0x\n", __func__,
  26043. + greset.d32);
  26044. + break;
  26045. + }
  26046. + dwc_udelay(1);
  26047. + } while (greset.b.rxfflsh == 1);
  26048. +
  26049. + /* Wait for 3 PHY Clocks */
  26050. + dwc_udelay(1);
  26051. +}
  26052. +
  26053. +/**
  26054. + * Do core a soft reset of the core. Be careful with this because it
  26055. + * resets all the internal state machines of the core.
  26056. + */
  26057. +void dwc_otg_core_reset(dwc_otg_core_if_t * core_if)
  26058. +{
  26059. + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
  26060. + volatile grstctl_t greset = {.d32 = 0 };
  26061. + int count = 0;
  26062. +
  26063. + DWC_DEBUGPL(DBG_CILV, "%s\n", __func__);
  26064. + /* Wait for AHB master IDLE state. */
  26065. + do {
  26066. + dwc_udelay(10);
  26067. + greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
  26068. + if (++count > 100000) {
  26069. + DWC_WARN("%s() HANG! AHB Idle GRSTCTL=%0x\n", __func__,
  26070. + greset.d32);
  26071. + return;
  26072. + }
  26073. + }
  26074. + while (greset.b.ahbidle == 0);
  26075. +
  26076. + /* Core Soft Reset */
  26077. + count = 0;
  26078. + greset.b.csftrst = 1;
  26079. + DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
  26080. + do {
  26081. + greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
  26082. + if (++count > 10000) {
  26083. + DWC_WARN("%s() HANG! Soft Reset GRSTCTL=%0x\n",
  26084. + __func__, greset.d32);
  26085. + break;
  26086. + }
  26087. + dwc_udelay(1);
  26088. + }
  26089. + while (greset.b.csftrst == 1);
  26090. +
  26091. + /* Wait for 3 PHY Clocks */
  26092. + dwc_mdelay(100);
  26093. +}
  26094. +
  26095. +uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if)
  26096. +{
  26097. + return (dwc_otg_mode(_core_if) != DWC_HOST_MODE);
  26098. +}
  26099. +
  26100. +uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if)
  26101. +{
  26102. + return (dwc_otg_mode(_core_if) == DWC_HOST_MODE);
  26103. +}
  26104. +
  26105. +/**
  26106. + * Register HCD callbacks. The callbacks are used to start and stop
  26107. + * the HCD for interrupt processing.
  26108. + *
  26109. + * @param core_if Programming view of DWC_otg controller.
  26110. + * @param cb the HCD callback structure.
  26111. + * @param p pointer to be passed to callback function (usb_hcd*).
  26112. + */
  26113. +void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * core_if,
  26114. + dwc_otg_cil_callbacks_t * cb, void *p)
  26115. +{
  26116. + core_if->hcd_cb = cb;
  26117. + cb->p = p;
  26118. +}
  26119. +
  26120. +/**
  26121. + * Register PCD callbacks. The callbacks are used to start and stop
  26122. + * the PCD for interrupt processing.
  26123. + *
  26124. + * @param core_if Programming view of DWC_otg controller.
  26125. + * @param cb the PCD callback structure.
  26126. + * @param p pointer to be passed to callback function (pcd*).
  26127. + */
  26128. +void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * core_if,
  26129. + dwc_otg_cil_callbacks_t * cb, void *p)
  26130. +{
  26131. + core_if->pcd_cb = cb;
  26132. + cb->p = p;
  26133. +}
  26134. +
  26135. +#ifdef DWC_EN_ISOC
  26136. +
  26137. +/**
  26138. + * This function writes isoc data per 1 (micro)frame into tx fifo
  26139. + *
  26140. + * @param core_if Programming view of DWC_otg controller.
  26141. + * @param ep The EP to start the transfer on.
  26142. + *
  26143. + */
  26144. +void write_isoc_frame_data(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
  26145. +{
  26146. + dwc_otg_dev_in_ep_regs_t *ep_regs;
  26147. + dtxfsts_data_t txstatus = {.d32 = 0 };
  26148. + uint32_t len = 0;
  26149. + uint32_t dwords;
  26150. +
  26151. + ep->xfer_len = ep->data_per_frame;
  26152. + ep->xfer_count = 0;
  26153. +
  26154. + ep_regs = core_if->dev_if->in_ep_regs[ep->num];
  26155. +
  26156. + len = ep->xfer_len - ep->xfer_count;
  26157. +
  26158. + if (len > ep->maxpacket) {
  26159. + len = ep->maxpacket;
  26160. + }
  26161. +
  26162. + dwords = (len + 3) / 4;
  26163. +
  26164. + /* While there is space in the queue and space in the FIFO and
  26165. + * More data to tranfer, Write packets to the Tx FIFO */
  26166. + txstatus.d32 =
  26167. + DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dtxfsts);
  26168. + DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", ep->num, txstatus.d32);
  26169. +
  26170. + while (txstatus.b.txfspcavail > dwords &&
  26171. + ep->xfer_count < ep->xfer_len && ep->xfer_len != 0) {
  26172. + /* Write the FIFO */
  26173. + dwc_otg_ep_write_packet(core_if, ep, 0);
  26174. +
  26175. + len = ep->xfer_len - ep->xfer_count;
  26176. + if (len > ep->maxpacket) {
  26177. + len = ep->maxpacket;
  26178. + }
  26179. +
  26180. + dwords = (len + 3) / 4;
  26181. + txstatus.d32 =
  26182. + DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
  26183. + dtxfsts);
  26184. + DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", ep->num,
  26185. + txstatus.d32);
  26186. + }
  26187. +}
  26188. +
  26189. +/**
  26190. + * This function initializes a descriptor chain for Isochronous transfer
  26191. + *
  26192. + * @param core_if Programming view of DWC_otg controller.
  26193. + * @param ep The EP to start the transfer on.
  26194. + *
  26195. + */
  26196. +void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if,
  26197. + dwc_ep_t * ep)
  26198. +{
  26199. + deptsiz_data_t deptsiz = {.d32 = 0 };
  26200. + depctl_data_t depctl = {.d32 = 0 };
  26201. + dsts_data_t dsts = {.d32 = 0 };
  26202. + volatile uint32_t *addr;
  26203. +
  26204. + if (ep->is_in) {
  26205. + addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
  26206. + } else {
  26207. + addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
  26208. + }
  26209. +
  26210. + ep->xfer_len = ep->data_per_frame;
  26211. + ep->xfer_count = 0;
  26212. + ep->xfer_buff = ep->cur_pkt_addr;
  26213. + ep->dma_addr = ep->cur_pkt_dma_addr;
  26214. +
  26215. + if (ep->is_in) {
  26216. + /* Program the transfer size and packet count
  26217. + * as follows: xfersize = N * maxpacket +
  26218. + * short_packet pktcnt = N + (short_packet
  26219. + * exist ? 1 : 0)
  26220. + */
  26221. + deptsiz.b.xfersize = ep->xfer_len;
  26222. + deptsiz.b.pktcnt =
  26223. + (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
  26224. + deptsiz.b.mc = deptsiz.b.pktcnt;
  26225. + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz,
  26226. + deptsiz.d32);
  26227. +
  26228. + /* Write the DMA register */
  26229. + if (core_if->dma_enable) {
  26230. + DWC_WRITE_REG32(&
  26231. + (core_if->dev_if->in_ep_regs[ep->num]->
  26232. + diepdma), (uint32_t) ep->dma_addr);
  26233. + }
  26234. + } else {
  26235. + deptsiz.b.pktcnt =
  26236. + (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket;
  26237. + deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
  26238. +
  26239. + DWC_WRITE_REG32(&core_if->dev_if->
  26240. + out_ep_regs[ep->num]->doeptsiz, deptsiz.d32);
  26241. +
  26242. + if (core_if->dma_enable) {
  26243. + DWC_WRITE_REG32(&
  26244. + (core_if->dev_if->
  26245. + out_ep_regs[ep->num]->doepdma),
  26246. + (uint32_t) ep->dma_addr);
  26247. + }
  26248. + }
  26249. +
  26250. + /** Enable endpoint, clear nak */
  26251. +
  26252. + depctl.d32 = 0;
  26253. + if (ep->bInterval == 1) {
  26254. + dsts.d32 =
  26255. + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
  26256. + ep->next_frame = dsts.b.soffn + ep->bInterval;
  26257. +
  26258. + if (ep->next_frame & 0x1) {
  26259. + depctl.b.setd1pid = 1;
  26260. + } else {
  26261. + depctl.b.setd0pid = 1;
  26262. + }
  26263. + } else {
  26264. + ep->next_frame += ep->bInterval;
  26265. +
  26266. + if (ep->next_frame & 0x1) {
  26267. + depctl.b.setd1pid = 1;
  26268. + } else {
  26269. + depctl.b.setd0pid = 1;
  26270. + }
  26271. + }
  26272. + depctl.b.epena = 1;
  26273. + depctl.b.cnak = 1;
  26274. +
  26275. + DWC_MODIFY_REG32(addr, 0, depctl.d32);
  26276. + depctl.d32 = DWC_READ_REG32(addr);
  26277. +
  26278. + if (ep->is_in && core_if->dma_enable == 0) {
  26279. + write_isoc_frame_data(core_if, ep);
  26280. + }
  26281. +
  26282. +}
  26283. +#endif /* DWC_EN_ISOC */
  26284. +
  26285. +static void dwc_otg_set_uninitialized(int32_t * p, int size)
  26286. +{
  26287. + int i;
  26288. + for (i = 0; i < size; i++) {
  26289. + p[i] = -1;
  26290. + }
  26291. +}
  26292. +
  26293. +static int dwc_otg_param_initialized(int32_t val)
  26294. +{
  26295. + return val != -1;
  26296. +}
  26297. +
  26298. +static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if)
  26299. +{
  26300. + int i;
  26301. + core_if->core_params = DWC_ALLOC(sizeof(*core_if->core_params));
  26302. + if (!core_if->core_params) {
  26303. + return -DWC_E_NO_MEMORY;
  26304. + }
  26305. + dwc_otg_set_uninitialized((int32_t *) core_if->core_params,
  26306. + sizeof(*core_if->core_params) /
  26307. + sizeof(int32_t));
  26308. + DWC_PRINTF("Setting default values for core params\n");
  26309. + dwc_otg_set_param_otg_cap(core_if, dwc_param_otg_cap_default);
  26310. + dwc_otg_set_param_dma_enable(core_if, dwc_param_dma_enable_default);
  26311. + dwc_otg_set_param_dma_desc_enable(core_if,
  26312. + dwc_param_dma_desc_enable_default);
  26313. + dwc_otg_set_param_opt(core_if, dwc_param_opt_default);
  26314. + dwc_otg_set_param_dma_burst_size(core_if,
  26315. + dwc_param_dma_burst_size_default);
  26316. + dwc_otg_set_param_host_support_fs_ls_low_power(core_if,
  26317. + dwc_param_host_support_fs_ls_low_power_default);
  26318. + dwc_otg_set_param_enable_dynamic_fifo(core_if,
  26319. + dwc_param_enable_dynamic_fifo_default);
  26320. + dwc_otg_set_param_data_fifo_size(core_if,
  26321. + dwc_param_data_fifo_size_default);
  26322. + dwc_otg_set_param_dev_rx_fifo_size(core_if,
  26323. + dwc_param_dev_rx_fifo_size_default);
  26324. + dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,
  26325. + dwc_param_dev_nperio_tx_fifo_size_default);
  26326. + dwc_otg_set_param_host_rx_fifo_size(core_if,
  26327. + dwc_param_host_rx_fifo_size_default);
  26328. + dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,
  26329. + dwc_param_host_nperio_tx_fifo_size_default);
  26330. + dwc_otg_set_param_host_perio_tx_fifo_size(core_if,
  26331. + dwc_param_host_perio_tx_fifo_size_default);
  26332. + dwc_otg_set_param_max_transfer_size(core_if,
  26333. + dwc_param_max_transfer_size_default);
  26334. + dwc_otg_set_param_max_packet_count(core_if,
  26335. + dwc_param_max_packet_count_default);
  26336. + dwc_otg_set_param_host_channels(core_if,
  26337. + dwc_param_host_channels_default);
  26338. + dwc_otg_set_param_dev_endpoints(core_if,
  26339. + dwc_param_dev_endpoints_default);
  26340. + dwc_otg_set_param_phy_type(core_if, dwc_param_phy_type_default);
  26341. + dwc_otg_set_param_speed(core_if, dwc_param_speed_default);
  26342. + dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,
  26343. + dwc_param_host_ls_low_power_phy_clk_default);
  26344. + dwc_otg_set_param_phy_ulpi_ddr(core_if, dwc_param_phy_ulpi_ddr_default);
  26345. + dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,
  26346. + dwc_param_phy_ulpi_ext_vbus_default);
  26347. + dwc_otg_set_param_phy_utmi_width(core_if,
  26348. + dwc_param_phy_utmi_width_default);
  26349. + dwc_otg_set_param_ts_dline(core_if, dwc_param_ts_dline_default);
  26350. + dwc_otg_set_param_i2c_enable(core_if, dwc_param_i2c_enable_default);
  26351. + dwc_otg_set_param_ulpi_fs_ls(core_if, dwc_param_ulpi_fs_ls_default);
  26352. + dwc_otg_set_param_en_multiple_tx_fifo(core_if,
  26353. + dwc_param_en_multiple_tx_fifo_default);
  26354. + for (i = 0; i < 15; i++) {
  26355. + dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,
  26356. + dwc_param_dev_perio_tx_fifo_size_default,
  26357. + i);
  26358. + }
  26359. +
  26360. + for (i = 0; i < 15; i++) {
  26361. + dwc_otg_set_param_dev_tx_fifo_size(core_if,
  26362. + dwc_param_dev_tx_fifo_size_default,
  26363. + i);
  26364. + }
  26365. + dwc_otg_set_param_thr_ctl(core_if, dwc_param_thr_ctl_default);
  26366. + dwc_otg_set_param_mpi_enable(core_if, dwc_param_mpi_enable_default);
  26367. + dwc_otg_set_param_pti_enable(core_if, dwc_param_pti_enable_default);
  26368. + dwc_otg_set_param_lpm_enable(core_if, dwc_param_lpm_enable_default);
  26369. + dwc_otg_set_param_ic_usb_cap(core_if, dwc_param_ic_usb_cap_default);
  26370. + dwc_otg_set_param_tx_thr_length(core_if,
  26371. + dwc_param_tx_thr_length_default);
  26372. + dwc_otg_set_param_rx_thr_length(core_if,
  26373. + dwc_param_rx_thr_length_default);
  26374. + dwc_otg_set_param_ahb_thr_ratio(core_if,
  26375. + dwc_param_ahb_thr_ratio_default);
  26376. + dwc_otg_set_param_power_down(core_if, dwc_param_power_down_default);
  26377. + dwc_otg_set_param_reload_ctl(core_if, dwc_param_reload_ctl_default);
  26378. + dwc_otg_set_param_dev_out_nak(core_if, dwc_param_dev_out_nak_default);
  26379. + dwc_otg_set_param_cont_on_bna(core_if, dwc_param_cont_on_bna_default);
  26380. + dwc_otg_set_param_ahb_single(core_if, dwc_param_ahb_single_default);
  26381. + dwc_otg_set_param_otg_ver(core_if, dwc_param_otg_ver_default);
  26382. + dwc_otg_set_param_adp_enable(core_if, dwc_param_adp_enable_default);
  26383. + DWC_PRINTF("Finished setting default values for core params\n");
  26384. +
  26385. + return 0;
  26386. +}
  26387. +
  26388. +uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if)
  26389. +{
  26390. + return core_if->dma_enable;
  26391. +}
  26392. +
  26393. +/* Checks if the parameter is outside of its valid range of values */
  26394. +#define DWC_OTG_PARAM_TEST(_param_, _low_, _high_) \
  26395. + (((_param_) < (_low_)) || \
  26396. + ((_param_) > (_high_)))
  26397. +
  26398. +/* Parameter access functions */
  26399. +int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val)
  26400. +{
  26401. + int valid;
  26402. + int retval = 0;
  26403. + if (DWC_OTG_PARAM_TEST(val, 0, 2)) {
  26404. + DWC_WARN("Wrong value for otg_cap parameter\n");
  26405. + DWC_WARN("otg_cap parameter must be 0,1 or 2\n");
  26406. + retval = -DWC_E_INVALID;
  26407. + goto out;
  26408. + }
  26409. +
  26410. + valid = 1;
  26411. + switch (val) {
  26412. + case DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE:
  26413. + if (core_if->hwcfg2.b.op_mode !=
  26414. + DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
  26415. + valid = 0;
  26416. + break;
  26417. + case DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE:
  26418. + if ((core_if->hwcfg2.b.op_mode !=
  26419. + DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
  26420. + && (core_if->hwcfg2.b.op_mode !=
  26421. + DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
  26422. + && (core_if->hwcfg2.b.op_mode !=
  26423. + DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)
  26424. + && (core_if->hwcfg2.b.op_mode !=
  26425. + DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) {
  26426. + valid = 0;
  26427. + }
  26428. + break;
  26429. + case DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE:
  26430. + /* always valid */
  26431. + break;
  26432. + }
  26433. + if (!valid) {
  26434. + if (dwc_otg_param_initialized(core_if->core_params->otg_cap)) {
  26435. + DWC_ERROR
  26436. + ("%d invalid for otg_cap paremter. Check HW configuration.\n",
  26437. + val);
  26438. + }
  26439. + val =
  26440. + (((core_if->hwcfg2.b.op_mode ==
  26441. + DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
  26442. + || (core_if->hwcfg2.b.op_mode ==
  26443. + DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
  26444. + || (core_if->hwcfg2.b.op_mode ==
  26445. + DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)
  26446. + || (core_if->hwcfg2.b.op_mode ==
  26447. + DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) ?
  26448. + DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE :
  26449. + DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
  26450. + retval = -DWC_E_INVALID;
  26451. + }
  26452. +
  26453. + core_if->core_params->otg_cap = val;
  26454. +out:
  26455. + return retval;
  26456. +}
  26457. +
  26458. +int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if)
  26459. +{
  26460. + return core_if->core_params->otg_cap;
  26461. +}
  26462. +
  26463. +int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val)
  26464. +{
  26465. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  26466. + DWC_WARN("Wrong value for opt parameter\n");
  26467. + return -DWC_E_INVALID;
  26468. + }
  26469. + core_if->core_params->opt = val;
  26470. + return 0;
  26471. +}
  26472. +
  26473. +int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if)
  26474. +{
  26475. + return core_if->core_params->opt;
  26476. +}
  26477. +
  26478. +int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if, int32_t val)
  26479. +{
  26480. + int retval = 0;
  26481. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  26482. + DWC_WARN("Wrong value for dma enable\n");
  26483. + return -DWC_E_INVALID;
  26484. + }
  26485. +
  26486. + if ((val == 1) && (core_if->hwcfg2.b.architecture == 0)) {
  26487. + if (dwc_otg_param_initialized(core_if->core_params->dma_enable)) {
  26488. + DWC_ERROR
  26489. + ("%d invalid for dma_enable paremter. Check HW configuration.\n",
  26490. + val);
  26491. + }
  26492. + val = 0;
  26493. + retval = -DWC_E_INVALID;
  26494. + }
  26495. +
  26496. + core_if->core_params->dma_enable = val;
  26497. + if (val == 0) {
  26498. + dwc_otg_set_param_dma_desc_enable(core_if, 0);
  26499. + }
  26500. + return retval;
  26501. +}
  26502. +
  26503. +int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if)
  26504. +{
  26505. + return core_if->core_params->dma_enable;
  26506. +}
  26507. +
  26508. +int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if, int32_t val)
  26509. +{
  26510. + int retval = 0;
  26511. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  26512. + DWC_WARN("Wrong value for dma_enable\n");
  26513. + DWC_WARN("dma_desc_enable must be 0 or 1\n");
  26514. + return -DWC_E_INVALID;
  26515. + }
  26516. +
  26517. + if ((val == 1)
  26518. + && ((dwc_otg_get_param_dma_enable(core_if) == 0)
  26519. + || (core_if->hwcfg4.b.desc_dma == 0))) {
  26520. + if (dwc_otg_param_initialized
  26521. + (core_if->core_params->dma_desc_enable)) {
  26522. + DWC_ERROR
  26523. + ("%d invalid for dma_desc_enable paremter. Check HW configuration.\n",
  26524. + val);
  26525. + }
  26526. + val = 0;
  26527. + retval = -DWC_E_INVALID;
  26528. + }
  26529. + core_if->core_params->dma_desc_enable = val;
  26530. + return retval;
  26531. +}
  26532. +
  26533. +int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if)
  26534. +{
  26535. + return core_if->core_params->dma_desc_enable;
  26536. +}
  26537. +
  26538. +int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t * core_if,
  26539. + int32_t val)
  26540. +{
  26541. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  26542. + DWC_WARN("Wrong value for host_support_fs_low_power\n");
  26543. + DWC_WARN("host_support_fs_low_power must be 0 or 1\n");
  26544. + return -DWC_E_INVALID;
  26545. + }
  26546. + core_if->core_params->host_support_fs_ls_low_power = val;
  26547. + return 0;
  26548. +}
  26549. +
  26550. +int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *
  26551. + core_if)
  26552. +{
  26553. + return core_if->core_params->host_support_fs_ls_low_power;
  26554. +}
  26555. +
  26556. +int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if,
  26557. + int32_t val)
  26558. +{
  26559. + int retval = 0;
  26560. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  26561. + DWC_WARN("Wrong value for enable_dynamic_fifo\n");
  26562. + DWC_WARN("enable_dynamic_fifo must be 0 or 1\n");
  26563. + return -DWC_E_INVALID;
  26564. + }
  26565. +
  26566. + if ((val == 1) && (core_if->hwcfg2.b.dynamic_fifo == 0)) {
  26567. + if (dwc_otg_param_initialized
  26568. + (core_if->core_params->enable_dynamic_fifo)) {
  26569. + DWC_ERROR
  26570. + ("%d invalid for enable_dynamic_fifo paremter. Check HW configuration.\n",
  26571. + val);
  26572. + }
  26573. + val = 0;
  26574. + retval = -DWC_E_INVALID;
  26575. + }
  26576. + core_if->core_params->enable_dynamic_fifo = val;
  26577. + return retval;
  26578. +}
  26579. +
  26580. +int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if)
  26581. +{
  26582. + return core_if->core_params->enable_dynamic_fifo;
  26583. +}
  26584. +
  26585. +int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if, int32_t val)
  26586. +{
  26587. + int retval = 0;
  26588. + if (DWC_OTG_PARAM_TEST(val, 32, 32768)) {
  26589. + DWC_WARN("Wrong value for data_fifo_size\n");
  26590. + DWC_WARN("data_fifo_size must be 32-32768\n");
  26591. + return -DWC_E_INVALID;
  26592. + }
  26593. +
  26594. + if (val > core_if->hwcfg3.b.dfifo_depth) {
  26595. + if (dwc_otg_param_initialized
  26596. + (core_if->core_params->data_fifo_size)) {
  26597. + DWC_ERROR
  26598. + ("%d invalid for data_fifo_size parameter. Check HW configuration.\n",
  26599. + val);
  26600. + }
  26601. + val = core_if->hwcfg3.b.dfifo_depth;
  26602. + retval = -DWC_E_INVALID;
  26603. + }
  26604. +
  26605. + core_if->core_params->data_fifo_size = val;
  26606. + return retval;
  26607. +}
  26608. +
  26609. +int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if)
  26610. +{
  26611. + return core_if->core_params->data_fifo_size;
  26612. +}
  26613. +
  26614. +int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val)
  26615. +{
  26616. + int retval = 0;
  26617. + if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
  26618. + DWC_WARN("Wrong value for dev_rx_fifo_size\n");
  26619. + DWC_WARN("dev_rx_fifo_size must be 16-32768\n");
  26620. + return -DWC_E_INVALID;
  26621. + }
  26622. +
  26623. + if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) {
  26624. + if (dwc_otg_param_initialized(core_if->core_params->dev_rx_fifo_size)) {
  26625. + DWC_WARN("%d invalid for dev_rx_fifo_size parameter\n", val);
  26626. + }
  26627. + val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
  26628. + retval = -DWC_E_INVALID;
  26629. + }
  26630. +
  26631. + core_if->core_params->dev_rx_fifo_size = val;
  26632. + return retval;
  26633. +}
  26634. +
  26635. +int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if)
  26636. +{
  26637. + return core_if->core_params->dev_rx_fifo_size;
  26638. +}
  26639. +
  26640. +int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if,
  26641. + int32_t val)
  26642. +{
  26643. + int retval = 0;
  26644. +
  26645. + if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
  26646. + DWC_WARN("Wrong value for dev_nperio_tx_fifo\n");
  26647. + DWC_WARN("dev_nperio_tx_fifo must be 16-32768\n");
  26648. + return -DWC_E_INVALID;
  26649. + }
  26650. +
  26651. + if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {
  26652. + if (dwc_otg_param_initialized
  26653. + (core_if->core_params->dev_nperio_tx_fifo_size)) {
  26654. + DWC_ERROR
  26655. + ("%d invalid for dev_nperio_tx_fifo_size. Check HW configuration.\n",
  26656. + val);
  26657. + }
  26658. + val =
  26659. + (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >>
  26660. + 16);
  26661. + retval = -DWC_E_INVALID;
  26662. + }
  26663. +
  26664. + core_if->core_params->dev_nperio_tx_fifo_size = val;
  26665. + return retval;
  26666. +}
  26667. +
  26668. +int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if)
  26669. +{
  26670. + return core_if->core_params->dev_nperio_tx_fifo_size;
  26671. +}
  26672. +
  26673. +int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if,
  26674. + int32_t val)
  26675. +{
  26676. + int retval = 0;
  26677. +
  26678. + if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
  26679. + DWC_WARN("Wrong value for host_rx_fifo_size\n");
  26680. + DWC_WARN("host_rx_fifo_size must be 16-32768\n");
  26681. + return -DWC_E_INVALID;
  26682. + }
  26683. +
  26684. + if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) {
  26685. + if (dwc_otg_param_initialized
  26686. + (core_if->core_params->host_rx_fifo_size)) {
  26687. + DWC_ERROR
  26688. + ("%d invalid for host_rx_fifo_size. Check HW configuration.\n",
  26689. + val);
  26690. + }
  26691. + val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
  26692. + retval = -DWC_E_INVALID;
  26693. + }
  26694. +
  26695. + core_if->core_params->host_rx_fifo_size = val;
  26696. + return retval;
  26697. +
  26698. +}
  26699. +
  26700. +int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if)
  26701. +{
  26702. + return core_if->core_params->host_rx_fifo_size;
  26703. +}
  26704. +
  26705. +int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if,
  26706. + int32_t val)
  26707. +{
  26708. + int retval = 0;
  26709. +
  26710. + if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
  26711. + DWC_WARN("Wrong value for host_nperio_tx_fifo_size\n");
  26712. + DWC_WARN("host_nperio_tx_fifo_size must be 16-32768\n");
  26713. + return -DWC_E_INVALID;
  26714. + }
  26715. +
  26716. + if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {
  26717. + if (dwc_otg_param_initialized
  26718. + (core_if->core_params->host_nperio_tx_fifo_size)) {
  26719. + DWC_ERROR
  26720. + ("%d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n",
  26721. + val);
  26722. + }
  26723. + val =
  26724. + (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >>
  26725. + 16);
  26726. + retval = -DWC_E_INVALID;
  26727. + }
  26728. +
  26729. + core_if->core_params->host_nperio_tx_fifo_size = val;
  26730. + return retval;
  26731. +}
  26732. +
  26733. +int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if)
  26734. +{
  26735. + return core_if->core_params->host_nperio_tx_fifo_size;
  26736. +}
  26737. +
  26738. +int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
  26739. + int32_t val)
  26740. +{
  26741. + int retval = 0;
  26742. + if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
  26743. + DWC_WARN("Wrong value for host_perio_tx_fifo_size\n");
  26744. + DWC_WARN("host_perio_tx_fifo_size must be 16-32768\n");
  26745. + return -DWC_E_INVALID;
  26746. + }
  26747. +
  26748. + if (val > ((core_if->hptxfsiz.d32) >> 16)) {
  26749. + if (dwc_otg_param_initialized
  26750. + (core_if->core_params->host_perio_tx_fifo_size)) {
  26751. + DWC_ERROR
  26752. + ("%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n",
  26753. + val);
  26754. + }
  26755. + val = (core_if->hptxfsiz.d32) >> 16;
  26756. + retval = -DWC_E_INVALID;
  26757. + }
  26758. +
  26759. + core_if->core_params->host_perio_tx_fifo_size = val;
  26760. + return retval;
  26761. +}
  26762. +
  26763. +int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if)
  26764. +{
  26765. + return core_if->core_params->host_perio_tx_fifo_size;
  26766. +}
  26767. +
  26768. +int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if,
  26769. + int32_t val)
  26770. +{
  26771. + int retval = 0;
  26772. +
  26773. + if (DWC_OTG_PARAM_TEST(val, 2047, 524288)) {
  26774. + DWC_WARN("Wrong value for max_transfer_size\n");
  26775. + DWC_WARN("max_transfer_size must be 2047-524288\n");
  26776. + return -DWC_E_INVALID;
  26777. + }
  26778. +
  26779. + if (val >= (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11))) {
  26780. + if (dwc_otg_param_initialized
  26781. + (core_if->core_params->max_transfer_size)) {
  26782. + DWC_ERROR
  26783. + ("%d invalid for max_transfer_size. Check HW configuration.\n",
  26784. + val);
  26785. + }
  26786. + val =
  26787. + ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 11)) -
  26788. + 1);
  26789. + retval = -DWC_E_INVALID;
  26790. + }
  26791. +
  26792. + core_if->core_params->max_transfer_size = val;
  26793. + return retval;
  26794. +}
  26795. +
  26796. +int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if)
  26797. +{
  26798. + return core_if->core_params->max_transfer_size;
  26799. +}
  26800. +
  26801. +int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if, int32_t val)
  26802. +{
  26803. + int retval = 0;
  26804. +
  26805. + if (DWC_OTG_PARAM_TEST(val, 15, 511)) {
  26806. + DWC_WARN("Wrong value for max_packet_count\n");
  26807. + DWC_WARN("max_packet_count must be 15-511\n");
  26808. + return -DWC_E_INVALID;
  26809. + }
  26810. +
  26811. + if (val > (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4))) {
  26812. + if (dwc_otg_param_initialized
  26813. + (core_if->core_params->max_packet_count)) {
  26814. + DWC_ERROR
  26815. + ("%d invalid for max_packet_count. Check HW configuration.\n",
  26816. + val);
  26817. + }
  26818. + val =
  26819. + ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1);
  26820. + retval = -DWC_E_INVALID;
  26821. + }
  26822. +
  26823. + core_if->core_params->max_packet_count = val;
  26824. + return retval;
  26825. +}
  26826. +
  26827. +int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if)
  26828. +{
  26829. + return core_if->core_params->max_packet_count;
  26830. +}
  26831. +
  26832. +int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if, int32_t val)
  26833. +{
  26834. + int retval = 0;
  26835. +
  26836. + if (DWC_OTG_PARAM_TEST(val, 1, 16)) {
  26837. + DWC_WARN("Wrong value for host_channels\n");
  26838. + DWC_WARN("host_channels must be 1-16\n");
  26839. + return -DWC_E_INVALID;
  26840. + }
  26841. +
  26842. + if (val > (core_if->hwcfg2.b.num_host_chan + 1)) {
  26843. + if (dwc_otg_param_initialized
  26844. + (core_if->core_params->host_channels)) {
  26845. + DWC_ERROR
  26846. + ("%d invalid for host_channels. Check HW configurations.\n",
  26847. + val);
  26848. + }
  26849. + val = (core_if->hwcfg2.b.num_host_chan + 1);
  26850. + retval = -DWC_E_INVALID;
  26851. + }
  26852. +
  26853. + core_if->core_params->host_channels = val;
  26854. + return retval;
  26855. +}
  26856. +
  26857. +int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if)
  26858. +{
  26859. + return core_if->core_params->host_channels;
  26860. +}
  26861. +
  26862. +int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if, int32_t val)
  26863. +{
  26864. + int retval = 0;
  26865. +
  26866. + if (DWC_OTG_PARAM_TEST(val, 1, 15)) {
  26867. + DWC_WARN("Wrong value for dev_endpoints\n");
  26868. + DWC_WARN("dev_endpoints must be 1-15\n");
  26869. + return -DWC_E_INVALID;
  26870. + }
  26871. +
  26872. + if (val > (core_if->hwcfg2.b.num_dev_ep)) {
  26873. + if (dwc_otg_param_initialized
  26874. + (core_if->core_params->dev_endpoints)) {
  26875. + DWC_ERROR
  26876. + ("%d invalid for dev_endpoints. Check HW configurations.\n",
  26877. + val);
  26878. + }
  26879. + val = core_if->hwcfg2.b.num_dev_ep;
  26880. + retval = -DWC_E_INVALID;
  26881. + }
  26882. +
  26883. + core_if->core_params->dev_endpoints = val;
  26884. + return retval;
  26885. +}
  26886. +
  26887. +int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if)
  26888. +{
  26889. + return core_if->core_params->dev_endpoints;
  26890. +}
  26891. +
  26892. +int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val)
  26893. +{
  26894. + int retval = 0;
  26895. + int valid = 0;
  26896. +
  26897. + if (DWC_OTG_PARAM_TEST(val, 0, 2)) {
  26898. + DWC_WARN("Wrong value for phy_type\n");
  26899. + DWC_WARN("phy_type must be 0,1 or 2\n");
  26900. + return -DWC_E_INVALID;
  26901. + }
  26902. +#ifndef NO_FS_PHY_HW_CHECKS
  26903. + if ((val == DWC_PHY_TYPE_PARAM_UTMI) &&
  26904. + ((core_if->hwcfg2.b.hs_phy_type == 1) ||
  26905. + (core_if->hwcfg2.b.hs_phy_type == 3))) {
  26906. + valid = 1;
  26907. + } else if ((val == DWC_PHY_TYPE_PARAM_ULPI) &&
  26908. + ((core_if->hwcfg2.b.hs_phy_type == 2) ||
  26909. + (core_if->hwcfg2.b.hs_phy_type == 3))) {
  26910. + valid = 1;
  26911. + } else if ((val == DWC_PHY_TYPE_PARAM_FS) &&
  26912. + (core_if->hwcfg2.b.fs_phy_type == 1)) {
  26913. + valid = 1;
  26914. + }
  26915. + if (!valid) {
  26916. + if (dwc_otg_param_initialized(core_if->core_params->phy_type)) {
  26917. + DWC_ERROR
  26918. + ("%d invalid for phy_type. Check HW configurations.\n",
  26919. + val);
  26920. + }
  26921. + if (core_if->hwcfg2.b.hs_phy_type) {
  26922. + if ((core_if->hwcfg2.b.hs_phy_type == 3) ||
  26923. + (core_if->hwcfg2.b.hs_phy_type == 1)) {
  26924. + val = DWC_PHY_TYPE_PARAM_UTMI;
  26925. + } else {
  26926. + val = DWC_PHY_TYPE_PARAM_ULPI;
  26927. + }
  26928. + }
  26929. + retval = -DWC_E_INVALID;
  26930. + }
  26931. +#endif
  26932. + core_if->core_params->phy_type = val;
  26933. + return retval;
  26934. +}
  26935. +
  26936. +int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if)
  26937. +{
  26938. + return core_if->core_params->phy_type;
  26939. +}
  26940. +
  26941. +int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val)
  26942. +{
  26943. + int retval = 0;
  26944. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  26945. + DWC_WARN("Wrong value for speed parameter\n");
  26946. + DWC_WARN("max_speed parameter must be 0 or 1\n");
  26947. + return -DWC_E_INVALID;
  26948. + }
  26949. + if ((val == 0)
  26950. + && dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS) {
  26951. + if (dwc_otg_param_initialized(core_if->core_params->speed)) {
  26952. + DWC_ERROR
  26953. + ("%d invalid for speed paremter. Check HW configuration.\n",
  26954. + val);
  26955. + }
  26956. + val =
  26957. + (dwc_otg_get_param_phy_type(core_if) ==
  26958. + DWC_PHY_TYPE_PARAM_FS ? 1 : 0);
  26959. + retval = -DWC_E_INVALID;
  26960. + }
  26961. + core_if->core_params->speed = val;
  26962. + return retval;
  26963. +}
  26964. +
  26965. +int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if)
  26966. +{
  26967. + return core_if->core_params->speed;
  26968. +}
  26969. +
  26970. +int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if,
  26971. + int32_t val)
  26972. +{
  26973. + int retval = 0;
  26974. +
  26975. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  26976. + DWC_WARN
  26977. + ("Wrong value for host_ls_low_power_phy_clk parameter\n");
  26978. + DWC_WARN("host_ls_low_power_phy_clk must be 0 or 1\n");
  26979. + return -DWC_E_INVALID;
  26980. + }
  26981. +
  26982. + if ((val == DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ)
  26983. + && (dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS)) {
  26984. + if (dwc_otg_param_initialized
  26985. + (core_if->core_params->host_ls_low_power_phy_clk)) {
  26986. + DWC_ERROR
  26987. + ("%d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n",
  26988. + val);
  26989. + }
  26990. + val =
  26991. + (dwc_otg_get_param_phy_type(core_if) ==
  26992. + DWC_PHY_TYPE_PARAM_FS) ?
  26993. + DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ :
  26994. + DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ;
  26995. + retval = -DWC_E_INVALID;
  26996. + }
  26997. +
  26998. + core_if->core_params->host_ls_low_power_phy_clk = val;
  26999. + return retval;
  27000. +}
  27001. +
  27002. +int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if)
  27003. +{
  27004. + return core_if->core_params->host_ls_low_power_phy_clk;
  27005. +}
  27006. +
  27007. +int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if, int32_t val)
  27008. +{
  27009. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  27010. + DWC_WARN("Wrong value for phy_ulpi_ddr\n");
  27011. + DWC_WARN("phy_upli_ddr must be 0 or 1\n");
  27012. + return -DWC_E_INVALID;
  27013. + }
  27014. +
  27015. + core_if->core_params->phy_ulpi_ddr = val;
  27016. + return 0;
  27017. +}
  27018. +
  27019. +int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if)
  27020. +{
  27021. + return core_if->core_params->phy_ulpi_ddr;
  27022. +}
  27023. +
  27024. +int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if,
  27025. + int32_t val)
  27026. +{
  27027. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  27028. + DWC_WARN("Wrong valaue for phy_ulpi_ext_vbus\n");
  27029. + DWC_WARN("phy_ulpi_ext_vbus must be 0 or 1\n");
  27030. + return -DWC_E_INVALID;
  27031. + }
  27032. +
  27033. + core_if->core_params->phy_ulpi_ext_vbus = val;
  27034. + return 0;
  27035. +}
  27036. +
  27037. +int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if)
  27038. +{
  27039. + return core_if->core_params->phy_ulpi_ext_vbus;
  27040. +}
  27041. +
  27042. +int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if, int32_t val)
  27043. +{
  27044. + if (DWC_OTG_PARAM_TEST(val, 8, 8) && DWC_OTG_PARAM_TEST(val, 16, 16)) {
  27045. + DWC_WARN("Wrong valaue for phy_utmi_width\n");
  27046. + DWC_WARN("phy_utmi_width must be 8 or 16\n");
  27047. + return -DWC_E_INVALID;
  27048. + }
  27049. +
  27050. + core_if->core_params->phy_utmi_width = val;
  27051. + return 0;
  27052. +}
  27053. +
  27054. +int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if)
  27055. +{
  27056. + return core_if->core_params->phy_utmi_width;
  27057. +}
  27058. +
  27059. +int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if, int32_t val)
  27060. +{
  27061. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  27062. + DWC_WARN("Wrong valaue for ulpi_fs_ls\n");
  27063. + DWC_WARN("ulpi_fs_ls must be 0 or 1\n");
  27064. + return -DWC_E_INVALID;
  27065. + }
  27066. +
  27067. + core_if->core_params->ulpi_fs_ls = val;
  27068. + return 0;
  27069. +}
  27070. +
  27071. +int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if)
  27072. +{
  27073. + return core_if->core_params->ulpi_fs_ls;
  27074. +}
  27075. +
  27076. +int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val)
  27077. +{
  27078. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  27079. + DWC_WARN("Wrong valaue for ts_dline\n");
  27080. + DWC_WARN("ts_dline must be 0 or 1\n");
  27081. + return -DWC_E_INVALID;
  27082. + }
  27083. +
  27084. + core_if->core_params->ts_dline = val;
  27085. + return 0;
  27086. +}
  27087. +
  27088. +int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if)
  27089. +{
  27090. + return core_if->core_params->ts_dline;
  27091. +}
  27092. +
  27093. +int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if, int32_t val)
  27094. +{
  27095. + int retval = 0;
  27096. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  27097. + DWC_WARN("Wrong valaue for i2c_enable\n");
  27098. + DWC_WARN("i2c_enable must be 0 or 1\n");
  27099. + return -DWC_E_INVALID;
  27100. + }
  27101. +#ifndef NO_FS_PHY_HW_CHECK
  27102. + if (val == 1 && core_if->hwcfg3.b.i2c == 0) {
  27103. + if (dwc_otg_param_initialized(core_if->core_params->i2c_enable)) {
  27104. + DWC_ERROR
  27105. + ("%d invalid for i2c_enable. Check HW configuration.\n",
  27106. + val);
  27107. + }
  27108. + val = 0;
  27109. + retval = -DWC_E_INVALID;
  27110. + }
  27111. +#endif
  27112. +
  27113. + core_if->core_params->i2c_enable = val;
  27114. + return retval;
  27115. +}
  27116. +
  27117. +int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if)
  27118. +{
  27119. + return core_if->core_params->i2c_enable;
  27120. +}
  27121. +
  27122. +int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
  27123. + int32_t val, int fifo_num)
  27124. +{
  27125. + int retval = 0;
  27126. +
  27127. + if (DWC_OTG_PARAM_TEST(val, 4, 768)) {
  27128. + DWC_WARN("Wrong value for dev_perio_tx_fifo_size\n");
  27129. + DWC_WARN("dev_perio_tx_fifo_size must be 4-768\n");
  27130. + return -DWC_E_INVALID;
  27131. + }
  27132. +
  27133. + if (val >
  27134. + (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) {
  27135. + if (dwc_otg_param_initialized
  27136. + (core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) {
  27137. + DWC_ERROR
  27138. + ("`%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n",
  27139. + val, fifo_num);
  27140. + }
  27141. + val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]));
  27142. + retval = -DWC_E_INVALID;
  27143. + }
  27144. +
  27145. + core_if->core_params->dev_perio_tx_fifo_size[fifo_num] = val;
  27146. + return retval;
  27147. +}
  27148. +
  27149. +int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
  27150. + int fifo_num)
  27151. +{
  27152. + return core_if->core_params->dev_perio_tx_fifo_size[fifo_num];
  27153. +}
  27154. +
  27155. +int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if,
  27156. + int32_t val)
  27157. +{
  27158. + int retval = 0;
  27159. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  27160. + DWC_WARN("Wrong valaue for en_multiple_tx_fifo,\n");
  27161. + DWC_WARN("en_multiple_tx_fifo must be 0 or 1\n");
  27162. + return -DWC_E_INVALID;
  27163. + }
  27164. +
  27165. + if (val == 1 && core_if->hwcfg4.b.ded_fifo_en == 0) {
  27166. + if (dwc_otg_param_initialized
  27167. + (core_if->core_params->en_multiple_tx_fifo)) {
  27168. + DWC_ERROR
  27169. + ("%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n",
  27170. + val);
  27171. + }
  27172. + val = 0;
  27173. + retval = -DWC_E_INVALID;
  27174. + }
  27175. +
  27176. + core_if->core_params->en_multiple_tx_fifo = val;
  27177. + return retval;
  27178. +}
  27179. +
  27180. +int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if)
  27181. +{
  27182. + return core_if->core_params->en_multiple_tx_fifo;
  27183. +}
  27184. +
  27185. +int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val,
  27186. + int fifo_num)
  27187. +{
  27188. + int retval = 0;
  27189. +
  27190. + if (DWC_OTG_PARAM_TEST(val, 4, 768)) {
  27191. + DWC_WARN("Wrong value for dev_tx_fifo_size\n");
  27192. + DWC_WARN("dev_tx_fifo_size must be 4-768\n");
  27193. + return -DWC_E_INVALID;
  27194. + }
  27195. +
  27196. + if (val >
  27197. + (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) {
  27198. + if (dwc_otg_param_initialized
  27199. + (core_if->core_params->dev_tx_fifo_size[fifo_num])) {
  27200. + DWC_ERROR
  27201. + ("`%d' invalid for parameter `dev_tx_fifo_size_%d'. Check HW configuration.\n",
  27202. + val, fifo_num);
  27203. + }
  27204. + val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]));
  27205. + retval = -DWC_E_INVALID;
  27206. + }
  27207. +
  27208. + core_if->core_params->dev_tx_fifo_size[fifo_num] = val;
  27209. + return retval;
  27210. +}
  27211. +
  27212. +int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
  27213. + int fifo_num)
  27214. +{
  27215. + return core_if->core_params->dev_tx_fifo_size[fifo_num];
  27216. +}
  27217. +
  27218. +int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val)
  27219. +{
  27220. + int retval = 0;
  27221. +
  27222. + if (DWC_OTG_PARAM_TEST(val, 0, 7)) {
  27223. + DWC_WARN("Wrong value for thr_ctl\n");
  27224. + DWC_WARN("thr_ctl must be 0-7\n");
  27225. + return -DWC_E_INVALID;
  27226. + }
  27227. +
  27228. + if ((val != 0) &&
  27229. + (!dwc_otg_get_param_dma_enable(core_if) ||
  27230. + !core_if->hwcfg4.b.ded_fifo_en)) {
  27231. + if (dwc_otg_param_initialized(core_if->core_params->thr_ctl)) {
  27232. + DWC_ERROR
  27233. + ("%d invalid for parameter thr_ctl. Check HW configuration.\n",
  27234. + val);
  27235. + }
  27236. + val = 0;
  27237. + retval = -DWC_E_INVALID;
  27238. + }
  27239. +
  27240. + core_if->core_params->thr_ctl = val;
  27241. + return retval;
  27242. +}
  27243. +
  27244. +int32_t dwc_otg_get_param_thr_ctl(dwc_otg_core_if_t * core_if)
  27245. +{
  27246. + return core_if->core_params->thr_ctl;
  27247. +}
  27248. +
  27249. +int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if, int32_t val)
  27250. +{
  27251. + int retval = 0;
  27252. +
  27253. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  27254. + DWC_WARN("Wrong value for lpm_enable\n");
  27255. + DWC_WARN("lpm_enable must be 0 or 1\n");
  27256. + return -DWC_E_INVALID;
  27257. + }
  27258. +
  27259. + if (val && !core_if->hwcfg3.b.otg_lpm_en) {
  27260. + if (dwc_otg_param_initialized(core_if->core_params->lpm_enable)) {
  27261. + DWC_ERROR
  27262. + ("%d invalid for parameter lpm_enable. Check HW configuration.\n",
  27263. + val);
  27264. + }
  27265. + val = 0;
  27266. + retval = -DWC_E_INVALID;
  27267. + }
  27268. +
  27269. + core_if->core_params->lpm_enable = val;
  27270. + return retval;
  27271. +}
  27272. +
  27273. +int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if)
  27274. +{
  27275. + return core_if->core_params->lpm_enable;
  27276. +}
  27277. +
  27278. +int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if, int32_t val)
  27279. +{
  27280. + if (DWC_OTG_PARAM_TEST(val, 8, 128)) {
  27281. + DWC_WARN("Wrong valaue for tx_thr_length\n");
  27282. + DWC_WARN("tx_thr_length must be 8 - 128\n");
  27283. + return -DWC_E_INVALID;
  27284. + }
  27285. +
  27286. + core_if->core_params->tx_thr_length = val;
  27287. + return 0;
  27288. +}
  27289. +
  27290. +int32_t dwc_otg_get_param_tx_thr_length(dwc_otg_core_if_t * core_if)
  27291. +{
  27292. + return core_if->core_params->tx_thr_length;
  27293. +}
  27294. +
  27295. +int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if, int32_t val)
  27296. +{
  27297. + if (DWC_OTG_PARAM_TEST(val, 8, 128)) {
  27298. + DWC_WARN("Wrong valaue for rx_thr_length\n");
  27299. + DWC_WARN("rx_thr_length must be 8 - 128\n");
  27300. + return -DWC_E_INVALID;
  27301. + }
  27302. +
  27303. + core_if->core_params->rx_thr_length = val;
  27304. + return 0;
  27305. +}
  27306. +
  27307. +int32_t dwc_otg_get_param_rx_thr_length(dwc_otg_core_if_t * core_if)
  27308. +{
  27309. + return core_if->core_params->rx_thr_length;
  27310. +}
  27311. +
  27312. +int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if, int32_t val)
  27313. +{
  27314. + if (DWC_OTG_PARAM_TEST(val, 1, 1) &&
  27315. + DWC_OTG_PARAM_TEST(val, 4, 4) &&
  27316. + DWC_OTG_PARAM_TEST(val, 8, 8) &&
  27317. + DWC_OTG_PARAM_TEST(val, 16, 16) &&
  27318. + DWC_OTG_PARAM_TEST(val, 32, 32) &&
  27319. + DWC_OTG_PARAM_TEST(val, 64, 64) &&
  27320. + DWC_OTG_PARAM_TEST(val, 128, 128) &&
  27321. + DWC_OTG_PARAM_TEST(val, 256, 256)) {
  27322. + DWC_WARN("`%d' invalid for parameter `dma_burst_size'\n", val);
  27323. + return -DWC_E_INVALID;
  27324. + }
  27325. + core_if->core_params->dma_burst_size = val;
  27326. + return 0;
  27327. +}
  27328. +
  27329. +int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if)
  27330. +{
  27331. + return core_if->core_params->dma_burst_size;
  27332. +}
  27333. +
  27334. +int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if, int32_t val)
  27335. +{
  27336. + int retval = 0;
  27337. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  27338. + DWC_WARN("`%d' invalid for parameter `pti_enable'\n", val);
  27339. + return -DWC_E_INVALID;
  27340. + }
  27341. + if (val && (core_if->snpsid < OTG_CORE_REV_2_72a)) {
  27342. + if (dwc_otg_param_initialized(core_if->core_params->pti_enable)) {
  27343. + DWC_ERROR
  27344. + ("%d invalid for parameter pti_enable. Check HW configuration.\n",
  27345. + val);
  27346. + }
  27347. + retval = -DWC_E_INVALID;
  27348. + val = 0;
  27349. + }
  27350. + core_if->core_params->pti_enable = val;
  27351. + return retval;
  27352. +}
  27353. +
  27354. +int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if)
  27355. +{
  27356. + return core_if->core_params->pti_enable;
  27357. +}
  27358. +
  27359. +int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if, int32_t val)
  27360. +{
  27361. + int retval = 0;
  27362. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  27363. + DWC_WARN("`%d' invalid for parameter `mpi_enable'\n", val);
  27364. + return -DWC_E_INVALID;
  27365. + }
  27366. + if (val && (core_if->hwcfg2.b.multi_proc_int == 0)) {
  27367. + if (dwc_otg_param_initialized(core_if->core_params->mpi_enable)) {
  27368. + DWC_ERROR
  27369. + ("%d invalid for parameter mpi_enable. Check HW configuration.\n",
  27370. + val);
  27371. + }
  27372. + retval = -DWC_E_INVALID;
  27373. + val = 0;
  27374. + }
  27375. + core_if->core_params->mpi_enable = val;
  27376. + return retval;
  27377. +}
  27378. +
  27379. +int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if)
  27380. +{
  27381. + return core_if->core_params->mpi_enable;
  27382. +}
  27383. +
  27384. +int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if, int32_t val)
  27385. +{
  27386. + int retval = 0;
  27387. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  27388. + DWC_WARN("`%d' invalid for parameter `adp_enable'\n", val);
  27389. + return -DWC_E_INVALID;
  27390. + }
  27391. + if (val && (core_if->hwcfg3.b.adp_supp == 0)) {
  27392. + if (dwc_otg_param_initialized
  27393. + (core_if->core_params->adp_supp_enable)) {
  27394. + DWC_ERROR
  27395. + ("%d invalid for parameter adp_enable. Check HW configuration.\n",
  27396. + val);
  27397. + }
  27398. + retval = -DWC_E_INVALID;
  27399. + val = 0;
  27400. + }
  27401. + core_if->core_params->adp_supp_enable = val;
  27402. + /*Set OTG version 2.0 in case of enabling ADP*/
  27403. + if (val)
  27404. + dwc_otg_set_param_otg_ver(core_if, 1);
  27405. +
  27406. + return retval;
  27407. +}
  27408. +
  27409. +int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if)
  27410. +{
  27411. + return core_if->core_params->adp_supp_enable;
  27412. +}
  27413. +
  27414. +int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if, int32_t val)
  27415. +{
  27416. + int retval = 0;
  27417. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  27418. + DWC_WARN("`%d' invalid for parameter `ic_usb_cap'\n", val);
  27419. + DWC_WARN("ic_usb_cap must be 0 or 1\n");
  27420. + return -DWC_E_INVALID;
  27421. + }
  27422. +
  27423. + if (val && (core_if->hwcfg2.b.otg_enable_ic_usb == 0)) {
  27424. + if (dwc_otg_param_initialized(core_if->core_params->ic_usb_cap)) {
  27425. + DWC_ERROR
  27426. + ("%d invalid for parameter ic_usb_cap. Check HW configuration.\n",
  27427. + val);
  27428. + }
  27429. + retval = -DWC_E_INVALID;
  27430. + val = 0;
  27431. + }
  27432. + core_if->core_params->ic_usb_cap = val;
  27433. + return retval;
  27434. +}
  27435. +
  27436. +int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if)
  27437. +{
  27438. + return core_if->core_params->ic_usb_cap;
  27439. +}
  27440. +
  27441. +int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if, int32_t val)
  27442. +{
  27443. + int retval = 0;
  27444. + int valid = 1;
  27445. +
  27446. + if (DWC_OTG_PARAM_TEST(val, 0, 3)) {
  27447. + DWC_WARN("`%d' invalid for parameter `ahb_thr_ratio'\n", val);
  27448. + DWC_WARN("ahb_thr_ratio must be 0 - 3\n");
  27449. + return -DWC_E_INVALID;
  27450. + }
  27451. +
  27452. + if (val
  27453. + && (core_if->snpsid < OTG_CORE_REV_2_81a
  27454. + || !dwc_otg_get_param_thr_ctl(core_if))) {
  27455. + valid = 0;
  27456. + } else if (val
  27457. + && ((dwc_otg_get_param_tx_thr_length(core_if) / (1 << val)) <
  27458. + 4)) {
  27459. + valid = 0;
  27460. + }
  27461. + if (valid == 0) {
  27462. + if (dwc_otg_param_initialized
  27463. + (core_if->core_params->ahb_thr_ratio)) {
  27464. + DWC_ERROR
  27465. + ("%d invalid for parameter ahb_thr_ratio. Check HW configuration.\n",
  27466. + val);
  27467. + }
  27468. + retval = -DWC_E_INVALID;
  27469. + val = 0;
  27470. + }
  27471. +
  27472. + core_if->core_params->ahb_thr_ratio = val;
  27473. + return retval;
  27474. +}
  27475. +
  27476. +int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if)
  27477. +{
  27478. + return core_if->core_params->ahb_thr_ratio;
  27479. +}
  27480. +
  27481. +int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, int32_t val)
  27482. +{
  27483. + int retval = 0;
  27484. + int valid = 1;
  27485. + hwcfg4_data_t hwcfg4 = {.d32 = 0 };
  27486. + hwcfg4.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4);
  27487. +
  27488. + if (DWC_OTG_PARAM_TEST(val, 0, 3)) {
  27489. + DWC_WARN("`%d' invalid for parameter `power_down'\n", val);
  27490. + DWC_WARN("power_down must be 0 - 2\n");
  27491. + return -DWC_E_INVALID;
  27492. + }
  27493. +
  27494. + if ((val == 2) && (core_if->snpsid < OTG_CORE_REV_2_91a)) {
  27495. + valid = 0;
  27496. + }
  27497. + if ((val == 3)
  27498. + && ((core_if->snpsid < OTG_CORE_REV_3_00a)
  27499. + || (hwcfg4.b.xhiber == 0))) {
  27500. + valid = 0;
  27501. + }
  27502. + if (valid == 0) {
  27503. + if (dwc_otg_param_initialized(core_if->core_params->power_down)) {
  27504. + DWC_ERROR
  27505. + ("%d invalid for parameter power_down. Check HW configuration.\n",
  27506. + val);
  27507. + }
  27508. + retval = -DWC_E_INVALID;
  27509. + val = 0;
  27510. + }
  27511. + core_if->core_params->power_down = val;
  27512. + return retval;
  27513. +}
  27514. +
  27515. +int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if)
  27516. +{
  27517. + return core_if->core_params->power_down;
  27518. +}
  27519. +
  27520. +int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if, int32_t val)
  27521. +{
  27522. + int retval = 0;
  27523. + int valid = 1;
  27524. +
  27525. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  27526. + DWC_WARN("`%d' invalid for parameter `reload_ctl'\n", val);
  27527. + DWC_WARN("reload_ctl must be 0 or 1\n");
  27528. + return -DWC_E_INVALID;
  27529. + }
  27530. +
  27531. + if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_92a)) {
  27532. + valid = 0;
  27533. + }
  27534. + if (valid == 0) {
  27535. + if (dwc_otg_param_initialized(core_if->core_params->reload_ctl)) {
  27536. + DWC_ERROR("%d invalid for parameter reload_ctl."
  27537. + "Check HW configuration.\n", val);
  27538. + }
  27539. + retval = -DWC_E_INVALID;
  27540. + val = 0;
  27541. + }
  27542. + core_if->core_params->reload_ctl = val;
  27543. + return retval;
  27544. +}
  27545. +
  27546. +int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if)
  27547. +{
  27548. + return core_if->core_params->reload_ctl;
  27549. +}
  27550. +
  27551. +int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if, int32_t val)
  27552. +{
  27553. + int retval = 0;
  27554. + int valid = 1;
  27555. +
  27556. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  27557. + DWC_WARN("`%d' invalid for parameter `dev_out_nak'\n", val);
  27558. + DWC_WARN("dev_out_nak must be 0 or 1\n");
  27559. + return -DWC_E_INVALID;
  27560. + }
  27561. +
  27562. + if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_93a) ||
  27563. + !(core_if->core_params->dma_desc_enable))) {
  27564. + valid = 0;
  27565. + }
  27566. + if (valid == 0) {
  27567. + if (dwc_otg_param_initialized(core_if->core_params->dev_out_nak)) {
  27568. + DWC_ERROR("%d invalid for parameter dev_out_nak."
  27569. + "Check HW configuration.\n", val);
  27570. + }
  27571. + retval = -DWC_E_INVALID;
  27572. + val = 0;
  27573. + }
  27574. + core_if->core_params->dev_out_nak = val;
  27575. + return retval;
  27576. +}
  27577. +
  27578. +int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if)
  27579. +{
  27580. + return core_if->core_params->dev_out_nak;
  27581. +}
  27582. +
  27583. +int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if, int32_t val)
  27584. +{
  27585. + int retval = 0;
  27586. + int valid = 1;
  27587. +
  27588. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  27589. + DWC_WARN("`%d' invalid for parameter `cont_on_bna'\n", val);
  27590. + DWC_WARN("cont_on_bna must be 0 or 1\n");
  27591. + return -DWC_E_INVALID;
  27592. + }
  27593. +
  27594. + if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_94a) ||
  27595. + !(core_if->core_params->dma_desc_enable))) {
  27596. + valid = 0;
  27597. + }
  27598. + if (valid == 0) {
  27599. + if (dwc_otg_param_initialized(core_if->core_params->cont_on_bna)) {
  27600. + DWC_ERROR("%d invalid for parameter cont_on_bna."
  27601. + "Check HW configuration.\n", val);
  27602. + }
  27603. + retval = -DWC_E_INVALID;
  27604. + val = 0;
  27605. + }
  27606. + core_if->core_params->cont_on_bna = val;
  27607. + return retval;
  27608. +}
  27609. +
  27610. +int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if)
  27611. +{
  27612. + return core_if->core_params->cont_on_bna;
  27613. +}
  27614. +
  27615. +int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if, int32_t val)
  27616. +{
  27617. + int retval = 0;
  27618. + int valid = 1;
  27619. +
  27620. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  27621. + DWC_WARN("`%d' invalid for parameter `ahb_single'\n", val);
  27622. + DWC_WARN("ahb_single must be 0 or 1\n");
  27623. + return -DWC_E_INVALID;
  27624. + }
  27625. +
  27626. + if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_94a)) {
  27627. + valid = 0;
  27628. + }
  27629. + if (valid == 0) {
  27630. + if (dwc_otg_param_initialized(core_if->core_params->ahb_single)) {
  27631. + DWC_ERROR("%d invalid for parameter ahb_single."
  27632. + "Check HW configuration.\n", val);
  27633. + }
  27634. + retval = -DWC_E_INVALID;
  27635. + val = 0;
  27636. + }
  27637. + core_if->core_params->ahb_single = val;
  27638. + return retval;
  27639. +}
  27640. +
  27641. +int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if)
  27642. +{
  27643. + return core_if->core_params->ahb_single;
  27644. +}
  27645. +
  27646. +int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val)
  27647. +{
  27648. + int retval = 0;
  27649. +
  27650. + if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
  27651. + DWC_WARN("`%d' invalid for parameter `otg_ver'\n", val);
  27652. + DWC_WARN
  27653. + ("otg_ver must be 0(for OTG 1.3 support) or 1(for OTG 2.0 support)\n");
  27654. + return -DWC_E_INVALID;
  27655. + }
  27656. +
  27657. + core_if->core_params->otg_ver = val;
  27658. + return retval;
  27659. +}
  27660. +
  27661. +int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if)
  27662. +{
  27663. + return core_if->core_params->otg_ver;
  27664. +}
  27665. +
  27666. +uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if)
  27667. +{
  27668. + gotgctl_data_t otgctl;
  27669. + otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
  27670. + return otgctl.b.hstnegscs;
  27671. +}
  27672. +
  27673. +uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if)
  27674. +{
  27675. + gotgctl_data_t otgctl;
  27676. + otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
  27677. + return otgctl.b.sesreqscs;
  27678. +}
  27679. +
  27680. +void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val)
  27681. +{
  27682. + if(core_if->otg_ver == 0) {
  27683. + gotgctl_data_t otgctl;
  27684. + otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
  27685. + otgctl.b.hnpreq = val;
  27686. + DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, otgctl.d32);
  27687. + } else {
  27688. + core_if->otg_sts = val;
  27689. + }
  27690. +}
  27691. +
  27692. +uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if)
  27693. +{
  27694. + return core_if->snpsid;
  27695. +}
  27696. +
  27697. +uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if)
  27698. +{
  27699. + gintsts_data_t gintsts;
  27700. + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
  27701. + return gintsts.b.curmode;
  27702. +}
  27703. +
  27704. +uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if)
  27705. +{
  27706. + gusbcfg_data_t usbcfg;
  27707. + usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
  27708. + return usbcfg.b.hnpcap;
  27709. +}
  27710. +
  27711. +void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val)
  27712. +{
  27713. + gusbcfg_data_t usbcfg;
  27714. + usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
  27715. + usbcfg.b.hnpcap = val;
  27716. + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
  27717. +}
  27718. +
  27719. +uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if)
  27720. +{
  27721. + gusbcfg_data_t usbcfg;
  27722. + usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
  27723. + return usbcfg.b.srpcap;
  27724. +}
  27725. +
  27726. +void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val)
  27727. +{
  27728. + gusbcfg_data_t usbcfg;
  27729. + usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
  27730. + usbcfg.b.srpcap = val;
  27731. + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
  27732. +}
  27733. +
  27734. +uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if)
  27735. +{
  27736. + dcfg_data_t dcfg;
  27737. + /* originally: dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); */
  27738. +
  27739. + dcfg.d32 = -1; //GRAYG
  27740. + DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)\n", __func__, core_if);
  27741. + if (NULL == core_if)
  27742. + DWC_ERROR("reg request with NULL core_if\n");
  27743. + DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)\n", __func__,
  27744. + core_if, core_if->dev_if);
  27745. + if (NULL == core_if->dev_if)
  27746. + DWC_ERROR("reg request with NULL dev_if\n");
  27747. + DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)->"
  27748. + "dev_global_regs(%p)\n", __func__,
  27749. + core_if, core_if->dev_if,
  27750. + core_if->dev_if->dev_global_regs);
  27751. + if (NULL == core_if->dev_if->dev_global_regs)
  27752. + DWC_ERROR("reg request with NULL dev_global_regs\n");
  27753. + else {
  27754. + DWC_DEBUGPL(DBG_CILV, "%s - &core_if(%p)->dev_if(%p)->"
  27755. + "dev_global_regs(%p)->dcfg = %p\n", __func__,
  27756. + core_if, core_if->dev_if,
  27757. + core_if->dev_if->dev_global_regs,
  27758. + &core_if->dev_if->dev_global_regs->dcfg);
  27759. + dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
  27760. + }
  27761. + return dcfg.b.devspd;
  27762. +}
  27763. +
  27764. +void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val)
  27765. +{
  27766. + dcfg_data_t dcfg;
  27767. + dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
  27768. + dcfg.b.devspd = val;
  27769. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
  27770. +}
  27771. +
  27772. +uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if)
  27773. +{
  27774. + hprt0_data_t hprt0;
  27775. + hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
  27776. + return hprt0.b.prtconnsts;
  27777. +}
  27778. +
  27779. +uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if)
  27780. +{
  27781. + dsts_data_t dsts;
  27782. + dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
  27783. + return dsts.b.enumspd;
  27784. +}
  27785. +
  27786. +uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if)
  27787. +{
  27788. + hprt0_data_t hprt0;
  27789. + hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
  27790. + return hprt0.b.prtpwr;
  27791. +
  27792. +}
  27793. +
  27794. +uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if)
  27795. +{
  27796. + return core_if->hibernation_suspend;
  27797. +}
  27798. +
  27799. +void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val)
  27800. +{
  27801. + hprt0_data_t hprt0;
  27802. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  27803. + hprt0.b.prtpwr = val;
  27804. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  27805. +}
  27806. +
  27807. +uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if)
  27808. +{
  27809. + hprt0_data_t hprt0;
  27810. + hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
  27811. + return hprt0.b.prtsusp;
  27812. +
  27813. +}
  27814. +
  27815. +void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val)
  27816. +{
  27817. + hprt0_data_t hprt0;
  27818. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  27819. + hprt0.b.prtsusp = val;
  27820. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  27821. +}
  27822. +
  27823. +uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if)
  27824. +{
  27825. + hfir_data_t hfir;
  27826. + hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);
  27827. + return hfir.b.frint;
  27828. +
  27829. +}
  27830. +
  27831. +void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val)
  27832. +{
  27833. + hfir_data_t hfir;
  27834. + uint32_t fram_int;
  27835. + fram_int = calc_frame_interval(core_if);
  27836. + hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir);
  27837. + if (!core_if->core_params->reload_ctl) {
  27838. + DWC_WARN("\nCannot reload HFIR register.HFIR.HFIRRldCtrl bit is"
  27839. + "not set to 1.\nShould load driver with reload_ctl=1"
  27840. + " module parameter\n");
  27841. + return;
  27842. + }
  27843. + switch (fram_int) {
  27844. + case 3750:
  27845. + if ((val < 3350) || (val > 4150)) {
  27846. + DWC_WARN("HFIR interval for HS core and 30 MHz"
  27847. + "clock freq should be from 3350 to 4150\n");
  27848. + return;
  27849. + }
  27850. + break;
  27851. + case 30000:
  27852. + if ((val < 26820) || (val > 33180)) {
  27853. + DWC_WARN("HFIR interval for FS/LS core and 30 MHz"
  27854. + "clock freq should be from 26820 to 33180\n");
  27855. + return;
  27856. + }
  27857. + break;
  27858. + case 6000:
  27859. + if ((val < 5360) || (val > 6640)) {
  27860. + DWC_WARN("HFIR interval for HS core and 48 MHz"
  27861. + "clock freq should be from 5360 to 6640\n");
  27862. + return;
  27863. + }
  27864. + break;
  27865. + case 48000:
  27866. + if ((val < 42912) || (val > 53088)) {
  27867. + DWC_WARN("HFIR interval for FS/LS core and 48 MHz"
  27868. + "clock freq should be from 42912 to 53088\n");
  27869. + return;
  27870. + }
  27871. + break;
  27872. + case 7500:
  27873. + if ((val < 6700) || (val > 8300)) {
  27874. + DWC_WARN("HFIR interval for HS core and 60 MHz"
  27875. + "clock freq should be from 6700 to 8300\n");
  27876. + return;
  27877. + }
  27878. + break;
  27879. + case 60000:
  27880. + if ((val < 53640) || (val > 65536)) {
  27881. + DWC_WARN("HFIR interval for FS/LS core and 60 MHz"
  27882. + "clock freq should be from 53640 to 65536\n");
  27883. + return;
  27884. + }
  27885. + break;
  27886. + default:
  27887. + DWC_WARN("Unknown frame interval\n");
  27888. + return;
  27889. + break;
  27890. +
  27891. + }
  27892. + hfir.b.frint = val;
  27893. + DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hfir.d32);
  27894. +}
  27895. +
  27896. +uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if)
  27897. +{
  27898. + hcfg_data_t hcfg;
  27899. + hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
  27900. + return hcfg.b.modechtimen;
  27901. +
  27902. +}
  27903. +
  27904. +void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val)
  27905. +{
  27906. + hcfg_data_t hcfg;
  27907. + hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg);
  27908. + hcfg.b.modechtimen = val;
  27909. + DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32);
  27910. +}
  27911. +
  27912. +void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val)
  27913. +{
  27914. + hprt0_data_t hprt0;
  27915. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  27916. + hprt0.b.prtres = val;
  27917. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  27918. +}
  27919. +
  27920. +uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if)
  27921. +{
  27922. + dctl_data_t dctl;
  27923. + dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
  27924. + return dctl.b.rmtwkupsig;
  27925. +}
  27926. +
  27927. +uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if)
  27928. +{
  27929. + glpmcfg_data_t lpmcfg;
  27930. + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
  27931. +
  27932. + DWC_ASSERT(!
  27933. + ((core_if->lx_state == DWC_OTG_L1) ^ lpmcfg.b.prt_sleep_sts),
  27934. + "lx_state = %d, lmpcfg.prt_sleep_sts = %d\n",
  27935. + core_if->lx_state, lpmcfg.b.prt_sleep_sts);
  27936. +
  27937. + return lpmcfg.b.prt_sleep_sts;
  27938. +}
  27939. +
  27940. +uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if)
  27941. +{
  27942. + glpmcfg_data_t lpmcfg;
  27943. + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
  27944. + return lpmcfg.b.rem_wkup_en;
  27945. +}
  27946. +
  27947. +uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if)
  27948. +{
  27949. + glpmcfg_data_t lpmcfg;
  27950. + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
  27951. + return lpmcfg.b.appl_resp;
  27952. +}
  27953. +
  27954. +void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val)
  27955. +{
  27956. + glpmcfg_data_t lpmcfg;
  27957. + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
  27958. + lpmcfg.b.appl_resp = val;
  27959. + DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
  27960. +}
  27961. +
  27962. +uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if)
  27963. +{
  27964. + glpmcfg_data_t lpmcfg;
  27965. + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
  27966. + return lpmcfg.b.hsic_connect;
  27967. +}
  27968. +
  27969. +void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val)
  27970. +{
  27971. + glpmcfg_data_t lpmcfg;
  27972. + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
  27973. + lpmcfg.b.hsic_connect = val;
  27974. + DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
  27975. +}
  27976. +
  27977. +uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if)
  27978. +{
  27979. + glpmcfg_data_t lpmcfg;
  27980. + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
  27981. + return lpmcfg.b.inv_sel_hsic;
  27982. +
  27983. +}
  27984. +
  27985. +void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val)
  27986. +{
  27987. + glpmcfg_data_t lpmcfg;
  27988. + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
  27989. + lpmcfg.b.inv_sel_hsic = val;
  27990. + DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
  27991. +}
  27992. +
  27993. +uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if)
  27994. +{
  27995. + return DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
  27996. +}
  27997. +
  27998. +void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val)
  27999. +{
  28000. + DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, val);
  28001. +}
  28002. +
  28003. +uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if)
  28004. +{
  28005. + return DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
  28006. +}
  28007. +
  28008. +void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val)
  28009. +{
  28010. + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, val);
  28011. +}
  28012. +
  28013. +uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if)
  28014. +{
  28015. + return DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
  28016. +}
  28017. +
  28018. +void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val)
  28019. +{
  28020. + DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, val);
  28021. +}
  28022. +
  28023. +uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if)
  28024. +{
  28025. + return DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz);
  28026. +}
  28027. +
  28028. +void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val)
  28029. +{
  28030. + DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, val);
  28031. +}
  28032. +
  28033. +uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if)
  28034. +{
  28035. + return DWC_READ_REG32(&core_if->core_global_regs->gpvndctl);
  28036. +}
  28037. +
  28038. +void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val)
  28039. +{
  28040. + DWC_WRITE_REG32(&core_if->core_global_regs->gpvndctl, val);
  28041. +}
  28042. +
  28043. +uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if)
  28044. +{
  28045. + return DWC_READ_REG32(&core_if->core_global_regs->ggpio);
  28046. +}
  28047. +
  28048. +void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val)
  28049. +{
  28050. + DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, val);
  28051. +}
  28052. +
  28053. +uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if)
  28054. +{
  28055. + return DWC_READ_REG32(core_if->host_if->hprt0);
  28056. +
  28057. +}
  28058. +
  28059. +void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val)
  28060. +{
  28061. + DWC_WRITE_REG32(core_if->host_if->hprt0, val);
  28062. +}
  28063. +
  28064. +uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if)
  28065. +{
  28066. + return DWC_READ_REG32(&core_if->core_global_regs->guid);
  28067. +}
  28068. +
  28069. +void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val)
  28070. +{
  28071. + DWC_WRITE_REG32(&core_if->core_global_regs->guid, val);
  28072. +}
  28073. +
  28074. +uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if)
  28075. +{
  28076. + return DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz);
  28077. +}
  28078. +
  28079. +uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if)
  28080. +{
  28081. + return ((core_if->otg_ver == 1) ? (uint16_t)0x0200 : (uint16_t)0x0103);
  28082. +}
  28083. +
  28084. +/**
  28085. + * Start the SRP timer to detect when the SRP does not complete within
  28086. + * 6 seconds.
  28087. + *
  28088. + * @param core_if the pointer to core_if strucure.
  28089. + */
  28090. +void dwc_otg_pcd_start_srp_timer(dwc_otg_core_if_t * core_if)
  28091. +{
  28092. + core_if->srp_timer_started = 1;
  28093. + DWC_TIMER_SCHEDULE(core_if->srp_timer, 6000 /* 6 secs */ );
  28094. +}
  28095. +
  28096. +void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if)
  28097. +{
  28098. + uint32_t *addr = (uint32_t *) & (core_if->core_global_regs->gotgctl);
  28099. + gotgctl_data_t mem;
  28100. + gotgctl_data_t val;
  28101. +
  28102. + val.d32 = DWC_READ_REG32(addr);
  28103. + if (val.b.sesreq) {
  28104. + DWC_ERROR("Session Request Already active!\n");
  28105. + return;
  28106. + }
  28107. +
  28108. + DWC_INFO("Session Request Initated\n"); //NOTICE
  28109. + mem.d32 = DWC_READ_REG32(addr);
  28110. + mem.b.sesreq = 1;
  28111. + DWC_WRITE_REG32(addr, mem.d32);
  28112. +
  28113. + /* Start the SRP timer */
  28114. + dwc_otg_pcd_start_srp_timer(core_if);
  28115. + return;
  28116. +}
  28117. --- /dev/null
  28118. +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.h
  28119. @@ -0,0 +1,1464 @@
  28120. +/* ==========================================================================
  28121. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $
  28122. + * $Revision: #123 $
  28123. + * $Date: 2012/08/10 $
  28124. + * $Change: 2047372 $
  28125. + *
  28126. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  28127. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  28128. + * otherwise expressly agreed to in writing between Synopsys and you.
  28129. + *
  28130. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  28131. + * any End User Software License Agreement or Agreement for Licensed Product
  28132. + * with Synopsys or any supplement thereto. You are permitted to use and
  28133. + * redistribute this Software in source and binary forms, with or without
  28134. + * modification, provided that redistributions of source code must retain this
  28135. + * notice. You may not view, use, disclose, copy or distribute this file or
  28136. + * any information contained herein except pursuant to this license grant from
  28137. + * Synopsys. If you do not agree with this notice, including the disclaimer
  28138. + * below, then you are not authorized to use the Software.
  28139. + *
  28140. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  28141. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28142. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28143. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  28144. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  28145. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  28146. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  28147. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28148. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28149. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  28150. + * DAMAGE.
  28151. + * ========================================================================== */
  28152. +
  28153. +#if !defined(__DWC_CIL_H__)
  28154. +#define __DWC_CIL_H__
  28155. +
  28156. +#include "dwc_list.h"
  28157. +#include "dwc_otg_dbg.h"
  28158. +#include "dwc_otg_regs.h"
  28159. +
  28160. +#include "dwc_otg_core_if.h"
  28161. +#include "dwc_otg_adp.h"
  28162. +
  28163. +/**
  28164. + * @file
  28165. + * This file contains the interface to the Core Interface Layer.
  28166. + */
  28167. +
  28168. +#ifdef DWC_UTE_CFI
  28169. +
  28170. +#define MAX_DMA_DESCS_PER_EP 256
  28171. +
  28172. +/**
  28173. + * Enumeration for the data buffer mode
  28174. + */
  28175. +typedef enum _data_buffer_mode {
  28176. + BM_STANDARD = 0, /* data buffer is in normal mode */
  28177. + BM_SG = 1, /* data buffer uses the scatter/gather mode */
  28178. + BM_CONCAT = 2, /* data buffer uses the concatenation mode */
  28179. + BM_CIRCULAR = 3, /* data buffer uses the circular DMA mode */
  28180. + BM_ALIGN = 4 /* data buffer is in buffer alignment mode */
  28181. +} data_buffer_mode_e;
  28182. +#endif //DWC_UTE_CFI
  28183. +
  28184. +/** Macros defined for DWC OTG HW Release version */
  28185. +
  28186. +#define OTG_CORE_REV_2_60a 0x4F54260A
  28187. +#define OTG_CORE_REV_2_71a 0x4F54271A
  28188. +#define OTG_CORE_REV_2_72a 0x4F54272A
  28189. +#define OTG_CORE_REV_2_80a 0x4F54280A
  28190. +#define OTG_CORE_REV_2_81a 0x4F54281A
  28191. +#define OTG_CORE_REV_2_90a 0x4F54290A
  28192. +#define OTG_CORE_REV_2_91a 0x4F54291A
  28193. +#define OTG_CORE_REV_2_92a 0x4F54292A
  28194. +#define OTG_CORE_REV_2_93a 0x4F54293A
  28195. +#define OTG_CORE_REV_2_94a 0x4F54294A
  28196. +#define OTG_CORE_REV_3_00a 0x4F54300A
  28197. +
  28198. +/**
  28199. + * Information for each ISOC packet.
  28200. + */
  28201. +typedef struct iso_pkt_info {
  28202. + uint32_t offset;
  28203. + uint32_t length;
  28204. + int32_t status;
  28205. +} iso_pkt_info_t;
  28206. +
  28207. +/**
  28208. + * The <code>dwc_ep</code> structure represents the state of a single
  28209. + * endpoint when acting in device mode. It contains the data items
  28210. + * needed for an endpoint to be activated and transfer packets.
  28211. + */
  28212. +typedef struct dwc_ep {
  28213. + /** EP number used for register address lookup */
  28214. + uint8_t num;
  28215. + /** EP direction 0 = OUT */
  28216. + unsigned is_in:1;
  28217. + /** EP active. */
  28218. + unsigned active:1;
  28219. +
  28220. + /**
  28221. + * Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic
  28222. + * Tx FIFO. If dedicated Tx FIFOs are enabled Tx FIFO # FOR IN EPs*/
  28223. + unsigned tx_fifo_num:4;
  28224. + /** EP type: 0 - Control, 1 - ISOC, 2 - BULK, 3 - INTR */
  28225. + unsigned type:2;
  28226. +#define DWC_OTG_EP_TYPE_CONTROL 0
  28227. +#define DWC_OTG_EP_TYPE_ISOC 1
  28228. +#define DWC_OTG_EP_TYPE_BULK 2
  28229. +#define DWC_OTG_EP_TYPE_INTR 3
  28230. +
  28231. + /** DATA start PID for INTR and BULK EP */
  28232. + unsigned data_pid_start:1;
  28233. + /** Frame (even/odd) for ISOC EP */
  28234. + unsigned even_odd_frame:1;
  28235. + /** Max Packet bytes */
  28236. + unsigned maxpacket:11;
  28237. +
  28238. + /** Max Transfer size */
  28239. + uint32_t maxxfer;
  28240. +
  28241. + /** @name Transfer state */
  28242. + /** @{ */
  28243. +
  28244. + /**
  28245. + * Pointer to the beginning of the transfer buffer -- do not modify
  28246. + * during transfer.
  28247. + */
  28248. +
  28249. + dwc_dma_t dma_addr;
  28250. +
  28251. + dwc_dma_t dma_desc_addr;
  28252. + dwc_otg_dev_dma_desc_t *desc_addr;
  28253. +
  28254. + uint8_t *start_xfer_buff;
  28255. + /** pointer to the transfer buffer */
  28256. + uint8_t *xfer_buff;
  28257. + /** Number of bytes to transfer */
  28258. + unsigned xfer_len:19;
  28259. + /** Number of bytes transferred. */
  28260. + unsigned xfer_count:19;
  28261. + /** Sent ZLP */
  28262. + unsigned sent_zlp:1;
  28263. + /** Total len for control transfer */
  28264. + unsigned total_len:19;
  28265. +
  28266. + /** stall clear flag */
  28267. + unsigned stall_clear_flag:1;
  28268. +
  28269. + /** SETUP pkt cnt rollover flag for EP0 out*/
  28270. + unsigned stp_rollover;
  28271. +
  28272. +#ifdef DWC_UTE_CFI
  28273. + /* The buffer mode */
  28274. + data_buffer_mode_e buff_mode;
  28275. +
  28276. + /* The chain of DMA descriptors.
  28277. + * MAX_DMA_DESCS_PER_EP will be allocated for each active EP.
  28278. + */
  28279. + dwc_otg_dma_desc_t *descs;
  28280. +
  28281. + /* The DMA address of the descriptors chain start */
  28282. + dma_addr_t descs_dma_addr;
  28283. + /** This variable stores the length of the last enqueued request */
  28284. + uint32_t cfi_req_len;
  28285. +#endif //DWC_UTE_CFI
  28286. +
  28287. +/** Max DMA Descriptor count for any EP */
  28288. +#define MAX_DMA_DESC_CNT 256
  28289. + /** Allocated DMA Desc count */
  28290. + uint32_t desc_cnt;
  28291. +
  28292. + /** bInterval */
  28293. + uint32_t bInterval;
  28294. + /** Next frame num to setup next ISOC transfer */
  28295. + uint32_t frame_num;
  28296. + /** Indicates SOF number overrun in DSTS */
  28297. + uint8_t frm_overrun;
  28298. +
  28299. +#ifdef DWC_UTE_PER_IO
  28300. + /** Next frame num for which will be setup DMA Desc */
  28301. + uint32_t xiso_frame_num;
  28302. + /** bInterval */
  28303. + uint32_t xiso_bInterval;
  28304. + /** Count of currently active transfers - shall be either 0 or 1 */
  28305. + int xiso_active_xfers;
  28306. + int xiso_queued_xfers;
  28307. +#endif
  28308. +#ifdef DWC_EN_ISOC
  28309. + /**
  28310. + * Variables specific for ISOC EPs
  28311. + *
  28312. + */
  28313. + /** DMA addresses of ISOC buffers */
  28314. + dwc_dma_t dma_addr0;
  28315. + dwc_dma_t dma_addr1;
  28316. +
  28317. + dwc_dma_t iso_dma_desc_addr;
  28318. + dwc_otg_dev_dma_desc_t *iso_desc_addr;
  28319. +
  28320. + /** pointer to the transfer buffers */
  28321. + uint8_t *xfer_buff0;
  28322. + uint8_t *xfer_buff1;
  28323. +
  28324. + /** number of ISOC Buffer is processing */
  28325. + uint32_t proc_buf_num;
  28326. + /** Interval of ISOC Buffer processing */
  28327. + uint32_t buf_proc_intrvl;
  28328. + /** Data size for regular frame */
  28329. + uint32_t data_per_frame;
  28330. +
  28331. + /* todo - pattern data support is to be implemented in the future */
  28332. + /** Data size for pattern frame */
  28333. + uint32_t data_pattern_frame;
  28334. + /** Frame number of pattern data */
  28335. + uint32_t sync_frame;
  28336. +
  28337. + /** bInterval */
  28338. + uint32_t bInterval;
  28339. + /** ISO Packet number per frame */
  28340. + uint32_t pkt_per_frm;
  28341. + /** Next frame num for which will be setup DMA Desc */
  28342. + uint32_t next_frame;
  28343. + /** Number of packets per buffer processing */
  28344. + uint32_t pkt_cnt;
  28345. + /** Info for all isoc packets */
  28346. + iso_pkt_info_t *pkt_info;
  28347. + /** current pkt number */
  28348. + uint32_t cur_pkt;
  28349. + /** current pkt number */
  28350. + uint8_t *cur_pkt_addr;
  28351. + /** current pkt number */
  28352. + uint32_t cur_pkt_dma_addr;
  28353. +#endif /* DWC_EN_ISOC */
  28354. +
  28355. +/** @} */
  28356. +} dwc_ep_t;
  28357. +
  28358. +/*
  28359. + * Reasons for halting a host channel.
  28360. + */
  28361. +typedef enum dwc_otg_halt_status {
  28362. + DWC_OTG_HC_XFER_NO_HALT_STATUS,
  28363. + DWC_OTG_HC_XFER_COMPLETE,
  28364. + DWC_OTG_HC_XFER_URB_COMPLETE,
  28365. + DWC_OTG_HC_XFER_ACK,
  28366. + DWC_OTG_HC_XFER_NAK,
  28367. + DWC_OTG_HC_XFER_NYET,
  28368. + DWC_OTG_HC_XFER_STALL,
  28369. + DWC_OTG_HC_XFER_XACT_ERR,
  28370. + DWC_OTG_HC_XFER_FRAME_OVERRUN,
  28371. + DWC_OTG_HC_XFER_BABBLE_ERR,
  28372. + DWC_OTG_HC_XFER_DATA_TOGGLE_ERR,
  28373. + DWC_OTG_HC_XFER_AHB_ERR,
  28374. + DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE,
  28375. + DWC_OTG_HC_XFER_URB_DEQUEUE
  28376. +} dwc_otg_halt_status_e;
  28377. +
  28378. +/**
  28379. + * Host channel descriptor. This structure represents the state of a single
  28380. + * host channel when acting in host mode. It contains the data items needed to
  28381. + * transfer packets to an endpoint via a host channel.
  28382. + */
  28383. +typedef struct dwc_hc {
  28384. + /** Host channel number used for register address lookup */
  28385. + uint8_t hc_num;
  28386. +
  28387. + /** Device to access */
  28388. + unsigned dev_addr:7;
  28389. +
  28390. + /** EP to access */
  28391. + unsigned ep_num:4;
  28392. +
  28393. + /** EP direction. 0: OUT, 1: IN */
  28394. + unsigned ep_is_in:1;
  28395. +
  28396. + /**
  28397. + * EP speed.
  28398. + * One of the following values:
  28399. + * - DWC_OTG_EP_SPEED_LOW
  28400. + * - DWC_OTG_EP_SPEED_FULL
  28401. + * - DWC_OTG_EP_SPEED_HIGH
  28402. + */
  28403. + unsigned speed:2;
  28404. +#define DWC_OTG_EP_SPEED_LOW 0
  28405. +#define DWC_OTG_EP_SPEED_FULL 1
  28406. +#define DWC_OTG_EP_SPEED_HIGH 2
  28407. +
  28408. + /**
  28409. + * Endpoint type.
  28410. + * One of the following values:
  28411. + * - DWC_OTG_EP_TYPE_CONTROL: 0
  28412. + * - DWC_OTG_EP_TYPE_ISOC: 1
  28413. + * - DWC_OTG_EP_TYPE_BULK: 2
  28414. + * - DWC_OTG_EP_TYPE_INTR: 3
  28415. + */
  28416. + unsigned ep_type:2;
  28417. +
  28418. + /** Max packet size in bytes */
  28419. + unsigned max_packet:11;
  28420. +
  28421. + /**
  28422. + * PID for initial transaction.
  28423. + * 0: DATA0,<br>
  28424. + * 1: DATA2,<br>
  28425. + * 2: DATA1,<br>
  28426. + * 3: MDATA (non-Control EP),
  28427. + * SETUP (Control EP)
  28428. + */
  28429. + unsigned data_pid_start:2;
  28430. +#define DWC_OTG_HC_PID_DATA0 0
  28431. +#define DWC_OTG_HC_PID_DATA2 1
  28432. +#define DWC_OTG_HC_PID_DATA1 2
  28433. +#define DWC_OTG_HC_PID_MDATA 3
  28434. +#define DWC_OTG_HC_PID_SETUP 3
  28435. +
  28436. + /** Number of periodic transactions per (micro)frame */
  28437. + unsigned multi_count:2;
  28438. +
  28439. + /** @name Transfer State */
  28440. + /** @{ */
  28441. +
  28442. + /** Pointer to the current transfer buffer position. */
  28443. + uint8_t *xfer_buff;
  28444. + /**
  28445. + * In Buffer DMA mode this buffer will be used
  28446. + * if xfer_buff is not DWORD aligned.
  28447. + */
  28448. + dwc_dma_t align_buff;
  28449. + /** Total number of bytes to transfer. */
  28450. + uint32_t xfer_len;
  28451. + /** Number of bytes transferred so far. */
  28452. + uint32_t xfer_count;
  28453. + /** Packet count at start of transfer.*/
  28454. + uint16_t start_pkt_count;
  28455. +
  28456. + /**
  28457. + * Flag to indicate whether the transfer has been started. Set to 1 if
  28458. + * it has been started, 0 otherwise.
  28459. + */
  28460. + uint8_t xfer_started;
  28461. +
  28462. + /**
  28463. + * Set to 1 to indicate that a PING request should be issued on this
  28464. + * channel. If 0, process normally.
  28465. + */
  28466. + uint8_t do_ping;
  28467. +
  28468. + /**
  28469. + * Set to 1 to indicate that the error count for this transaction is
  28470. + * non-zero. Set to 0 if the error count is 0.
  28471. + */
  28472. + uint8_t error_state;
  28473. +
  28474. + /**
  28475. + * Set to 1 to indicate that this channel should be halted the next
  28476. + * time a request is queued for the channel. This is necessary in
  28477. + * slave mode if no request queue space is available when an attempt
  28478. + * is made to halt the channel.
  28479. + */
  28480. + uint8_t halt_on_queue;
  28481. +
  28482. + /**
  28483. + * Set to 1 if the host channel has been halted, but the core is not
  28484. + * finished flushing queued requests. Otherwise 0.
  28485. + */
  28486. + uint8_t halt_pending;
  28487. +
  28488. + /**
  28489. + * Reason for halting the host channel.
  28490. + */
  28491. + dwc_otg_halt_status_e halt_status;
  28492. +
  28493. + /*
  28494. + * Split settings for the host channel
  28495. + */
  28496. + uint8_t do_split; /**< Enable split for the channel */
  28497. + uint8_t complete_split; /**< Enable complete split */
  28498. + uint8_t hub_addr; /**< Address of high speed hub */
  28499. +
  28500. + uint8_t port_addr; /**< Port of the low/full speed device */
  28501. + /** Split transaction position
  28502. + * One of the following values:
  28503. + * - DWC_HCSPLIT_XACTPOS_MID
  28504. + * - DWC_HCSPLIT_XACTPOS_BEGIN
  28505. + * - DWC_HCSPLIT_XACTPOS_END
  28506. + * - DWC_HCSPLIT_XACTPOS_ALL */
  28507. + uint8_t xact_pos;
  28508. +
  28509. + /** Set when the host channel does a short read. */
  28510. + uint8_t short_read;
  28511. +
  28512. + /**
  28513. + * Number of requests issued for this channel since it was assigned to
  28514. + * the current transfer (not counting PINGs).
  28515. + */
  28516. + uint8_t requests;
  28517. +
  28518. + /**
  28519. + * Queue Head for the transfer being processed by this channel.
  28520. + */
  28521. + struct dwc_otg_qh *qh;
  28522. +
  28523. + /** @} */
  28524. +
  28525. + /** Entry in list of host channels. */
  28526. + DWC_CIRCLEQ_ENTRY(dwc_hc) hc_list_entry;
  28527. +
  28528. + /** @name Descriptor DMA support */
  28529. + /** @{ */
  28530. +
  28531. + /** Number of Transfer Descriptors */
  28532. + uint16_t ntd;
  28533. +
  28534. + /** Descriptor List DMA address */
  28535. + dwc_dma_t desc_list_addr;
  28536. +
  28537. + /** Scheduling micro-frame bitmap. */
  28538. + uint8_t schinfo;
  28539. +
  28540. + /** @} */
  28541. +} dwc_hc_t;
  28542. +
  28543. +/**
  28544. + * The following parameters may be specified when starting the module. These
  28545. + * parameters define how the DWC_otg controller should be configured.
  28546. + */
  28547. +typedef struct dwc_otg_core_params {
  28548. + int32_t opt;
  28549. +
  28550. + /**
  28551. + * Specifies the OTG capabilities. The driver will automatically
  28552. + * detect the value for this parameter if none is specified.
  28553. + * 0 - HNP and SRP capable (default)
  28554. + * 1 - SRP Only capable
  28555. + * 2 - No HNP/SRP capable
  28556. + */
  28557. + int32_t otg_cap;
  28558. +
  28559. + /**
  28560. + * Specifies whether to use slave or DMA mode for accessing the data
  28561. + * FIFOs. The driver will automatically detect the value for this
  28562. + * parameter if none is specified.
  28563. + * 0 - Slave
  28564. + * 1 - DMA (default, if available)
  28565. + */
  28566. + int32_t dma_enable;
  28567. +
  28568. + /**
  28569. + * When DMA mode is enabled specifies whether to use address DMA or DMA
  28570. + * Descriptor mode for accessing the data FIFOs in device mode. The driver
  28571. + * will automatically detect the value for this if none is specified.
  28572. + * 0 - address DMA
  28573. + * 1 - DMA Descriptor(default, if available)
  28574. + */
  28575. + int32_t dma_desc_enable;
  28576. + /** The DMA Burst size (applicable only for External DMA
  28577. + * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
  28578. + */
  28579. + int32_t dma_burst_size; /* Translate this to GAHBCFG values */
  28580. +
  28581. + /**
  28582. + * Specifies the maximum speed of operation in host and device mode.
  28583. + * The actual speed depends on the speed of the attached device and
  28584. + * the value of phy_type. The actual speed depends on the speed of the
  28585. + * attached device.
  28586. + * 0 - High Speed (default)
  28587. + * 1 - Full Speed
  28588. + */
  28589. + int32_t speed;
  28590. + /** Specifies whether low power mode is supported when attached
  28591. + * to a Full Speed or Low Speed device in host mode.
  28592. + * 0 - Don't support low power mode (default)
  28593. + * 1 - Support low power mode
  28594. + */
  28595. + int32_t host_support_fs_ls_low_power;
  28596. +
  28597. + /** Specifies the PHY clock rate in low power mode when connected to a
  28598. + * Low Speed device in host mode. This parameter is applicable only if
  28599. + * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
  28600. + * then defaults to 6 MHZ otherwise 48 MHZ.
  28601. + *
  28602. + * 0 - 48 MHz
  28603. + * 1 - 6 MHz
  28604. + */
  28605. + int32_t host_ls_low_power_phy_clk;
  28606. +
  28607. + /**
  28608. + * 0 - Use cC FIFO size parameters
  28609. + * 1 - Allow dynamic FIFO sizing (default)
  28610. + */
  28611. + int32_t enable_dynamic_fifo;
  28612. +
  28613. + /** Total number of 4-byte words in the data FIFO memory. This
  28614. + * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic
  28615. + * Tx FIFOs.
  28616. + * 32 to 32768 (default 8192)
  28617. + * Note: The total FIFO memory depth in the FPGA configuration is 8192.
  28618. + */
  28619. + int32_t data_fifo_size;
  28620. +
  28621. + /** Number of 4-byte words in the Rx FIFO in device mode when dynamic
  28622. + * FIFO sizing is enabled.
  28623. + * 16 to 32768 (default 1064)
  28624. + */
  28625. + int32_t dev_rx_fifo_size;
  28626. +
  28627. + /** Number of 4-byte words in the non-periodic Tx FIFO in device mode
  28628. + * when dynamic FIFO sizing is enabled.
  28629. + * 16 to 32768 (default 1024)
  28630. + */
  28631. + int32_t dev_nperio_tx_fifo_size;
  28632. +
  28633. + /** Number of 4-byte words in each of the periodic Tx FIFOs in device
  28634. + * mode when dynamic FIFO sizing is enabled.
  28635. + * 4 to 768 (default 256)
  28636. + */
  28637. + uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
  28638. +
  28639. + /** Number of 4-byte words in the Rx FIFO in host mode when dynamic
  28640. + * FIFO sizing is enabled.
  28641. + * 16 to 32768 (default 1024)
  28642. + */
  28643. + int32_t host_rx_fifo_size;
  28644. +
  28645. + /** Number of 4-byte words in the non-periodic Tx FIFO in host mode
  28646. + * when Dynamic FIFO sizing is enabled in the core.
  28647. + * 16 to 32768 (default 1024)
  28648. + */
  28649. + int32_t host_nperio_tx_fifo_size;
  28650. +
  28651. + /** Number of 4-byte words in the host periodic Tx FIFO when dynamic
  28652. + * FIFO sizing is enabled.
  28653. + * 16 to 32768 (default 1024)
  28654. + */
  28655. + int32_t host_perio_tx_fifo_size;
  28656. +
  28657. + /** The maximum transfer size supported in bytes.
  28658. + * 2047 to 65,535 (default 65,535)
  28659. + */
  28660. + int32_t max_transfer_size;
  28661. +
  28662. + /** The maximum number of packets in a transfer.
  28663. + * 15 to 511 (default 511)
  28664. + */
  28665. + int32_t max_packet_count;
  28666. +
  28667. + /** The number of host channel registers to use.
  28668. + * 1 to 16 (default 12)
  28669. + * Note: The FPGA configuration supports a maximum of 12 host channels.
  28670. + */
  28671. + int32_t host_channels;
  28672. +
  28673. + /** The number of endpoints in addition to EP0 available for device
  28674. + * mode operations.
  28675. + * 1 to 15 (default 6 IN and OUT)
  28676. + * Note: The FPGA configuration supports a maximum of 6 IN and OUT
  28677. + * endpoints in addition to EP0.
  28678. + */
  28679. + int32_t dev_endpoints;
  28680. +
  28681. + /**
  28682. + * Specifies the type of PHY interface to use. By default, the driver
  28683. + * will automatically detect the phy_type.
  28684. + *
  28685. + * 0 - Full Speed PHY
  28686. + * 1 - UTMI+ (default)
  28687. + * 2 - ULPI
  28688. + */
  28689. + int32_t phy_type;
  28690. +
  28691. + /**
  28692. + * Specifies the UTMI+ Data Width. This parameter is
  28693. + * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
  28694. + * PHY_TYPE, this parameter indicates the data width between
  28695. + * the MAC and the ULPI Wrapper.) Also, this parameter is
  28696. + * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
  28697. + * to "8 and 16 bits", meaning that the core has been
  28698. + * configured to work at either data path width.
  28699. + *
  28700. + * 8 or 16 bits (default 16)
  28701. + */
  28702. + int32_t phy_utmi_width;
  28703. +
  28704. + /**
  28705. + * Specifies whether the ULPI operates at double or single
  28706. + * data rate. This parameter is only applicable if PHY_TYPE is
  28707. + * ULPI.
  28708. + *
  28709. + * 0 - single data rate ULPI interface with 8 bit wide data
  28710. + * bus (default)
  28711. + * 1 - double data rate ULPI interface with 4 bit wide data
  28712. + * bus
  28713. + */
  28714. + int32_t phy_ulpi_ddr;
  28715. +
  28716. + /**
  28717. + * Specifies whether to use the internal or external supply to
  28718. + * drive the vbus with a ULPI phy.
  28719. + */
  28720. + int32_t phy_ulpi_ext_vbus;
  28721. +
  28722. + /**
  28723. + * Specifies whether to use the I2Cinterface for full speed PHY. This
  28724. + * parameter is only applicable if PHY_TYPE is FS.
  28725. + * 0 - No (default)
  28726. + * 1 - Yes
  28727. + */
  28728. + int32_t i2c_enable;
  28729. +
  28730. + int32_t ulpi_fs_ls;
  28731. +
  28732. + int32_t ts_dline;
  28733. +
  28734. + /**
  28735. + * Specifies whether dedicated transmit FIFOs are
  28736. + * enabled for non periodic IN endpoints in device mode
  28737. + * 0 - No
  28738. + * 1 - Yes
  28739. + */
  28740. + int32_t en_multiple_tx_fifo;
  28741. +
  28742. + /** Number of 4-byte words in each of the Tx FIFOs in device
  28743. + * mode when dynamic FIFO sizing is enabled.
  28744. + * 4 to 768 (default 256)
  28745. + */
  28746. + uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
  28747. +
  28748. + /** Thresholding enable flag-
  28749. + * bit 0 - enable non-ISO Tx thresholding
  28750. + * bit 1 - enable ISO Tx thresholding
  28751. + * bit 2 - enable Rx thresholding
  28752. + */
  28753. + uint32_t thr_ctl;
  28754. +
  28755. + /** Thresholding length for Tx
  28756. + * FIFOs in 32 bit DWORDs
  28757. + */
  28758. + uint32_t tx_thr_length;
  28759. +
  28760. + /** Thresholding length for Rx
  28761. + * FIFOs in 32 bit DWORDs
  28762. + */
  28763. + uint32_t rx_thr_length;
  28764. +
  28765. + /**
  28766. + * Specifies whether LPM (Link Power Management) support is enabled
  28767. + */
  28768. + int32_t lpm_enable;
  28769. +
  28770. + /** Per Transfer Interrupt
  28771. + * mode enable flag
  28772. + * 1 - Enabled
  28773. + * 0 - Disabled
  28774. + */
  28775. + int32_t pti_enable;
  28776. +
  28777. + /** Multi Processor Interrupt
  28778. + * mode enable flag
  28779. + * 1 - Enabled
  28780. + * 0 - Disabled
  28781. + */
  28782. + int32_t mpi_enable;
  28783. +
  28784. + /** IS_USB Capability
  28785. + * 1 - Enabled
  28786. + * 0 - Disabled
  28787. + */
  28788. + int32_t ic_usb_cap;
  28789. +
  28790. + /** AHB Threshold Ratio
  28791. + * 2'b00 AHB Threshold = MAC Threshold
  28792. + * 2'b01 AHB Threshold = 1/2 MAC Threshold
  28793. + * 2'b10 AHB Threshold = 1/4 MAC Threshold
  28794. + * 2'b11 AHB Threshold = 1/8 MAC Threshold
  28795. + */
  28796. + int32_t ahb_thr_ratio;
  28797. +
  28798. + /** ADP Support
  28799. + * 1 - Enabled
  28800. + * 0 - Disabled
  28801. + */
  28802. + int32_t adp_supp_enable;
  28803. +
  28804. + /** HFIR Reload Control
  28805. + * 0 - The HFIR cannot be reloaded dynamically.
  28806. + * 1 - Allow dynamic reloading of the HFIR register during runtime.
  28807. + */
  28808. + int32_t reload_ctl;
  28809. +
  28810. + /** DCFG: Enable device Out NAK
  28811. + * 0 - The core does not set NAK after Bulk Out transfer complete.
  28812. + * 1 - The core sets NAK after Bulk OUT transfer complete.
  28813. + */
  28814. + int32_t dev_out_nak;
  28815. +
  28816. + /** DCFG: Enable Continue on BNA
  28817. + * After receiving BNA interrupt the core disables the endpoint,when the
  28818. + * endpoint is re-enabled by the application the core starts processing
  28819. + * 0 - from the DOEPDMA descriptor
  28820. + * 1 - from the descriptor which received the BNA.
  28821. + */
  28822. + int32_t cont_on_bna;
  28823. +
  28824. + /** GAHBCFG: AHB Single Support
  28825. + * This bit when programmed supports SINGLE transfers for remainder
  28826. + * data in a transfer for DMA mode of operation.
  28827. + * 0 - in this case the remainder data will be sent using INCR burst size.
  28828. + * 1 - in this case the remainder data will be sent using SINGLE burst size.
  28829. + */
  28830. + int32_t ahb_single;
  28831. +
  28832. + /** Core Power down mode
  28833. + * 0 - No Power Down is enabled
  28834. + * 1 - Reserved
  28835. + * 2 - Complete Power Down (Hibernation)
  28836. + */
  28837. + int32_t power_down;
  28838. +
  28839. + /** OTG revision supported
  28840. + * 0 - OTG 1.3 revision
  28841. + * 1 - OTG 2.0 revision
  28842. + */
  28843. + int32_t otg_ver;
  28844. +
  28845. +} dwc_otg_core_params_t;
  28846. +
  28847. +#ifdef DEBUG
  28848. +struct dwc_otg_core_if;
  28849. +typedef struct hc_xfer_info {
  28850. + struct dwc_otg_core_if *core_if;
  28851. + dwc_hc_t *hc;
  28852. +} hc_xfer_info_t;
  28853. +#endif
  28854. +
  28855. +typedef struct ep_xfer_info {
  28856. + struct dwc_otg_core_if *core_if;
  28857. + dwc_ep_t *ep;
  28858. + uint8_t state;
  28859. +} ep_xfer_info_t;
  28860. +/*
  28861. + * Device States
  28862. + */
  28863. +typedef enum dwc_otg_lx_state {
  28864. + /** On state */
  28865. + DWC_OTG_L0,
  28866. + /** LPM sleep state*/
  28867. + DWC_OTG_L1,
  28868. + /** USB suspend state*/
  28869. + DWC_OTG_L2,
  28870. + /** Off state*/
  28871. + DWC_OTG_L3
  28872. +} dwc_otg_lx_state_e;
  28873. +
  28874. +struct dwc_otg_global_regs_backup {
  28875. + uint32_t gotgctl_local;
  28876. + uint32_t gintmsk_local;
  28877. + uint32_t gahbcfg_local;
  28878. + uint32_t gusbcfg_local;
  28879. + uint32_t grxfsiz_local;
  28880. + uint32_t gnptxfsiz_local;
  28881. +#ifdef CONFIG_USB_DWC_OTG_LPM
  28882. + uint32_t glpmcfg_local;
  28883. +#endif
  28884. + uint32_t gi2cctl_local;
  28885. + uint32_t hptxfsiz_local;
  28886. + uint32_t pcgcctl_local;
  28887. + uint32_t gdfifocfg_local;
  28888. + uint32_t dtxfsiz_local[MAX_EPS_CHANNELS];
  28889. + uint32_t gpwrdn_local;
  28890. + uint32_t xhib_pcgcctl;
  28891. + uint32_t xhib_gpwrdn;
  28892. +};
  28893. +
  28894. +struct dwc_otg_host_regs_backup {
  28895. + uint32_t hcfg_local;
  28896. + uint32_t haintmsk_local;
  28897. + uint32_t hcintmsk_local[MAX_EPS_CHANNELS];
  28898. + uint32_t hprt0_local;
  28899. + uint32_t hfir_local;
  28900. +};
  28901. +
  28902. +struct dwc_otg_dev_regs_backup {
  28903. + uint32_t dcfg;
  28904. + uint32_t dctl;
  28905. + uint32_t daintmsk;
  28906. + uint32_t diepmsk;
  28907. + uint32_t doepmsk;
  28908. + uint32_t diepctl[MAX_EPS_CHANNELS];
  28909. + uint32_t dieptsiz[MAX_EPS_CHANNELS];
  28910. + uint32_t diepdma[MAX_EPS_CHANNELS];
  28911. +};
  28912. +/**
  28913. + * The <code>dwc_otg_core_if</code> structure contains information needed to manage
  28914. + * the DWC_otg controller acting in either host or device mode. It
  28915. + * represents the programming view of the controller as a whole.
  28916. + */
  28917. +struct dwc_otg_core_if {
  28918. + /** Parameters that define how the core should be configured.*/
  28919. + dwc_otg_core_params_t *core_params;
  28920. +
  28921. + /** Core Global registers starting at offset 000h. */
  28922. + dwc_otg_core_global_regs_t *core_global_regs;
  28923. +
  28924. + /** Device-specific information */
  28925. + dwc_otg_dev_if_t *dev_if;
  28926. + /** Host-specific information */
  28927. + dwc_otg_host_if_t *host_if;
  28928. +
  28929. + /** Value from SNPSID register */
  28930. + uint32_t snpsid;
  28931. +
  28932. + /*
  28933. + * Set to 1 if the core PHY interface bits in USBCFG have been
  28934. + * initialized.
  28935. + */
  28936. + uint8_t phy_init_done;
  28937. +
  28938. + /*
  28939. + * SRP Success flag, set by srp success interrupt in FS I2C mode
  28940. + */
  28941. + uint8_t srp_success;
  28942. + uint8_t srp_timer_started;
  28943. + /** Timer for SRP. If it expires before SRP is successful
  28944. + * clear the SRP. */
  28945. + dwc_timer_t *srp_timer;
  28946. +
  28947. +#ifdef DWC_DEV_SRPCAP
  28948. + /* This timer is needed to power on the hibernated host core if SRP is not
  28949. + * initiated on connected SRP capable device for limited period of time
  28950. + */
  28951. + uint8_t pwron_timer_started;
  28952. + dwc_timer_t *pwron_timer;
  28953. +#endif
  28954. + /* Common configuration information */
  28955. + /** Power and Clock Gating Control Register */
  28956. + volatile uint32_t *pcgcctl;
  28957. +#define DWC_OTG_PCGCCTL_OFFSET 0xE00
  28958. +
  28959. + /** Push/pop addresses for endpoints or host channels.*/
  28960. + uint32_t *data_fifo[MAX_EPS_CHANNELS];
  28961. +#define DWC_OTG_DATA_FIFO_OFFSET 0x1000
  28962. +#define DWC_OTG_DATA_FIFO_SIZE 0x1000
  28963. +
  28964. + /** Total RAM for FIFOs (Bytes) */
  28965. + uint16_t total_fifo_size;
  28966. + /** Size of Rx FIFO (Bytes) */
  28967. + uint16_t rx_fifo_size;
  28968. + /** Size of Non-periodic Tx FIFO (Bytes) */
  28969. + uint16_t nperio_tx_fifo_size;
  28970. +
  28971. + /** 1 if DMA is enabled, 0 otherwise. */
  28972. + uint8_t dma_enable;
  28973. +
  28974. + /** 1 if DMA descriptor is enabled, 0 otherwise. */
  28975. + uint8_t dma_desc_enable;
  28976. +
  28977. + /** 1 if PTI Enhancement mode is enabled, 0 otherwise. */
  28978. + uint8_t pti_enh_enable;
  28979. +
  28980. + /** 1 if MPI Enhancement mode is enabled, 0 otherwise. */
  28981. + uint8_t multiproc_int_enable;
  28982. +
  28983. + /** 1 if dedicated Tx FIFOs are enabled, 0 otherwise. */
  28984. + uint8_t en_multiple_tx_fifo;
  28985. +
  28986. + /** Set to 1 if multiple packets of a high-bandwidth transfer is in
  28987. + * process of being queued */
  28988. + uint8_t queuing_high_bandwidth;
  28989. +
  28990. + /** Hardware Configuration -- stored here for convenience.*/
  28991. + hwcfg1_data_t hwcfg1;
  28992. + hwcfg2_data_t hwcfg2;
  28993. + hwcfg3_data_t hwcfg3;
  28994. + hwcfg4_data_t hwcfg4;
  28995. + fifosize_data_t hptxfsiz;
  28996. +
  28997. + /** Host and Device Configuration -- stored here for convenience.*/
  28998. + hcfg_data_t hcfg;
  28999. + dcfg_data_t dcfg;
  29000. +
  29001. + /** The operational State, during transations
  29002. + * (a_host>>a_peripherial and b_device=>b_host) this may not
  29003. + * match the core but allows the software to determine
  29004. + * transitions.
  29005. + */
  29006. + uint8_t op_state;
  29007. +
  29008. + /**
  29009. + * Set to 1 if the HCD needs to be restarted on a session request
  29010. + * interrupt. This is required if no connector ID status change has
  29011. + * occurred since the HCD was last disconnected.
  29012. + */
  29013. + uint8_t restart_hcd_on_session_req;
  29014. +
  29015. + /** HCD callbacks */
  29016. + /** A-Device is a_host */
  29017. +#define A_HOST (1)
  29018. + /** A-Device is a_suspend */
  29019. +#define A_SUSPEND (2)
  29020. + /** A-Device is a_peripherial */
  29021. +#define A_PERIPHERAL (3)
  29022. + /** B-Device is operating as a Peripheral. */
  29023. +#define B_PERIPHERAL (4)
  29024. + /** B-Device is operating as a Host. */
  29025. +#define B_HOST (5)
  29026. +
  29027. + /** HCD callbacks */
  29028. + struct dwc_otg_cil_callbacks *hcd_cb;
  29029. + /** PCD callbacks */
  29030. + struct dwc_otg_cil_callbacks *pcd_cb;
  29031. +
  29032. + /** Device mode Periodic Tx FIFO Mask */
  29033. + uint32_t p_tx_msk;
  29034. + /** Device mode Periodic Tx FIFO Mask */
  29035. + uint32_t tx_msk;
  29036. +
  29037. + /** Workqueue object used for handling several interrupts */
  29038. + dwc_workq_t *wq_otg;
  29039. +
  29040. + /** Timer object used for handling "Wakeup Detected" Interrupt */
  29041. + dwc_timer_t *wkp_timer;
  29042. + /** This arrays used for debug purposes for DEV OUT NAK enhancement */
  29043. + uint32_t start_doeptsiz_val[MAX_EPS_CHANNELS];
  29044. + ep_xfer_info_t ep_xfer_info[MAX_EPS_CHANNELS];
  29045. + dwc_timer_t *ep_xfer_timer[MAX_EPS_CHANNELS];
  29046. +#ifdef DEBUG
  29047. + uint32_t start_hcchar_val[MAX_EPS_CHANNELS];
  29048. +
  29049. + hc_xfer_info_t hc_xfer_info[MAX_EPS_CHANNELS];
  29050. + dwc_timer_t *hc_xfer_timer[MAX_EPS_CHANNELS];
  29051. +
  29052. + uint32_t hfnum_7_samples;
  29053. + uint64_t hfnum_7_frrem_accum;
  29054. + uint32_t hfnum_0_samples;
  29055. + uint64_t hfnum_0_frrem_accum;
  29056. + uint32_t hfnum_other_samples;
  29057. + uint64_t hfnum_other_frrem_accum;
  29058. +#endif
  29059. +
  29060. +#ifdef DWC_UTE_CFI
  29061. + uint16_t pwron_rxfsiz;
  29062. + uint16_t pwron_gnptxfsiz;
  29063. + uint16_t pwron_txfsiz[15];
  29064. +
  29065. + uint16_t init_rxfsiz;
  29066. + uint16_t init_gnptxfsiz;
  29067. + uint16_t init_txfsiz[15];
  29068. +#endif
  29069. +
  29070. + /** Lx state of device */
  29071. + dwc_otg_lx_state_e lx_state;
  29072. +
  29073. + /** Saved Core Global registers */
  29074. + struct dwc_otg_global_regs_backup *gr_backup;
  29075. + /** Saved Host registers */
  29076. + struct dwc_otg_host_regs_backup *hr_backup;
  29077. + /** Saved Device registers */
  29078. + struct dwc_otg_dev_regs_backup *dr_backup;
  29079. +
  29080. + /** Power Down Enable */
  29081. + uint32_t power_down;
  29082. +
  29083. + /** ADP support Enable */
  29084. + uint32_t adp_enable;
  29085. +
  29086. + /** ADP structure object */
  29087. + dwc_otg_adp_t adp;
  29088. +
  29089. + /** hibernation/suspend flag */
  29090. + int hibernation_suspend;
  29091. +
  29092. + /** Device mode extended hibernation flag */
  29093. + int xhib;
  29094. +
  29095. + /** OTG revision supported */
  29096. + uint32_t otg_ver;
  29097. +
  29098. + /** OTG status flag used for HNP polling */
  29099. + uint8_t otg_sts;
  29100. +
  29101. + /** Pointer to either hcd->lock or pcd->lock */
  29102. + dwc_spinlock_t *lock;
  29103. +
  29104. + /** Start predict NextEP based on Learning Queue if equal 1,
  29105. + * also used as counter of disabled NP IN EP's */
  29106. + uint8_t start_predict;
  29107. +
  29108. + /** NextEp sequence, including EP0: nextep_seq[] = EP if non-periodic and
  29109. + * active, 0xff otherwise */
  29110. + uint8_t nextep_seq[MAX_EPS_CHANNELS];
  29111. +
  29112. + /** Index of fisrt EP in nextep_seq array which should be re-enabled **/
  29113. + uint8_t first_in_nextep_seq;
  29114. +
  29115. + /** Frame number while entering to ISR - needed for ISOCs **/
  29116. + uint32_t frame_num;
  29117. +
  29118. +};
  29119. +
  29120. +#ifdef DEBUG
  29121. +/*
  29122. + * This function is called when transfer is timed out.
  29123. + */
  29124. +extern void hc_xfer_timeout(void *ptr);
  29125. +#endif
  29126. +
  29127. +/*
  29128. + * This function is called when transfer is timed out on endpoint.
  29129. + */
  29130. +extern void ep_xfer_timeout(void *ptr);
  29131. +
  29132. +/*
  29133. + * The following functions are functions for works
  29134. + * using during handling some interrupts
  29135. + */
  29136. +extern void w_conn_id_status_change(void *p);
  29137. +
  29138. +extern void w_wakeup_detected(void *p);
  29139. +
  29140. +/** Saves global register values into system memory. */
  29141. +extern int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if);
  29142. +/** Saves device register values into system memory. */
  29143. +extern int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if);
  29144. +/** Saves host register values into system memory. */
  29145. +extern int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if);
  29146. +/** Restore global register values. */
  29147. +extern int dwc_otg_restore_global_regs(dwc_otg_core_if_t * core_if);
  29148. +/** Restore host register values. */
  29149. +extern int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset);
  29150. +/** Restore device register values. */
  29151. +extern int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if,
  29152. + int rem_wakeup);
  29153. +extern int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if);
  29154. +extern int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode,
  29155. + int is_host);
  29156. +
  29157. +extern int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if,
  29158. + int restore_mode, int reset);
  29159. +extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if,
  29160. + int rem_wakeup, int reset);
  29161. +
  29162. +/*
  29163. + * The following functions support initialization of the CIL driver component
  29164. + * and the DWC_otg controller.
  29165. + */
  29166. +extern void dwc_otg_core_host_init(dwc_otg_core_if_t * _core_if);
  29167. +extern void dwc_otg_core_dev_init(dwc_otg_core_if_t * _core_if);
  29168. +
  29169. +/** @name Device CIL Functions
  29170. + * The following functions support managing the DWC_otg controller in device
  29171. + * mode.
  29172. + */
  29173. +/**@{*/
  29174. +extern void dwc_otg_wakeup(dwc_otg_core_if_t * _core_if);
  29175. +extern void dwc_otg_read_setup_packet(dwc_otg_core_if_t * _core_if,
  29176. + uint32_t * _dest);
  29177. +extern uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * _core_if);
  29178. +extern void dwc_otg_ep0_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
  29179. +extern void dwc_otg_ep_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
  29180. +extern void dwc_otg_ep_deactivate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
  29181. +extern void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * _core_if,
  29182. + dwc_ep_t * _ep);
  29183. +extern void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * _core_if,
  29184. + dwc_ep_t * _ep);
  29185. +extern void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * _core_if,
  29186. + dwc_ep_t * _ep);
  29187. +extern void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * _core_if,
  29188. + dwc_ep_t * _ep);
  29189. +extern void dwc_otg_ep_write_packet(dwc_otg_core_if_t * _core_if,
  29190. + dwc_ep_t * _ep, int _dma);
  29191. +extern void dwc_otg_ep_set_stall(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep);
  29192. +extern void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * _core_if,
  29193. + dwc_ep_t * _ep);
  29194. +extern void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * _core_if);
  29195. +
  29196. +#ifdef DWC_EN_ISOC
  29197. +extern void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if,
  29198. + dwc_ep_t * ep);
  29199. +extern void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if,
  29200. + dwc_ep_t * ep);
  29201. +#endif /* DWC_EN_ISOC */
  29202. +/**@}*/
  29203. +
  29204. +/** @name Host CIL Functions
  29205. + * The following functions support managing the DWC_otg controller in host
  29206. + * mode.
  29207. + */
  29208. +/**@{*/
  29209. +extern void dwc_otg_hc_init(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
  29210. +extern void dwc_otg_hc_halt(dwc_otg_core_if_t * _core_if,
  29211. + dwc_hc_t * _hc, dwc_otg_halt_status_e _halt_status);
  29212. +extern void dwc_otg_hc_cleanup(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
  29213. +extern void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * _core_if,
  29214. + dwc_hc_t * _hc);
  29215. +extern int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * _core_if,
  29216. + dwc_hc_t * _hc);
  29217. +extern void dwc_otg_hc_do_ping(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc);
  29218. +extern void dwc_otg_hc_write_packet(dwc_otg_core_if_t * _core_if,
  29219. + dwc_hc_t * _hc);
  29220. +extern void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * _core_if);
  29221. +extern void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * _core_if);
  29222. +
  29223. +extern void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if,
  29224. + dwc_hc_t * hc);
  29225. +
  29226. +extern uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if);
  29227. +
  29228. +/* Macro used to clear one channel interrupt */
  29229. +#define clear_hc_int(_hc_regs_, _intr_) \
  29230. +do { \
  29231. + hcint_data_t hcint_clear = {.d32 = 0}; \
  29232. + hcint_clear.b._intr_ = 1; \
  29233. + DWC_WRITE_REG32(&(_hc_regs_)->hcint, hcint_clear.d32); \
  29234. +} while (0)
  29235. +
  29236. +/*
  29237. + * Macro used to disable one channel interrupt. Channel interrupts are
  29238. + * disabled when the channel is halted or released by the interrupt handler.
  29239. + * There is no need to handle further interrupts of that type until the
  29240. + * channel is re-assigned. In fact, subsequent handling may cause crashes
  29241. + * because the channel structures are cleaned up when the channel is released.
  29242. + */
  29243. +#define disable_hc_int(_hc_regs_, _intr_) \
  29244. +do { \
  29245. + hcintmsk_data_t hcintmsk = {.d32 = 0}; \
  29246. + hcintmsk.b._intr_ = 1; \
  29247. + DWC_MODIFY_REG32(&(_hc_regs_)->hcintmsk, hcintmsk.d32, 0); \
  29248. +} while (0)
  29249. +
  29250. +/**
  29251. + * This function Reads HPRT0 in preparation to modify. It keeps the
  29252. + * WC bits 0 so that if they are read as 1, they won't clear when you
  29253. + * write it back
  29254. + */
  29255. +static inline uint32_t dwc_otg_read_hprt0(dwc_otg_core_if_t * _core_if)
  29256. +{
  29257. + hprt0_data_t hprt0;
  29258. + hprt0.d32 = DWC_READ_REG32(_core_if->host_if->hprt0);
  29259. + hprt0.b.prtena = 0;
  29260. + hprt0.b.prtconndet = 0;
  29261. + hprt0.b.prtenchng = 0;
  29262. + hprt0.b.prtovrcurrchng = 0;
  29263. + return hprt0.d32;
  29264. +}
  29265. +
  29266. +/**@}*/
  29267. +
  29268. +/** @name Common CIL Functions
  29269. + * The following functions support managing the DWC_otg controller in either
  29270. + * device or host mode.
  29271. + */
  29272. +/**@{*/
  29273. +
  29274. +extern void dwc_otg_read_packet(dwc_otg_core_if_t * core_if,
  29275. + uint8_t * dest, uint16_t bytes);
  29276. +
  29277. +extern void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * _core_if, const int _num);
  29278. +extern void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * _core_if);
  29279. +extern void dwc_otg_core_reset(dwc_otg_core_if_t * _core_if);
  29280. +
  29281. +/**
  29282. + * This function returns the Core Interrupt register.
  29283. + */
  29284. +static inline uint32_t dwc_otg_read_core_intr(dwc_otg_core_if_t * core_if)
  29285. +{
  29286. + return (DWC_READ_REG32(&core_if->core_global_regs->gintsts) &
  29287. + DWC_READ_REG32(&core_if->core_global_regs->gintmsk));
  29288. +}
  29289. +
  29290. +/**
  29291. + * This function returns the OTG Interrupt register.
  29292. + */
  29293. +static inline uint32_t dwc_otg_read_otg_intr(dwc_otg_core_if_t * core_if)
  29294. +{
  29295. + return (DWC_READ_REG32(&core_if->core_global_regs->gotgint));
  29296. +}
  29297. +
  29298. +/**
  29299. + * This function reads the Device All Endpoints Interrupt register and
  29300. + * returns the IN endpoint interrupt bits.
  29301. + */
  29302. +static inline uint32_t dwc_otg_read_dev_all_in_ep_intr(dwc_otg_core_if_t *
  29303. + core_if)
  29304. +{
  29305. +
  29306. + uint32_t v;
  29307. +
  29308. + if (core_if->multiproc_int_enable) {
  29309. + v = DWC_READ_REG32(&core_if->dev_if->
  29310. + dev_global_regs->deachint) &
  29311. + DWC_READ_REG32(&core_if->
  29312. + dev_if->dev_global_regs->deachintmsk);
  29313. + } else {
  29314. + v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) &
  29315. + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
  29316. + }
  29317. + return (v & 0xffff);
  29318. +}
  29319. +
  29320. +/**
  29321. + * This function reads the Device All Endpoints Interrupt register and
  29322. + * returns the OUT endpoint interrupt bits.
  29323. + */
  29324. +static inline uint32_t dwc_otg_read_dev_all_out_ep_intr(dwc_otg_core_if_t *
  29325. + core_if)
  29326. +{
  29327. + uint32_t v;
  29328. +
  29329. + if (core_if->multiproc_int_enable) {
  29330. + v = DWC_READ_REG32(&core_if->dev_if->
  29331. + dev_global_regs->deachint) &
  29332. + DWC_READ_REG32(&core_if->
  29333. + dev_if->dev_global_regs->deachintmsk);
  29334. + } else {
  29335. + v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) &
  29336. + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk);
  29337. + }
  29338. +
  29339. + return ((v & 0xffff0000) >> 16);
  29340. +}
  29341. +
  29342. +/**
  29343. + * This function returns the Device IN EP Interrupt register
  29344. + */
  29345. +static inline uint32_t dwc_otg_read_dev_in_ep_intr(dwc_otg_core_if_t * core_if,
  29346. + dwc_ep_t * ep)
  29347. +{
  29348. + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
  29349. + uint32_t v, msk, emp;
  29350. +
  29351. + if (core_if->multiproc_int_enable) {
  29352. + msk =
  29353. + DWC_READ_REG32(&dev_if->
  29354. + dev_global_regs->diepeachintmsk[ep->num]);
  29355. + emp =
  29356. + DWC_READ_REG32(&dev_if->
  29357. + dev_global_regs->dtknqr4_fifoemptymsk);
  29358. + msk |= ((emp >> ep->num) & 0x1) << 7;
  29359. + v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk;
  29360. + } else {
  29361. + msk = DWC_READ_REG32(&dev_if->dev_global_regs->diepmsk);
  29362. + emp =
  29363. + DWC_READ_REG32(&dev_if->
  29364. + dev_global_regs->dtknqr4_fifoemptymsk);
  29365. + msk |= ((emp >> ep->num) & 0x1) << 7;
  29366. + v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk;
  29367. + }
  29368. +
  29369. + return v;
  29370. +}
  29371. +
  29372. +/**
  29373. + * This function returns the Device OUT EP Interrupt register
  29374. + */
  29375. +static inline uint32_t dwc_otg_read_dev_out_ep_intr(dwc_otg_core_if_t *
  29376. + _core_if, dwc_ep_t * _ep)
  29377. +{
  29378. + dwc_otg_dev_if_t *dev_if = _core_if->dev_if;
  29379. + uint32_t v;
  29380. + doepmsk_data_t msk = {.d32 = 0 };
  29381. +
  29382. + if (_core_if->multiproc_int_enable) {
  29383. + msk.d32 =
  29384. + DWC_READ_REG32(&dev_if->
  29385. + dev_global_regs->doepeachintmsk[_ep->num]);
  29386. + if (_core_if->pti_enh_enable) {
  29387. + msk.b.pktdrpsts = 1;
  29388. + }
  29389. + v = DWC_READ_REG32(&dev_if->
  29390. + out_ep_regs[_ep->num]->doepint) & msk.d32;
  29391. + } else {
  29392. + msk.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->doepmsk);
  29393. + if (_core_if->pti_enh_enable) {
  29394. + msk.b.pktdrpsts = 1;
  29395. + }
  29396. + v = DWC_READ_REG32(&dev_if->
  29397. + out_ep_regs[_ep->num]->doepint) & msk.d32;
  29398. + }
  29399. + return v;
  29400. +}
  29401. +
  29402. +/**
  29403. + * This function returns the Host All Channel Interrupt register
  29404. + */
  29405. +static inline uint32_t dwc_otg_read_host_all_channels_intr(dwc_otg_core_if_t *
  29406. + _core_if)
  29407. +{
  29408. + return (DWC_READ_REG32(&_core_if->host_if->host_global_regs->haint));
  29409. +}
  29410. +
  29411. +static inline uint32_t dwc_otg_read_host_channel_intr(dwc_otg_core_if_t *
  29412. + _core_if, dwc_hc_t * _hc)
  29413. +{
  29414. + return (DWC_READ_REG32
  29415. + (&_core_if->host_if->hc_regs[_hc->hc_num]->hcint));
  29416. +}
  29417. +
  29418. +/**
  29419. + * This function returns the mode of the operation, host or device.
  29420. + *
  29421. + * @return 0 - Device Mode, 1 - Host Mode
  29422. + */
  29423. +static inline uint32_t dwc_otg_mode(dwc_otg_core_if_t * _core_if)
  29424. +{
  29425. + return (DWC_READ_REG32(&_core_if->core_global_regs->gintsts) & 0x1);
  29426. +}
  29427. +
  29428. +/**@}*/
  29429. +
  29430. +/**
  29431. + * DWC_otg CIL callback structure. This structure allows the HCD and
  29432. + * PCD to register functions used for starting and stopping the PCD
  29433. + * and HCD for role change on for a DRD.
  29434. + */
  29435. +typedef struct dwc_otg_cil_callbacks {
  29436. + /** Start function for role change */
  29437. + int (*start) (void *_p);
  29438. + /** Stop Function for role change */
  29439. + int (*stop) (void *_p);
  29440. + /** Disconnect Function for role change */
  29441. + int (*disconnect) (void *_p);
  29442. + /** Resume/Remote wakeup Function */
  29443. + int (*resume_wakeup) (void *_p);
  29444. + /** Suspend function */
  29445. + int (*suspend) (void *_p);
  29446. + /** Session Start (SRP) */
  29447. + int (*session_start) (void *_p);
  29448. +#ifdef CONFIG_USB_DWC_OTG_LPM
  29449. + /** Sleep (switch to L0 state) */
  29450. + int (*sleep) (void *_p);
  29451. +#endif
  29452. + /** Pointer passed to start() and stop() */
  29453. + void *p;
  29454. +} dwc_otg_cil_callbacks_t;
  29455. +
  29456. +extern void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * _core_if,
  29457. + dwc_otg_cil_callbacks_t * _cb,
  29458. + void *_p);
  29459. +extern void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * _core_if,
  29460. + dwc_otg_cil_callbacks_t * _cb,
  29461. + void *_p);
  29462. +
  29463. +void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if);
  29464. +
  29465. +//////////////////////////////////////////////////////////////////////
  29466. +/** Start the HCD. Helper function for using the HCD callbacks.
  29467. + *
  29468. + * @param core_if Programming view of DWC_otg controller.
  29469. + */
  29470. +static inline void cil_hcd_start(dwc_otg_core_if_t * core_if)
  29471. +{
  29472. + if (core_if->hcd_cb && core_if->hcd_cb->start) {
  29473. + core_if->hcd_cb->start(core_if->hcd_cb->p);
  29474. + }
  29475. +}
  29476. +
  29477. +/** Stop the HCD. Helper function for using the HCD callbacks.
  29478. + *
  29479. + * @param core_if Programming view of DWC_otg controller.
  29480. + */
  29481. +static inline void cil_hcd_stop(dwc_otg_core_if_t * core_if)
  29482. +{
  29483. + if (core_if->hcd_cb && core_if->hcd_cb->stop) {
  29484. + core_if->hcd_cb->stop(core_if->hcd_cb->p);
  29485. + }
  29486. +}
  29487. +
  29488. +/** Disconnect the HCD. Helper function for using the HCD callbacks.
  29489. + *
  29490. + * @param core_if Programming view of DWC_otg controller.
  29491. + */
  29492. +static inline void cil_hcd_disconnect(dwc_otg_core_if_t * core_if)
  29493. +{
  29494. + if (core_if->hcd_cb && core_if->hcd_cb->disconnect) {
  29495. + core_if->hcd_cb->disconnect(core_if->hcd_cb->p);
  29496. + }
  29497. +}
  29498. +
  29499. +/** Inform the HCD the a New Session has begun. Helper function for
  29500. + * using the HCD callbacks.
  29501. + *
  29502. + * @param core_if Programming view of DWC_otg controller.
  29503. + */
  29504. +static inline void cil_hcd_session_start(dwc_otg_core_if_t * core_if)
  29505. +{
  29506. + if (core_if->hcd_cb && core_if->hcd_cb->session_start) {
  29507. + core_if->hcd_cb->session_start(core_if->hcd_cb->p);
  29508. + }
  29509. +}
  29510. +
  29511. +#ifdef CONFIG_USB_DWC_OTG_LPM
  29512. +/**
  29513. + * Inform the HCD about LPM sleep.
  29514. + * Helper function for using the HCD callbacks.
  29515. + *
  29516. + * @param core_if Programming view of DWC_otg controller.
  29517. + */
  29518. +static inline void cil_hcd_sleep(dwc_otg_core_if_t * core_if)
  29519. +{
  29520. + if (core_if->hcd_cb && core_if->hcd_cb->sleep) {
  29521. + core_if->hcd_cb->sleep(core_if->hcd_cb->p);
  29522. + }
  29523. +}
  29524. +#endif
  29525. +
  29526. +/** Resume the HCD. Helper function for using the HCD callbacks.
  29527. + *
  29528. + * @param core_if Programming view of DWC_otg controller.
  29529. + */
  29530. +static inline void cil_hcd_resume(dwc_otg_core_if_t * core_if)
  29531. +{
  29532. + if (core_if->hcd_cb && core_if->hcd_cb->resume_wakeup) {
  29533. + core_if->hcd_cb->resume_wakeup(core_if->hcd_cb->p);
  29534. + }
  29535. +}
  29536. +
  29537. +/** Start the PCD. Helper function for using the PCD callbacks.
  29538. + *
  29539. + * @param core_if Programming view of DWC_otg controller.
  29540. + */
  29541. +static inline void cil_pcd_start(dwc_otg_core_if_t * core_if)
  29542. +{
  29543. + if (core_if->pcd_cb && core_if->pcd_cb->start) {
  29544. + core_if->pcd_cb->start(core_if->pcd_cb->p);
  29545. + }
  29546. +}
  29547. +
  29548. +/** Stop the PCD. Helper function for using the PCD callbacks.
  29549. + *
  29550. + * @param core_if Programming view of DWC_otg controller.
  29551. + */
  29552. +static inline void cil_pcd_stop(dwc_otg_core_if_t * core_if)
  29553. +{
  29554. + if (core_if->pcd_cb && core_if->pcd_cb->stop) {
  29555. + core_if->pcd_cb->stop(core_if->pcd_cb->p);
  29556. + }
  29557. +}
  29558. +
  29559. +/** Suspend the PCD. Helper function for using the PCD callbacks.
  29560. + *
  29561. + * @param core_if Programming view of DWC_otg controller.
  29562. + */
  29563. +static inline void cil_pcd_suspend(dwc_otg_core_if_t * core_if)
  29564. +{
  29565. + if (core_if->pcd_cb && core_if->pcd_cb->suspend) {
  29566. + core_if->pcd_cb->suspend(core_if->pcd_cb->p);
  29567. + }
  29568. +}
  29569. +
  29570. +/** Resume the PCD. Helper function for using the PCD callbacks.
  29571. + *
  29572. + * @param core_if Programming view of DWC_otg controller.
  29573. + */
  29574. +static inline void cil_pcd_resume(dwc_otg_core_if_t * core_if)
  29575. +{
  29576. + if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
  29577. + core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
  29578. + }
  29579. +}
  29580. +
  29581. +//////////////////////////////////////////////////////////////////////
  29582. +
  29583. +#endif
  29584. --- /dev/null
  29585. +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
  29586. @@ -0,0 +1,1563 @@
  29587. +/* ==========================================================================
  29588. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $
  29589. + * $Revision: #32 $
  29590. + * $Date: 2012/08/10 $
  29591. + * $Change: 2047372 $
  29592. + *
  29593. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  29594. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  29595. + * otherwise expressly agreed to in writing between Synopsys and you.
  29596. + *
  29597. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  29598. + * any End User Software License Agreement or Agreement for Licensed Product
  29599. + * with Synopsys or any supplement thereto. You are permitted to use and
  29600. + * redistribute this Software in source and binary forms, with or without
  29601. + * modification, provided that redistributions of source code must retain this
  29602. + * notice. You may not view, use, disclose, copy or distribute this file or
  29603. + * any information contained herein except pursuant to this license grant from
  29604. + * Synopsys. If you do not agree with this notice, including the disclaimer
  29605. + * below, then you are not authorized to use the Software.
  29606. + *
  29607. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  29608. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29609. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29610. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  29611. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  29612. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  29613. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  29614. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29615. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29616. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  29617. + * DAMAGE.
  29618. + * ========================================================================== */
  29619. +
  29620. +/** @file
  29621. + *
  29622. + * The Core Interface Layer provides basic services for accessing and
  29623. + * managing the DWC_otg hardware. These services are used by both the
  29624. + * Host Controller Driver and the Peripheral Controller Driver.
  29625. + *
  29626. + * This file contains the Common Interrupt handlers.
  29627. + */
  29628. +#include "dwc_os.h"
  29629. +#include "dwc_otg_regs.h"
  29630. +#include "dwc_otg_cil.h"
  29631. +#include "dwc_otg_driver.h"
  29632. +#include "dwc_otg_pcd.h"
  29633. +#include "dwc_otg_hcd.h"
  29634. +
  29635. +#ifdef DEBUG
  29636. +inline const char *op_state_str(dwc_otg_core_if_t * core_if)
  29637. +{
  29638. + return (core_if->op_state == A_HOST ? "a_host" :
  29639. + (core_if->op_state == A_SUSPEND ? "a_suspend" :
  29640. + (core_if->op_state == A_PERIPHERAL ? "a_peripheral" :
  29641. + (core_if->op_state == B_PERIPHERAL ? "b_peripheral" :
  29642. + (core_if->op_state == B_HOST ? "b_host" : "unknown")))));
  29643. +}
  29644. +#endif
  29645. +
  29646. +/** This function will log a debug message
  29647. + *
  29648. + * @param core_if Programming view of DWC_otg controller.
  29649. + */
  29650. +int32_t dwc_otg_handle_mode_mismatch_intr(dwc_otg_core_if_t * core_if)
  29651. +{
  29652. + gintsts_data_t gintsts;
  29653. + DWC_WARN("Mode Mismatch Interrupt: currently in %s mode\n",
  29654. + dwc_otg_mode(core_if) ? "Host" : "Device");
  29655. +
  29656. + /* Clear interrupt */
  29657. + gintsts.d32 = 0;
  29658. + gintsts.b.modemismatch = 1;
  29659. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
  29660. + return 1;
  29661. +}
  29662. +
  29663. +/**
  29664. + * This function handles the OTG Interrupts. It reads the OTG
  29665. + * Interrupt Register (GOTGINT) to determine what interrupt has
  29666. + * occurred.
  29667. + *
  29668. + * @param core_if Programming view of DWC_otg controller.
  29669. + */
  29670. +int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if)
  29671. +{
  29672. + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
  29673. + gotgint_data_t gotgint;
  29674. + gotgctl_data_t gotgctl;
  29675. + gintmsk_data_t gintmsk;
  29676. + gpwrdn_data_t gpwrdn;
  29677. +
  29678. + gotgint.d32 = DWC_READ_REG32(&global_regs->gotgint);
  29679. + gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
  29680. + DWC_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32,
  29681. + op_state_str(core_if));
  29682. +
  29683. + if (gotgint.b.sesenddet) {
  29684. + DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
  29685. + "Session End Detected++ (%s)\n",
  29686. + op_state_str(core_if));
  29687. + gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
  29688. +
  29689. + if (core_if->op_state == B_HOST) {
  29690. + cil_pcd_start(core_if);
  29691. + core_if->op_state = B_PERIPHERAL;
  29692. + } else {
  29693. + /* If not B_HOST and Device HNP still set. HNP
  29694. + * Did not succeed!*/
  29695. + if (gotgctl.b.devhnpen) {
  29696. + DWC_DEBUGPL(DBG_ANY, "Session End Detected\n");
  29697. + __DWC_ERROR("Device Not Connected/Responding!\n");
  29698. + }
  29699. +
  29700. + /* If Session End Detected the B-Cable has
  29701. + * been disconnected. */
  29702. + /* Reset PCD and Gadget driver to a
  29703. + * clean state. */
  29704. + core_if->lx_state = DWC_OTG_L0;
  29705. + DWC_SPINUNLOCK(core_if->lock);
  29706. + cil_pcd_stop(core_if);
  29707. + DWC_SPINLOCK(core_if->lock);
  29708. +
  29709. + if (core_if->adp_enable) {
  29710. + if (core_if->power_down == 2) {
  29711. + gpwrdn.d32 = 0;
  29712. + gpwrdn.b.pwrdnswtch = 1;
  29713. + DWC_MODIFY_REG32(&core_if->
  29714. + core_global_regs->
  29715. + gpwrdn, gpwrdn.d32, 0);
  29716. + }
  29717. +
  29718. + gpwrdn.d32 = 0;
  29719. + gpwrdn.b.pmuintsel = 1;
  29720. + gpwrdn.b.pmuactv = 1;
  29721. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  29722. + gpwrdn, 0, gpwrdn.d32);
  29723. +
  29724. + dwc_otg_adp_sense_start(core_if);
  29725. + }
  29726. + }
  29727. +
  29728. + gotgctl.d32 = 0;
  29729. + gotgctl.b.devhnpen = 1;
  29730. + DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
  29731. + }
  29732. + if (gotgint.b.sesreqsucstschng) {
  29733. + DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
  29734. + "Session Reqeust Success Status Change++\n");
  29735. + gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
  29736. + if (gotgctl.b.sesreqscs) {
  29737. +
  29738. + if ((core_if->core_params->phy_type ==
  29739. + DWC_PHY_TYPE_PARAM_FS) && (core_if->core_params->i2c_enable)) {
  29740. + core_if->srp_success = 1;
  29741. + } else {
  29742. + DWC_SPINUNLOCK(core_if->lock);
  29743. + cil_pcd_resume(core_if);
  29744. + DWC_SPINLOCK(core_if->lock);
  29745. + /* Clear Session Request */
  29746. + gotgctl.d32 = 0;
  29747. + gotgctl.b.sesreq = 1;
  29748. + DWC_MODIFY_REG32(&global_regs->gotgctl,
  29749. + gotgctl.d32, 0);
  29750. + }
  29751. + }
  29752. + }
  29753. + if (gotgint.b.hstnegsucstschng) {
  29754. + /* Print statements during the HNP interrupt handling
  29755. + * can cause it to fail.*/
  29756. + gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl);
  29757. + /* WA for 3.00a- HW is not setting cur_mode, even sometimes
  29758. + * this does not help*/
  29759. + if (core_if->snpsid >= OTG_CORE_REV_3_00a)
  29760. + dwc_udelay(100);
  29761. + if (gotgctl.b.hstnegscs) {
  29762. + if (dwc_otg_is_host_mode(core_if)) {
  29763. + core_if->op_state = B_HOST;
  29764. + /*
  29765. + * Need to disable SOF interrupt immediately.
  29766. + * When switching from device to host, the PCD
  29767. + * interrupt handler won't handle the
  29768. + * interrupt if host mode is already set. The
  29769. + * HCD interrupt handler won't get called if
  29770. + * the HCD state is HALT. This means that the
  29771. + * interrupt does not get handled and Linux
  29772. + * complains loudly.
  29773. + */
  29774. + gintmsk.d32 = 0;
  29775. + gintmsk.b.sofintr = 1;
  29776. + DWC_MODIFY_REG32(&global_regs->gintmsk,
  29777. + gintmsk.d32, 0);
  29778. + /* Call callback function with spin lock released */
  29779. + DWC_SPINUNLOCK(core_if->lock);
  29780. + cil_pcd_stop(core_if);
  29781. + /*
  29782. + * Initialize the Core for Host mode.
  29783. + */
  29784. + cil_hcd_start(core_if);
  29785. + DWC_SPINLOCK(core_if->lock);
  29786. + core_if->op_state = B_HOST;
  29787. + }
  29788. + } else {
  29789. + gotgctl.d32 = 0;
  29790. + gotgctl.b.hnpreq = 1;
  29791. + gotgctl.b.devhnpen = 1;
  29792. + DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0);
  29793. + DWC_DEBUGPL(DBG_ANY, "HNP Failed\n");
  29794. + __DWC_ERROR("Device Not Connected/Responding\n");
  29795. + }
  29796. + }
  29797. + if (gotgint.b.hstnegdet) {
  29798. + /* The disconnect interrupt is set at the same time as
  29799. + * Host Negotiation Detected. During the mode
  29800. + * switch all interrupts are cleared so the disconnect
  29801. + * interrupt handler will not get executed.
  29802. + */
  29803. + DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
  29804. + "Host Negotiation Detected++ (%s)\n",
  29805. + (dwc_otg_is_host_mode(core_if) ? "Host" :
  29806. + "Device"));
  29807. + if (dwc_otg_is_device_mode(core_if)) {
  29808. + DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n",
  29809. + core_if->op_state);
  29810. + DWC_SPINUNLOCK(core_if->lock);
  29811. + cil_hcd_disconnect(core_if);
  29812. + cil_pcd_start(core_if);
  29813. + DWC_SPINLOCK(core_if->lock);
  29814. + core_if->op_state = A_PERIPHERAL;
  29815. + } else {
  29816. + /*
  29817. + * Need to disable SOF interrupt immediately. When
  29818. + * switching from device to host, the PCD interrupt
  29819. + * handler won't handle the interrupt if host mode is
  29820. + * already set. The HCD interrupt handler won't get
  29821. + * called if the HCD state is HALT. This means that
  29822. + * the interrupt does not get handled and Linux
  29823. + * complains loudly.
  29824. + */
  29825. + gintmsk.d32 = 0;
  29826. + gintmsk.b.sofintr = 1;
  29827. + DWC_MODIFY_REG32(&global_regs->gintmsk, gintmsk.d32, 0);
  29828. + DWC_SPINUNLOCK(core_if->lock);
  29829. + cil_pcd_stop(core_if);
  29830. + cil_hcd_start(core_if);
  29831. + DWC_SPINLOCK(core_if->lock);
  29832. + core_if->op_state = A_HOST;
  29833. + }
  29834. + }
  29835. + if (gotgint.b.adevtoutchng) {
  29836. + DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: "
  29837. + "A-Device Timeout Change++\n");
  29838. + }
  29839. + if (gotgint.b.debdone) {
  29840. + DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " "Debounce Done++\n");
  29841. + }
  29842. +
  29843. + /* Clear GOTGINT */
  29844. + DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, gotgint.d32);
  29845. +
  29846. + return 1;
  29847. +}
  29848. +
  29849. +void w_conn_id_status_change(void *p)
  29850. +{
  29851. + dwc_otg_core_if_t *core_if = p;
  29852. + uint32_t count = 0;
  29853. + gotgctl_data_t gotgctl = {.d32 = 0 };
  29854. +
  29855. + gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
  29856. + DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32);
  29857. + DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts);
  29858. +
  29859. + /* B-Device connector (Device Mode) */
  29860. + if (gotgctl.b.conidsts) {
  29861. + /* Wait for switch to device mode. */
  29862. + while (!dwc_otg_is_device_mode(core_if)) {
  29863. + DWC_PRINTF("Waiting for Peripheral Mode, Mode=%s\n",
  29864. + (dwc_otg_is_host_mode(core_if) ? "Host" :
  29865. + "Peripheral"));
  29866. + dwc_mdelay(100);
  29867. + if (++count > 10000)
  29868. + break;
  29869. + }
  29870. + DWC_ASSERT(++count < 10000,
  29871. + "Connection id status change timed out");
  29872. + core_if->op_state = B_PERIPHERAL;
  29873. + dwc_otg_core_init(core_if);
  29874. + dwc_otg_enable_global_interrupts(core_if);
  29875. + cil_pcd_start(core_if);
  29876. + } else {
  29877. + /* A-Device connector (Host Mode) */
  29878. + while (!dwc_otg_is_host_mode(core_if)) {
  29879. + DWC_PRINTF("Waiting for Host Mode, Mode=%s\n",
  29880. + (dwc_otg_is_host_mode(core_if) ? "Host" :
  29881. + "Peripheral"));
  29882. + dwc_mdelay(100);
  29883. + if (++count > 10000)
  29884. + break;
  29885. + }
  29886. + DWC_ASSERT(++count < 10000,
  29887. + "Connection id status change timed out");
  29888. + core_if->op_state = A_HOST;
  29889. + /*
  29890. + * Initialize the Core for Host mode.
  29891. + */
  29892. + dwc_otg_core_init(core_if);
  29893. + dwc_otg_enable_global_interrupts(core_if);
  29894. + cil_hcd_start(core_if);
  29895. + }
  29896. +}
  29897. +
  29898. +/**
  29899. + * This function handles the Connector ID Status Change Interrupt. It
  29900. + * reads the OTG Interrupt Register (GOTCTL) to determine whether this
  29901. + * is a Device to Host Mode transition or a Host Mode to Device
  29902. + * Transition.
  29903. + *
  29904. + * This only occurs when the cable is connected/removed from the PHY
  29905. + * connector.
  29906. + *
  29907. + * @param core_if Programming view of DWC_otg controller.
  29908. + */
  29909. +int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t * core_if)
  29910. +{
  29911. +
  29912. + /*
  29913. + * Need to disable SOF interrupt immediately. If switching from device
  29914. + * to host, the PCD interrupt handler won't handle the interrupt if
  29915. + * host mode is already set. The HCD interrupt handler won't get
  29916. + * called if the HCD state is HALT. This means that the interrupt does
  29917. + * not get handled and Linux complains loudly.
  29918. + */
  29919. + gintmsk_data_t gintmsk = {.d32 = 0 };
  29920. + gintsts_data_t gintsts = {.d32 = 0 };
  29921. +
  29922. + gintmsk.b.sofintr = 1;
  29923. + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
  29924. +
  29925. + DWC_DEBUGPL(DBG_CIL,
  29926. + " ++Connector ID Status Change Interrupt++ (%s)\n",
  29927. + (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"));
  29928. +
  29929. + DWC_SPINUNLOCK(core_if->lock);
  29930. +
  29931. + /*
  29932. + * Need to schedule a work, as there are possible DELAY function calls
  29933. + * Release lock before scheduling workq as it holds spinlock during scheduling
  29934. + */
  29935. +
  29936. + DWC_WORKQ_SCHEDULE(core_if->wq_otg, w_conn_id_status_change,
  29937. + core_if, "connection id status change");
  29938. + DWC_SPINLOCK(core_if->lock);
  29939. +
  29940. + /* Set flag and clear interrupt */
  29941. + gintsts.b.conidstschng = 1;
  29942. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
  29943. +
  29944. + return 1;
  29945. +}
  29946. +
  29947. +/**
  29948. + * This interrupt indicates that a device is initiating the Session
  29949. + * Request Protocol to request the host to turn on bus power so a new
  29950. + * session can begin. The handler responds by turning on bus power. If
  29951. + * the DWC_otg controller is in low power mode, the handler brings the
  29952. + * controller out of low power mode before turning on bus power.
  29953. + *
  29954. + * @param core_if Programming view of DWC_otg controller.
  29955. + */
  29956. +int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t * core_if)
  29957. +{
  29958. + gintsts_data_t gintsts;
  29959. +
  29960. +#ifndef DWC_HOST_ONLY
  29961. + DWC_DEBUGPL(DBG_ANY, "++Session Request Interrupt++\n");
  29962. +
  29963. + if (dwc_otg_is_device_mode(core_if)) {
  29964. + DWC_PRINTF("SRP: Device mode\n");
  29965. + } else {
  29966. + hprt0_data_t hprt0;
  29967. + DWC_PRINTF("SRP: Host mode\n");
  29968. +
  29969. + /* Turn on the port power bit. */
  29970. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  29971. + hprt0.b.prtpwr = 1;
  29972. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  29973. +
  29974. + /* Start the Connection timer. So a message can be displayed
  29975. + * if connect does not occur within 10 seconds. */
  29976. + cil_hcd_session_start(core_if);
  29977. + }
  29978. +#endif
  29979. +
  29980. + /* Clear interrupt */
  29981. + gintsts.d32 = 0;
  29982. + gintsts.b.sessreqintr = 1;
  29983. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
  29984. +
  29985. + return 1;
  29986. +}
  29987. +
  29988. +void w_wakeup_detected(void *p)
  29989. +{
  29990. + dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) p;
  29991. + /*
  29992. + * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms
  29993. + * so that OPT tests pass with all PHYs).
  29994. + */
  29995. + hprt0_data_t hprt0 = {.d32 = 0 };
  29996. +#if 0
  29997. + pcgcctl_data_t pcgcctl = {.d32 = 0 };
  29998. + /* Restart the Phy Clock */
  29999. + pcgcctl.b.stoppclk = 1;
  30000. + DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
  30001. + dwc_udelay(10);
  30002. +#endif //0
  30003. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  30004. + DWC_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32);
  30005. +// dwc_mdelay(70);
  30006. + hprt0.b.prtres = 0; /* Resume */
  30007. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  30008. + DWC_DEBUGPL(DBG_ANY, "Clear Resume: HPRT0=%0x\n",
  30009. + DWC_READ_REG32(core_if->host_if->hprt0));
  30010. +
  30011. + cil_hcd_resume(core_if);
  30012. +
  30013. + /** Change to L0 state*/
  30014. + core_if->lx_state = DWC_OTG_L0;
  30015. +}
  30016. +
  30017. +/**
  30018. + * This interrupt indicates that the DWC_otg controller has detected a
  30019. + * resume or remote wakeup sequence. If the DWC_otg controller is in
  30020. + * low power mode, the handler must brings the controller out of low
  30021. + * power mode. The controller automatically begins resume
  30022. + * signaling. The handler schedules a time to stop resume signaling.
  30023. + */
  30024. +int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t * core_if)
  30025. +{
  30026. + gintsts_data_t gintsts;
  30027. +
  30028. + DWC_DEBUGPL(DBG_ANY,
  30029. + "++Resume and Remote Wakeup Detected Interrupt++\n");
  30030. +
  30031. + DWC_PRINTF("%s lxstate = %d\n", __func__, core_if->lx_state);
  30032. +
  30033. + if (dwc_otg_is_device_mode(core_if)) {
  30034. + dctl_data_t dctl = {.d32 = 0 };
  30035. + DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n",
  30036. + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->
  30037. + dsts));
  30038. + if (core_if->lx_state == DWC_OTG_L2) {
  30039. +#ifdef PARTIAL_POWER_DOWN
  30040. + if (core_if->hwcfg4.b.power_optimiz) {
  30041. + pcgcctl_data_t power = {.d32 = 0 };
  30042. +
  30043. + power.d32 = DWC_READ_REG32(core_if->pcgcctl);
  30044. + DWC_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n",
  30045. + power.d32);
  30046. +
  30047. + power.b.stoppclk = 0;
  30048. + DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
  30049. +
  30050. + power.b.pwrclmp = 0;
  30051. + DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
  30052. +
  30053. + power.b.rstpdwnmodule = 0;
  30054. + DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
  30055. + }
  30056. +#endif
  30057. + /* Clear the Remote Wakeup Signaling */
  30058. + dctl.b.rmtwkupsig = 1;
  30059. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
  30060. + dctl, dctl.d32, 0);
  30061. +
  30062. + DWC_SPINUNLOCK(core_if->lock);
  30063. + if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
  30064. + core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
  30065. + }
  30066. + DWC_SPINLOCK(core_if->lock);
  30067. + } else {
  30068. + glpmcfg_data_t lpmcfg;
  30069. + lpmcfg.d32 =
  30070. + DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
  30071. + lpmcfg.b.hird_thres &= (~(1 << 4));
  30072. + DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg,
  30073. + lpmcfg.d32);
  30074. + }
  30075. + /** Change to L0 state*/
  30076. + core_if->lx_state = DWC_OTG_L0;
  30077. + } else {
  30078. + if (core_if->lx_state != DWC_OTG_L1) {
  30079. + pcgcctl_data_t pcgcctl = {.d32 = 0 };
  30080. +
  30081. + /* Restart the Phy Clock */
  30082. + pcgcctl.b.stoppclk = 1;
  30083. + DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
  30084. + DWC_TIMER_SCHEDULE(core_if->wkp_timer, 71);
  30085. + } else {
  30086. + /** Change to L0 state*/
  30087. + core_if->lx_state = DWC_OTG_L0;
  30088. + }
  30089. + }
  30090. +
  30091. + /* Clear interrupt */
  30092. + gintsts.d32 = 0;
  30093. + gintsts.b.wkupintr = 1;
  30094. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
  30095. +
  30096. + return 1;
  30097. +}
  30098. +
  30099. +/**
  30100. + * This interrupt indicates that the Wakeup Logic has detected a
  30101. + * Device disconnect.
  30102. + */
  30103. +static int32_t dwc_otg_handle_pwrdn_disconnect_intr(dwc_otg_core_if_t *core_if)
  30104. +{
  30105. + gpwrdn_data_t gpwrdn = { .d32 = 0 };
  30106. + gpwrdn_data_t gpwrdn_temp = { .d32 = 0 };
  30107. + gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
  30108. +
  30109. + DWC_PRINTF("%s called\n", __FUNCTION__);
  30110. +
  30111. + if (!core_if->hibernation_suspend) {
  30112. + DWC_PRINTF("Already exited from Hibernation\n");
  30113. + return 1;
  30114. + }
  30115. +
  30116. + /* Switch on the voltage to the core */
  30117. + gpwrdn.b.pwrdnswtch = 1;
  30118. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30119. + dwc_udelay(10);
  30120. +
  30121. + /* Reset the core */
  30122. + gpwrdn.d32 = 0;
  30123. + gpwrdn.b.pwrdnrstn = 1;
  30124. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30125. + dwc_udelay(10);
  30126. +
  30127. + /* Disable power clamps*/
  30128. + gpwrdn.d32 = 0;
  30129. + gpwrdn.b.pwrdnclmp = 1;
  30130. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30131. +
  30132. + /* Remove reset the core signal */
  30133. + gpwrdn.d32 = 0;
  30134. + gpwrdn.b.pwrdnrstn = 1;
  30135. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
  30136. + dwc_udelay(10);
  30137. +
  30138. + /* Disable PMU interrupt */
  30139. + gpwrdn.d32 = 0;
  30140. + gpwrdn.b.pmuintsel = 1;
  30141. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30142. +
  30143. + core_if->hibernation_suspend = 0;
  30144. +
  30145. + /* Disable PMU */
  30146. + gpwrdn.d32 = 0;
  30147. + gpwrdn.b.pmuactv = 1;
  30148. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30149. + dwc_udelay(10);
  30150. +
  30151. + if (gpwrdn_temp.b.idsts) {
  30152. + core_if->op_state = B_PERIPHERAL;
  30153. + dwc_otg_core_init(core_if);
  30154. + dwc_otg_enable_global_interrupts(core_if);
  30155. + cil_pcd_start(core_if);
  30156. + } else {
  30157. + core_if->op_state = A_HOST;
  30158. + dwc_otg_core_init(core_if);
  30159. + dwc_otg_enable_global_interrupts(core_if);
  30160. + cil_hcd_start(core_if);
  30161. + }
  30162. +
  30163. + return 1;
  30164. +}
  30165. +
  30166. +/**
  30167. + * This interrupt indicates that the Wakeup Logic has detected a
  30168. + * remote wakeup sequence.
  30169. + */
  30170. +static int32_t dwc_otg_handle_pwrdn_wakeup_detected_intr(dwc_otg_core_if_t * core_if)
  30171. +{
  30172. + gpwrdn_data_t gpwrdn = {.d32 = 0 };
  30173. + DWC_DEBUGPL(DBG_ANY,
  30174. + "++Powerdown Remote Wakeup Detected Interrupt++\n");
  30175. +
  30176. + if (!core_if->hibernation_suspend) {
  30177. + DWC_PRINTF("Already exited from Hibernation\n");
  30178. + return 1;
  30179. + }
  30180. +
  30181. + gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
  30182. + if (gpwrdn.b.idsts) { // Device Mode
  30183. + if ((core_if->power_down == 2)
  30184. + && (core_if->hibernation_suspend == 1)) {
  30185. + dwc_otg_device_hibernation_restore(core_if, 0, 0);
  30186. + }
  30187. + } else {
  30188. + if ((core_if->power_down == 2)
  30189. + && (core_if->hibernation_suspend == 1)) {
  30190. + dwc_otg_host_hibernation_restore(core_if, 1, 0);
  30191. + }
  30192. + }
  30193. + return 1;
  30194. +}
  30195. +
  30196. +static int32_t dwc_otg_handle_pwrdn_idsts_change(dwc_otg_device_t *otg_dev)
  30197. +{
  30198. + gpwrdn_data_t gpwrdn = {.d32 = 0 };
  30199. + gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
  30200. + dwc_otg_core_if_t *core_if = otg_dev->core_if;
  30201. +
  30202. + DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
  30203. + gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
  30204. + if (core_if->power_down == 2) {
  30205. + if (!core_if->hibernation_suspend) {
  30206. + DWC_PRINTF("Already exited from Hibernation\n");
  30207. + return 1;
  30208. + }
  30209. + DWC_DEBUGPL(DBG_ANY, "Exit from hibernation on ID sts change\n");
  30210. + /* Switch on the voltage to the core */
  30211. + gpwrdn.b.pwrdnswtch = 1;
  30212. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30213. + dwc_udelay(10);
  30214. +
  30215. + /* Reset the core */
  30216. + gpwrdn.d32 = 0;
  30217. + gpwrdn.b.pwrdnrstn = 1;
  30218. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30219. + dwc_udelay(10);
  30220. +
  30221. + /* Disable power clamps */
  30222. + gpwrdn.d32 = 0;
  30223. + gpwrdn.b.pwrdnclmp = 1;
  30224. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30225. +
  30226. + /* Remove reset the core signal */
  30227. + gpwrdn.d32 = 0;
  30228. + gpwrdn.b.pwrdnrstn = 1;
  30229. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
  30230. + dwc_udelay(10);
  30231. +
  30232. + /* Disable PMU interrupt */
  30233. + gpwrdn.d32 = 0;
  30234. + gpwrdn.b.pmuintsel = 1;
  30235. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30236. +
  30237. + /*Indicates that we are exiting from hibernation */
  30238. + core_if->hibernation_suspend = 0;
  30239. +
  30240. + /* Disable PMU */
  30241. + gpwrdn.d32 = 0;
  30242. + gpwrdn.b.pmuactv = 1;
  30243. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30244. + dwc_udelay(10);
  30245. +
  30246. + gpwrdn.d32 = core_if->gr_backup->gpwrdn_local;
  30247. + if (gpwrdn.b.dis_vbus == 1) {
  30248. + gpwrdn.d32 = 0;
  30249. + gpwrdn.b.dis_vbus = 1;
  30250. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30251. + }
  30252. +
  30253. + if (gpwrdn_temp.b.idsts) {
  30254. + core_if->op_state = B_PERIPHERAL;
  30255. + dwc_otg_core_init(core_if);
  30256. + dwc_otg_enable_global_interrupts(core_if);
  30257. + cil_pcd_start(core_if);
  30258. + } else {
  30259. + core_if->op_state = A_HOST;
  30260. + dwc_otg_core_init(core_if);
  30261. + dwc_otg_enable_global_interrupts(core_if);
  30262. + cil_hcd_start(core_if);
  30263. + }
  30264. + }
  30265. +
  30266. + if (core_if->adp_enable) {
  30267. + uint8_t is_host = 0;
  30268. + DWC_SPINUNLOCK(core_if->lock);
  30269. + /* Change the core_if's lock to hcd/pcd lock depend on mode? */
  30270. +#ifndef DWC_HOST_ONLY
  30271. + if (gpwrdn_temp.b.idsts)
  30272. + core_if->lock = otg_dev->pcd->lock;
  30273. +#endif
  30274. +#ifndef DWC_DEVICE_ONLY
  30275. + if (!gpwrdn_temp.b.idsts) {
  30276. + core_if->lock = otg_dev->hcd->lock;
  30277. + is_host = 1;
  30278. + }
  30279. +#endif
  30280. + DWC_PRINTF("RESTART ADP\n");
  30281. + if (core_if->adp.probe_enabled)
  30282. + dwc_otg_adp_probe_stop(core_if);
  30283. + if (core_if->adp.sense_enabled)
  30284. + dwc_otg_adp_sense_stop(core_if);
  30285. + if (core_if->adp.sense_timer_started)
  30286. + DWC_TIMER_CANCEL(core_if->adp.sense_timer);
  30287. + if (core_if->adp.vbuson_timer_started)
  30288. + DWC_TIMER_CANCEL(core_if->adp.vbuson_timer);
  30289. + core_if->adp.probe_timer_values[0] = -1;
  30290. + core_if->adp.probe_timer_values[1] = -1;
  30291. + core_if->adp.sense_timer_started = 0;
  30292. + core_if->adp.vbuson_timer_started = 0;
  30293. + core_if->adp.probe_counter = 0;
  30294. + core_if->adp.gpwrdn = 0;
  30295. +
  30296. + /* Disable PMU and restart ADP */
  30297. + gpwrdn_temp.d32 = 0;
  30298. + gpwrdn_temp.b.pmuactv = 1;
  30299. + gpwrdn_temp.b.pmuintsel = 1;
  30300. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30301. + DWC_PRINTF("Check point 1\n");
  30302. + dwc_mdelay(110);
  30303. + dwc_otg_adp_start(core_if, is_host);
  30304. + DWC_SPINLOCK(core_if->lock);
  30305. + }
  30306. +
  30307. +
  30308. + return 1;
  30309. +}
  30310. +
  30311. +static int32_t dwc_otg_handle_pwrdn_session_change(dwc_otg_core_if_t * core_if)
  30312. +{
  30313. + gpwrdn_data_t gpwrdn = {.d32 = 0 };
  30314. + int32_t otg_cap_param = core_if->core_params->otg_cap;
  30315. + DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
  30316. +
  30317. + gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
  30318. + if (core_if->power_down == 2) {
  30319. + if (!core_if->hibernation_suspend) {
  30320. + DWC_PRINTF("Already exited from Hibernation\n");
  30321. + return 1;
  30322. + }
  30323. +
  30324. + if ((otg_cap_param != DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
  30325. + otg_cap_param != DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) &&
  30326. + gpwrdn.b.bsessvld == 0) {
  30327. + /* Save gpwrdn register for further usage if stschng interrupt */
  30328. + core_if->gr_backup->gpwrdn_local =
  30329. + DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
  30330. + /*Exit from ISR and wait for stschng interrupt with bsessvld = 1 */
  30331. + return 1;
  30332. + }
  30333. +
  30334. + /* Switch on the voltage to the core */
  30335. + gpwrdn.d32 = 0;
  30336. + gpwrdn.b.pwrdnswtch = 1;
  30337. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30338. + dwc_udelay(10);
  30339. +
  30340. + /* Reset the core */
  30341. + gpwrdn.d32 = 0;
  30342. + gpwrdn.b.pwrdnrstn = 1;
  30343. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30344. + dwc_udelay(10);
  30345. +
  30346. + /* Disable power clamps */
  30347. + gpwrdn.d32 = 0;
  30348. + gpwrdn.b.pwrdnclmp = 1;
  30349. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30350. +
  30351. + /* Remove reset the core signal */
  30352. + gpwrdn.d32 = 0;
  30353. + gpwrdn.b.pwrdnrstn = 1;
  30354. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
  30355. + dwc_udelay(10);
  30356. +
  30357. + /* Disable PMU interrupt */
  30358. + gpwrdn.d32 = 0;
  30359. + gpwrdn.b.pmuintsel = 1;
  30360. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30361. + dwc_udelay(10);
  30362. +
  30363. + /*Indicates that we are exiting from hibernation */
  30364. + core_if->hibernation_suspend = 0;
  30365. +
  30366. + /* Disable PMU */
  30367. + gpwrdn.d32 = 0;
  30368. + gpwrdn.b.pmuactv = 1;
  30369. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30370. + dwc_udelay(10);
  30371. +
  30372. + core_if->op_state = B_PERIPHERAL;
  30373. + dwc_otg_core_init(core_if);
  30374. + dwc_otg_enable_global_interrupts(core_if);
  30375. + cil_pcd_start(core_if);
  30376. +
  30377. + if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE ||
  30378. + otg_cap_param == DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) {
  30379. + /*
  30380. + * Initiate SRP after initial ADP probe.
  30381. + */
  30382. + dwc_otg_initiate_srp(core_if);
  30383. + }
  30384. + }
  30385. +
  30386. + return 1;
  30387. +}
  30388. +/**
  30389. + * This interrupt indicates that the Wakeup Logic has detected a
  30390. + * status change either on IDDIG or BSessVld.
  30391. + */
  30392. +static uint32_t dwc_otg_handle_pwrdn_stschng_intr(dwc_otg_device_t *otg_dev)
  30393. +{
  30394. + int retval;
  30395. + gpwrdn_data_t gpwrdn = {.d32 = 0 };
  30396. + gpwrdn_data_t gpwrdn_temp = {.d32 = 0 };
  30397. + dwc_otg_core_if_t *core_if = otg_dev->core_if;
  30398. +
  30399. + DWC_PRINTF("%s called\n", __FUNCTION__);
  30400. +
  30401. + if (core_if->power_down == 2) {
  30402. + if (core_if->hibernation_suspend <= 0) {
  30403. + DWC_PRINTF("Already exited from Hibernation\n");
  30404. + return 1;
  30405. + } else
  30406. + gpwrdn_temp.d32 = core_if->gr_backup->gpwrdn_local;
  30407. +
  30408. + } else {
  30409. + gpwrdn_temp.d32 = core_if->adp.gpwrdn;
  30410. + }
  30411. +
  30412. + gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
  30413. +
  30414. + if (gpwrdn.b.idsts ^ gpwrdn_temp.b.idsts) {
  30415. + retval = dwc_otg_handle_pwrdn_idsts_change(otg_dev);
  30416. + } else if (gpwrdn.b.bsessvld ^ gpwrdn_temp.b.bsessvld) {
  30417. + retval = dwc_otg_handle_pwrdn_session_change(core_if);
  30418. + }
  30419. +
  30420. + return retval;
  30421. +}
  30422. +
  30423. +/**
  30424. + * This interrupt indicates that the Wakeup Logic has detected a
  30425. + * SRP.
  30426. + */
  30427. +static int32_t dwc_otg_handle_pwrdn_srp_intr(dwc_otg_core_if_t * core_if)
  30428. +{
  30429. + gpwrdn_data_t gpwrdn = {.d32 = 0 };
  30430. +
  30431. + DWC_PRINTF("%s called\n", __FUNCTION__);
  30432. +
  30433. + if (!core_if->hibernation_suspend) {
  30434. + DWC_PRINTF("Already exited from Hibernation\n");
  30435. + return 1;
  30436. + }
  30437. +#ifdef DWC_DEV_SRPCAP
  30438. + if (core_if->pwron_timer_started) {
  30439. + core_if->pwron_timer_started = 0;
  30440. + DWC_TIMER_CANCEL(core_if->pwron_timer);
  30441. + }
  30442. +#endif
  30443. +
  30444. + /* Switch on the voltage to the core */
  30445. + gpwrdn.b.pwrdnswtch = 1;
  30446. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30447. + dwc_udelay(10);
  30448. +
  30449. + /* Reset the core */
  30450. + gpwrdn.d32 = 0;
  30451. + gpwrdn.b.pwrdnrstn = 1;
  30452. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30453. + dwc_udelay(10);
  30454. +
  30455. + /* Disable power clamps */
  30456. + gpwrdn.d32 = 0;
  30457. + gpwrdn.b.pwrdnclmp = 1;
  30458. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30459. +
  30460. + /* Remove reset the core signal */
  30461. + gpwrdn.d32 = 0;
  30462. + gpwrdn.b.pwrdnrstn = 1;
  30463. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
  30464. + dwc_udelay(10);
  30465. +
  30466. + /* Disable PMU interrupt */
  30467. + gpwrdn.d32 = 0;
  30468. + gpwrdn.b.pmuintsel = 1;
  30469. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30470. +
  30471. + /* Indicates that we are exiting from hibernation */
  30472. + core_if->hibernation_suspend = 0;
  30473. +
  30474. + /* Disable PMU */
  30475. + gpwrdn.d32 = 0;
  30476. + gpwrdn.b.pmuactv = 1;
  30477. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30478. + dwc_udelay(10);
  30479. +
  30480. + /* Programm Disable VBUS to 0 */
  30481. + gpwrdn.d32 = 0;
  30482. + gpwrdn.b.dis_vbus = 1;
  30483. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  30484. +
  30485. + /*Initialize the core as Host */
  30486. + core_if->op_state = A_HOST;
  30487. + dwc_otg_core_init(core_if);
  30488. + dwc_otg_enable_global_interrupts(core_if);
  30489. + cil_hcd_start(core_if);
  30490. +
  30491. + return 1;
  30492. +}
  30493. +
  30494. +/** This interrupt indicates that restore command after Hibernation
  30495. + * was completed by the core. */
  30496. +int32_t dwc_otg_handle_restore_done_intr(dwc_otg_core_if_t * core_if)
  30497. +{
  30498. + pcgcctl_data_t pcgcctl;
  30499. + DWC_DEBUGPL(DBG_ANY, "++Restore Done Interrupt++\n");
  30500. +
  30501. + //TODO De-assert restore signal. 8.a
  30502. + pcgcctl.d32 = DWC_READ_REG32(core_if->pcgcctl);
  30503. + if (pcgcctl.b.restoremode == 1) {
  30504. + gintmsk_data_t gintmsk = {.d32 = 0 };
  30505. + /*
  30506. + * If restore mode is Remote Wakeup,
  30507. + * unmask Remote Wakeup interrupt.
  30508. + */
  30509. + gintmsk.b.wkupintr = 1;
  30510. + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
  30511. + 0, gintmsk.d32);
  30512. + }
  30513. +
  30514. + return 1;
  30515. +}
  30516. +
  30517. +/**
  30518. + * This interrupt indicates that a device has been disconnected from
  30519. + * the root port.
  30520. + */
  30521. +int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if)
  30522. +{
  30523. + gintsts_data_t gintsts;
  30524. +
  30525. + DWC_DEBUGPL(DBG_ANY, "++Disconnect Detected Interrupt++ (%s) %s\n",
  30526. + (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"),
  30527. + op_state_str(core_if));
  30528. +
  30529. +/** @todo Consolidate this if statement. */
  30530. +#ifndef DWC_HOST_ONLY
  30531. + if (core_if->op_state == B_HOST) {
  30532. + /* If in device mode Disconnect and stop the HCD, then
  30533. + * start the PCD. */
  30534. + DWC_SPINUNLOCK(core_if->lock);
  30535. + cil_hcd_disconnect(core_if);
  30536. + cil_pcd_start(core_if);
  30537. + DWC_SPINLOCK(core_if->lock);
  30538. + core_if->op_state = B_PERIPHERAL;
  30539. + } else if (dwc_otg_is_device_mode(core_if)) {
  30540. + gotgctl_data_t gotgctl = {.d32 = 0 };
  30541. + gotgctl.d32 =
  30542. + DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
  30543. + if (gotgctl.b.hstsethnpen == 1) {
  30544. + /* Do nothing, if HNP in process the OTG
  30545. + * interrupt "Host Negotiation Detected"
  30546. + * interrupt will do the mode switch.
  30547. + */
  30548. + } else if (gotgctl.b.devhnpen == 0) {
  30549. + /* If in device mode Disconnect and stop the HCD, then
  30550. + * start the PCD. */
  30551. + DWC_SPINUNLOCK(core_if->lock);
  30552. + cil_hcd_disconnect(core_if);
  30553. + cil_pcd_start(core_if);
  30554. + DWC_SPINLOCK(core_if->lock);
  30555. + core_if->op_state = B_PERIPHERAL;
  30556. + } else {
  30557. + DWC_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n");
  30558. + }
  30559. + } else {
  30560. + if (core_if->op_state == A_HOST) {
  30561. + /* A-Cable still connected but device disconnected. */
  30562. + cil_hcd_disconnect(core_if);
  30563. + if (core_if->adp_enable) {
  30564. + gpwrdn_data_t gpwrdn = { .d32 = 0 };
  30565. + cil_hcd_stop(core_if);
  30566. + /* Enable Power Down Logic */
  30567. + gpwrdn.b.pmuintsel = 1;
  30568. + gpwrdn.b.pmuactv = 1;
  30569. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  30570. + gpwrdn, 0, gpwrdn.d32);
  30571. + dwc_otg_adp_probe_start(core_if);
  30572. +
  30573. + /* Power off the core */
  30574. + if (core_if->power_down == 2) {
  30575. + gpwrdn.d32 = 0;
  30576. + gpwrdn.b.pwrdnswtch = 1;
  30577. + DWC_MODIFY_REG32
  30578. + (&core_if->core_global_regs->gpwrdn,
  30579. + gpwrdn.d32, 0);
  30580. + }
  30581. + }
  30582. + }
  30583. + }
  30584. +#endif
  30585. + /* Change to L3(OFF) state */
  30586. + core_if->lx_state = DWC_OTG_L3;
  30587. +
  30588. + gintsts.d32 = 0;
  30589. + gintsts.b.disconnect = 1;
  30590. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
  30591. + return 1;
  30592. +}
  30593. +
  30594. +/**
  30595. + * This interrupt indicates that SUSPEND state has been detected on
  30596. + * the USB.
  30597. + *
  30598. + * For HNP the USB Suspend interrupt signals the change from
  30599. + * "a_peripheral" to "a_host".
  30600. + *
  30601. + * When power management is enabled the core will be put in low power
  30602. + * mode.
  30603. + */
  30604. +int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if)
  30605. +{
  30606. + dsts_data_t dsts;
  30607. + gintsts_data_t gintsts;
  30608. + dcfg_data_t dcfg;
  30609. +
  30610. + DWC_DEBUGPL(DBG_ANY, "USB SUSPEND\n");
  30611. +
  30612. + if (dwc_otg_is_device_mode(core_if)) {
  30613. + /* Check the Device status register to determine if the Suspend
  30614. + * state is active. */
  30615. + dsts.d32 =
  30616. + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
  30617. + DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32);
  30618. + DWC_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d "
  30619. + "HWCFG4.power Optimize=%d\n",
  30620. + dsts.b.suspsts, core_if->hwcfg4.b.power_optimiz);
  30621. +
  30622. +#ifdef PARTIAL_POWER_DOWN
  30623. +/** @todo Add a module parameter for power management. */
  30624. +
  30625. + if (dsts.b.suspsts && core_if->hwcfg4.b.power_optimiz) {
  30626. + pcgcctl_data_t power = {.d32 = 0 };
  30627. + DWC_DEBUGPL(DBG_CIL, "suspend\n");
  30628. +
  30629. + power.b.pwrclmp = 1;
  30630. + DWC_WRITE_REG32(core_if->pcgcctl, power.d32);
  30631. +
  30632. + power.b.rstpdwnmodule = 1;
  30633. + DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32);
  30634. +
  30635. + power.b.stoppclk = 1;
  30636. + DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32);
  30637. +
  30638. + } else {
  30639. + DWC_DEBUGPL(DBG_ANY, "disconnect?\n");
  30640. + }
  30641. +#endif
  30642. + /* PCD callback for suspend. Release the lock inside of callback function */
  30643. + cil_pcd_suspend(core_if);
  30644. + if (core_if->power_down == 2)
  30645. + {
  30646. + dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
  30647. + DWC_DEBUGPL(DBG_ANY,"lx_state = %08x\n",core_if->lx_state);
  30648. + DWC_DEBUGPL(DBG_ANY," device address = %08d\n",dcfg.b.devaddr);
  30649. +
  30650. + if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) {
  30651. + pcgcctl_data_t pcgcctl = {.d32 = 0 };
  30652. + gpwrdn_data_t gpwrdn = {.d32 = 0 };
  30653. + gusbcfg_data_t gusbcfg = {.d32 = 0 };
  30654. +
  30655. + /* Change to L2(suspend) state */
  30656. + core_if->lx_state = DWC_OTG_L2;
  30657. +
  30658. + /* Clear interrupt in gintsts */
  30659. + gintsts.d32 = 0;
  30660. + gintsts.b.usbsuspend = 1;
  30661. + DWC_WRITE_REG32(&core_if->core_global_regs->
  30662. + gintsts, gintsts.d32);
  30663. + DWC_PRINTF("Start of hibernation completed\n");
  30664. + dwc_otg_save_global_regs(core_if);
  30665. + dwc_otg_save_dev_regs(core_if);
  30666. +
  30667. + gusbcfg.d32 =
  30668. + DWC_READ_REG32(&core_if->core_global_regs->
  30669. + gusbcfg);
  30670. + if (gusbcfg.b.ulpi_utmi_sel == 1) {
  30671. + /* ULPI interface */
  30672. + /* Suspend the Phy Clock */
  30673. + pcgcctl.d32 = 0;
  30674. + pcgcctl.b.stoppclk = 1;
  30675. + DWC_MODIFY_REG32(core_if->pcgcctl, 0,
  30676. + pcgcctl.d32);
  30677. + dwc_udelay(10);
  30678. + gpwrdn.b.pmuactv = 1;
  30679. + DWC_MODIFY_REG32(&core_if->
  30680. + core_global_regs->
  30681. + gpwrdn, 0, gpwrdn.d32);
  30682. + } else {
  30683. + /* UTMI+ Interface */
  30684. + gpwrdn.b.pmuactv = 1;
  30685. + DWC_MODIFY_REG32(&core_if->
  30686. + core_global_regs->
  30687. + gpwrdn, 0, gpwrdn.d32);
  30688. + dwc_udelay(10);
  30689. + pcgcctl.b.stoppclk = 1;
  30690. + DWC_MODIFY_REG32(core_if->pcgcctl, 0,
  30691. + pcgcctl.d32);
  30692. + dwc_udelay(10);
  30693. + }
  30694. +
  30695. + /* Set flag to indicate that we are in hibernation */
  30696. + core_if->hibernation_suspend = 1;
  30697. + /* Enable interrupts from wake up logic */
  30698. + gpwrdn.d32 = 0;
  30699. + gpwrdn.b.pmuintsel = 1;
  30700. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  30701. + gpwrdn, 0, gpwrdn.d32);
  30702. + dwc_udelay(10);
  30703. +
  30704. + /* Unmask device mode interrupts in GPWRDN */
  30705. + gpwrdn.d32 = 0;
  30706. + gpwrdn.b.rst_det_msk = 1;
  30707. + gpwrdn.b.lnstchng_msk = 1;
  30708. + gpwrdn.b.sts_chngint_msk = 1;
  30709. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  30710. + gpwrdn, 0, gpwrdn.d32);
  30711. + dwc_udelay(10);
  30712. +
  30713. + /* Enable Power Down Clamp */
  30714. + gpwrdn.d32 = 0;
  30715. + gpwrdn.b.pwrdnclmp = 1;
  30716. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  30717. + gpwrdn, 0, gpwrdn.d32);
  30718. + dwc_udelay(10);
  30719. +
  30720. + /* Switch off VDD */
  30721. + gpwrdn.d32 = 0;
  30722. + gpwrdn.b.pwrdnswtch = 1;
  30723. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  30724. + gpwrdn, 0, gpwrdn.d32);
  30725. +
  30726. + /* Save gpwrdn register for further usage if stschng interrupt */
  30727. + core_if->gr_backup->gpwrdn_local =
  30728. + DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
  30729. + DWC_PRINTF("Hibernation completed\n");
  30730. +
  30731. + return 1;
  30732. + }
  30733. + } else if (core_if->power_down == 3) {
  30734. + pcgcctl_data_t pcgcctl = {.d32 = 0 };
  30735. + dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
  30736. + DWC_DEBUGPL(DBG_ANY, "lx_state = %08x\n",core_if->lx_state);
  30737. + DWC_DEBUGPL(DBG_ANY, " device address = %08d\n",dcfg.b.devaddr);
  30738. +
  30739. + if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) {
  30740. + DWC_DEBUGPL(DBG_ANY, "Start entering to extended hibernation\n");
  30741. + core_if->xhib = 1;
  30742. +
  30743. + /* Clear interrupt in gintsts */
  30744. + gintsts.d32 = 0;
  30745. + gintsts.b.usbsuspend = 1;
  30746. + DWC_WRITE_REG32(&core_if->core_global_regs->
  30747. + gintsts, gintsts.d32);
  30748. +
  30749. + dwc_otg_save_global_regs(core_if);
  30750. + dwc_otg_save_dev_regs(core_if);
  30751. +
  30752. + /* Wait for 10 PHY clocks */
  30753. + dwc_udelay(10);
  30754. +
  30755. + /* Program GPIO register while entering to xHib */
  30756. + DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x1);
  30757. +
  30758. + pcgcctl.b.enbl_extnd_hiber = 1;
  30759. + DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
  30760. + DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
  30761. +
  30762. + pcgcctl.d32 = 0;
  30763. + pcgcctl.b.extnd_hiber_pwrclmp = 1;
  30764. + DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
  30765. +
  30766. + pcgcctl.d32 = 0;
  30767. + pcgcctl.b.extnd_hiber_switch = 1;
  30768. + core_if->gr_backup->xhib_gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
  30769. + core_if->gr_backup->xhib_pcgcctl = DWC_READ_REG32(core_if->pcgcctl) | pcgcctl.d32;
  30770. + DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
  30771. +
  30772. + DWC_DEBUGPL(DBG_ANY, "Finished entering to extended hibernation\n");
  30773. +
  30774. + return 1;
  30775. + }
  30776. + }
  30777. + } else {
  30778. + if (core_if->op_state == A_PERIPHERAL) {
  30779. + DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n");
  30780. + /* Clear the a_peripheral flag, back to a_host. */
  30781. + DWC_SPINUNLOCK(core_if->lock);
  30782. + cil_pcd_stop(core_if);
  30783. + cil_hcd_start(core_if);
  30784. + DWC_SPINLOCK(core_if->lock);
  30785. + core_if->op_state = A_HOST;
  30786. + }
  30787. + }
  30788. +
  30789. + /* Change to L2(suspend) state */
  30790. + core_if->lx_state = DWC_OTG_L2;
  30791. +
  30792. + /* Clear interrupt */
  30793. + gintsts.d32 = 0;
  30794. + gintsts.b.usbsuspend = 1;
  30795. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
  30796. +
  30797. + return 1;
  30798. +}
  30799. +
  30800. +static int32_t dwc_otg_handle_xhib_exit_intr(dwc_otg_core_if_t * core_if)
  30801. +{
  30802. + gpwrdn_data_t gpwrdn = {.d32 = 0 };
  30803. + pcgcctl_data_t pcgcctl = {.d32 = 0 };
  30804. + gahbcfg_data_t gahbcfg = {.d32 = 0 };
  30805. +
  30806. + dwc_udelay(10);
  30807. +
  30808. + /* Program GPIO register while entering to xHib */
  30809. + DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x0);
  30810. +
  30811. + pcgcctl.d32 = core_if->gr_backup->xhib_pcgcctl;
  30812. + pcgcctl.b.extnd_hiber_pwrclmp = 0;
  30813. + DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
  30814. + dwc_udelay(10);
  30815. +
  30816. + gpwrdn.d32 = core_if->gr_backup->xhib_gpwrdn;
  30817. + gpwrdn.b.restore = 1;
  30818. + DWC_WRITE_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32);
  30819. + dwc_udelay(10);
  30820. +
  30821. + restore_lpm_i2c_regs(core_if);
  30822. +
  30823. + pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
  30824. + pcgcctl.b.max_xcvrselect = 1;
  30825. + pcgcctl.b.ess_reg_restored = 0;
  30826. + pcgcctl.b.extnd_hiber_switch = 0;
  30827. + pcgcctl.b.extnd_hiber_pwrclmp = 0;
  30828. + pcgcctl.b.enbl_extnd_hiber = 1;
  30829. + DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
  30830. +
  30831. + gahbcfg.d32 = core_if->gr_backup->gahbcfg_local;
  30832. + gahbcfg.b.glblintrmsk = 1;
  30833. + DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32);
  30834. +
  30835. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF);
  30836. + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0x1 << 16);
  30837. +
  30838. + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg,
  30839. + core_if->gr_backup->gusbcfg_local);
  30840. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg,
  30841. + core_if->dr_backup->dcfg);
  30842. +
  30843. + pcgcctl.d32 = 0;
  30844. + pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
  30845. + pcgcctl.b.max_xcvrselect = 1;
  30846. + pcgcctl.d32 |= 0x608;
  30847. + DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
  30848. + dwc_udelay(10);
  30849. +
  30850. + pcgcctl.d32 = 0;
  30851. + pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14);
  30852. + pcgcctl.b.max_xcvrselect = 1;
  30853. + pcgcctl.b.ess_reg_restored = 1;
  30854. + pcgcctl.b.enbl_extnd_hiber = 1;
  30855. + pcgcctl.b.rstpdwnmodule = 1;
  30856. + pcgcctl.b.restoremode = 1;
  30857. + DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32);
  30858. +
  30859. + DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__);
  30860. +
  30861. + return 1;
  30862. +}
  30863. +
  30864. +#ifdef CONFIG_USB_DWC_OTG_LPM
  30865. +/**
  30866. + * This function hadles LPM transaction received interrupt.
  30867. + */
  30868. +static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if)
  30869. +{
  30870. + glpmcfg_data_t lpmcfg;
  30871. + gintsts_data_t gintsts;
  30872. +
  30873. + if (!core_if->core_params->lpm_enable) {
  30874. + DWC_PRINTF("Unexpected LPM interrupt\n");
  30875. + }
  30876. +
  30877. + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
  30878. + DWC_PRINTF("LPM config register = 0x%08x\n", lpmcfg.d32);
  30879. +
  30880. + if (dwc_otg_is_host_mode(core_if)) {
  30881. + cil_hcd_sleep(core_if);
  30882. + } else {
  30883. + lpmcfg.b.hird_thres |= (1 << 4);
  30884. + DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg,
  30885. + lpmcfg.d32);
  30886. + }
  30887. +
  30888. + /* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */
  30889. + dwc_udelay(10);
  30890. + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
  30891. + if (lpmcfg.b.prt_sleep_sts) {
  30892. + /* Save the current state */
  30893. + core_if->lx_state = DWC_OTG_L1;
  30894. + }
  30895. +
  30896. + /* Clear interrupt */
  30897. + gintsts.d32 = 0;
  30898. + gintsts.b.lpmtranrcvd = 1;
  30899. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
  30900. + return 1;
  30901. +}
  30902. +#endif /* CONFIG_USB_DWC_OTG_LPM */
  30903. +
  30904. +/**
  30905. + * This function returns the Core Interrupt register.
  30906. + */
  30907. +static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if)
  30908. +{
  30909. + gahbcfg_data_t gahbcfg = {.d32 = 0 };
  30910. + gintsts_data_t gintsts;
  30911. + gintmsk_data_t gintmsk;
  30912. + gintmsk_data_t gintmsk_common = {.d32 = 0 };
  30913. + gintmsk_common.b.wkupintr = 1;
  30914. + gintmsk_common.b.sessreqintr = 1;
  30915. + gintmsk_common.b.conidstschng = 1;
  30916. + gintmsk_common.b.otgintr = 1;
  30917. + gintmsk_common.b.modemismatch = 1;
  30918. + gintmsk_common.b.disconnect = 1;
  30919. + gintmsk_common.b.usbsuspend = 1;
  30920. +#ifdef CONFIG_USB_DWC_OTG_LPM
  30921. + gintmsk_common.b.lpmtranrcvd = 1;
  30922. +#endif
  30923. + gintmsk_common.b.restoredone = 1;
  30924. + /** @todo: The port interrupt occurs while in device
  30925. + * mode. Added code to CIL to clear the interrupt for now!
  30926. + */
  30927. + gintmsk_common.b.portintr = 1;
  30928. +
  30929. + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
  30930. + gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
  30931. + gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
  30932. +
  30933. +#ifdef DEBUG
  30934. + /* if any common interrupts set */
  30935. + if (gintsts.d32 & gintmsk_common.d32) {
  30936. + DWC_DEBUGPL(DBG_ANY, "gintsts=%08x gintmsk=%08x\n",
  30937. + gintsts.d32, gintmsk.d32);
  30938. + }
  30939. +#endif
  30940. + if (gahbcfg.b.glblintrmsk)
  30941. + return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
  30942. + else
  30943. + return 0;
  30944. +
  30945. +}
  30946. +
  30947. +/* MACRO for clearing interupt bits in GPWRDN register */
  30948. +#define CLEAR_GPWRDN_INTR(__core_if,__intr) \
  30949. +do { \
  30950. + gpwrdn_data_t gpwrdn = {.d32=0}; \
  30951. + gpwrdn.b.__intr = 1; \
  30952. + DWC_MODIFY_REG32(&__core_if->core_global_regs->gpwrdn, \
  30953. + 0, gpwrdn.d32); \
  30954. +} while (0)
  30955. +
  30956. +/**
  30957. + * Common interrupt handler.
  30958. + *
  30959. + * The common interrupts are those that occur in both Host and Device mode.
  30960. + * This handler handles the following interrupts:
  30961. + * - Mode Mismatch Interrupt
  30962. + * - Disconnect Interrupt
  30963. + * - OTG Interrupt
  30964. + * - Connector ID Status Change Interrupt
  30965. + * - Session Request Interrupt.
  30966. + * - Resume / Remote Wakeup Detected Interrupt.
  30967. + * - LPM Transaction Received Interrupt
  30968. + * - ADP Transaction Received Interrupt
  30969. + *
  30970. + */
  30971. +int32_t dwc_otg_handle_common_intr(void *dev)
  30972. +{
  30973. + int retval = 0;
  30974. + gintsts_data_t gintsts;
  30975. + gpwrdn_data_t gpwrdn = {.d32 = 0 };
  30976. + dwc_otg_device_t *otg_dev = dev;
  30977. + dwc_otg_core_if_t *core_if = otg_dev->core_if;
  30978. + gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
  30979. + if (dwc_otg_is_device_mode(core_if))
  30980. + core_if->frame_num = dwc_otg_get_frame_number(core_if);
  30981. +
  30982. + if (core_if->lock)
  30983. + DWC_SPINLOCK(core_if->lock);
  30984. +
  30985. + if (core_if->power_down == 3 && core_if->xhib == 1) {
  30986. + DWC_DEBUGPL(DBG_ANY, "Exiting from xHIB state\n");
  30987. + retval |= dwc_otg_handle_xhib_exit_intr(core_if);
  30988. + core_if->xhib = 2;
  30989. + if (core_if->lock)
  30990. + DWC_SPINUNLOCK(core_if->lock);
  30991. +
  30992. + return retval;
  30993. + }
  30994. +
  30995. + if (core_if->hibernation_suspend <= 0) {
  30996. + gintsts.d32 = dwc_otg_read_common_intr(core_if);
  30997. +
  30998. + if (gintsts.b.modemismatch) {
  30999. + retval |= dwc_otg_handle_mode_mismatch_intr(core_if);
  31000. + }
  31001. + if (gintsts.b.otgintr) {
  31002. + retval |= dwc_otg_handle_otg_intr(core_if);
  31003. + }
  31004. + if (gintsts.b.conidstschng) {
  31005. + retval |=
  31006. + dwc_otg_handle_conn_id_status_change_intr(core_if);
  31007. + }
  31008. + if (gintsts.b.disconnect) {
  31009. + retval |= dwc_otg_handle_disconnect_intr(core_if);
  31010. + }
  31011. + if (gintsts.b.sessreqintr) {
  31012. + retval |= dwc_otg_handle_session_req_intr(core_if);
  31013. + }
  31014. + if (gintsts.b.wkupintr) {
  31015. + retval |= dwc_otg_handle_wakeup_detected_intr(core_if);
  31016. + }
  31017. + if (gintsts.b.usbsuspend) {
  31018. + retval |= dwc_otg_handle_usb_suspend_intr(core_if);
  31019. + }
  31020. +#ifdef CONFIG_USB_DWC_OTG_LPM
  31021. + if (gintsts.b.lpmtranrcvd) {
  31022. + retval |= dwc_otg_handle_lpm_intr(core_if);
  31023. + }
  31024. +#endif
  31025. + if (gintsts.b.restoredone) {
  31026. + gintsts.d32 = 0;
  31027. + if (core_if->power_down == 2)
  31028. + core_if->hibernation_suspend = -1;
  31029. + else if (core_if->power_down == 3 && core_if->xhib == 2) {
  31030. + gpwrdn_data_t gpwrdn = {.d32 = 0 };
  31031. + pcgcctl_data_t pcgcctl = {.d32 = 0 };
  31032. + dctl_data_t dctl = {.d32 = 0 };
  31033. +
  31034. + DWC_WRITE_REG32(&core_if->core_global_regs->
  31035. + gintsts, 0xFFFFFFFF);
  31036. +
  31037. + DWC_DEBUGPL(DBG_ANY,
  31038. + "RESTORE DONE generated\n");
  31039. +
  31040. + gpwrdn.b.restore = 1;
  31041. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  31042. + dwc_udelay(10);
  31043. +
  31044. + pcgcctl.b.rstpdwnmodule = 1;
  31045. + DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
  31046. +
  31047. + DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, core_if->gr_backup->gusbcfg_local);
  31048. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, core_if->dr_backup->dcfg);
  31049. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, core_if->dr_backup->dctl);
  31050. + dwc_udelay(50);
  31051. +
  31052. + dctl.b.pwronprgdone = 1;
  31053. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
  31054. + dwc_udelay(10);
  31055. +
  31056. + dwc_otg_restore_global_regs(core_if);
  31057. + dwc_otg_restore_dev_regs(core_if, 0);
  31058. +
  31059. + dctl.d32 = 0;
  31060. + dctl.b.pwronprgdone = 1;
  31061. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
  31062. + dwc_udelay(10);
  31063. +
  31064. + pcgcctl.d32 = 0;
  31065. + pcgcctl.b.enbl_extnd_hiber = 1;
  31066. + DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
  31067. +
  31068. + /* The core will be in ON STATE */
  31069. + core_if->lx_state = DWC_OTG_L0;
  31070. + core_if->xhib = 0;
  31071. +
  31072. + DWC_SPINUNLOCK(core_if->lock);
  31073. + if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
  31074. + core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
  31075. + }
  31076. + DWC_SPINLOCK(core_if->lock);
  31077. +
  31078. + }
  31079. +
  31080. + gintsts.b.restoredone = 1;
  31081. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
  31082. + DWC_PRINTF(" --Restore done interrupt received-- \n");
  31083. + retval |= 1;
  31084. + }
  31085. + if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) {
  31086. + /* The port interrupt occurs while in device mode with HPRT0
  31087. + * Port Enable/Disable.
  31088. + */
  31089. + gintsts.d32 = 0;
  31090. + gintsts.b.portintr = 1;
  31091. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
  31092. + retval |= 1;
  31093. +
  31094. + }
  31095. + } else {
  31096. + DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32);
  31097. +
  31098. + if (gpwrdn.b.disconn_det && gpwrdn.b.disconn_det_msk) {
  31099. + CLEAR_GPWRDN_INTR(core_if, disconn_det);
  31100. + if (gpwrdn.b.linestate == 0) {
  31101. + dwc_otg_handle_pwrdn_disconnect_intr(core_if);
  31102. + } else {
  31103. + DWC_PRINTF("Disconnect detected while linestate is not 0\n");
  31104. + }
  31105. +
  31106. + retval |= 1;
  31107. + }
  31108. + if (gpwrdn.b.lnstschng && gpwrdn.b.lnstchng_msk) {
  31109. + CLEAR_GPWRDN_INTR(core_if, lnstschng);
  31110. + /* remote wakeup from hibernation */
  31111. + if (gpwrdn.b.linestate == 2 || gpwrdn.b.linestate == 1) {
  31112. + dwc_otg_handle_pwrdn_wakeup_detected_intr(core_if);
  31113. + } else {
  31114. + DWC_PRINTF("gpwrdn.linestate = %d\n", gpwrdn.b.linestate);
  31115. + }
  31116. + retval |= 1;
  31117. + }
  31118. + if (gpwrdn.b.rst_det && gpwrdn.b.rst_det_msk) {
  31119. + CLEAR_GPWRDN_INTR(core_if, rst_det);
  31120. + if (gpwrdn.b.linestate == 0) {
  31121. + DWC_PRINTF("Reset detected\n");
  31122. + retval |= dwc_otg_device_hibernation_restore(core_if, 0, 1);
  31123. + }
  31124. + }
  31125. + if (gpwrdn.b.srp_det && gpwrdn.b.srp_det_msk) {
  31126. + CLEAR_GPWRDN_INTR(core_if, srp_det);
  31127. + dwc_otg_handle_pwrdn_srp_intr(core_if);
  31128. + retval |= 1;
  31129. + }
  31130. + }
  31131. + /* Handle ADP interrupt here */
  31132. + if (gpwrdn.b.adp_int) {
  31133. + DWC_PRINTF("ADP interrupt\n");
  31134. + CLEAR_GPWRDN_INTR(core_if, adp_int);
  31135. + dwc_otg_adp_handle_intr(core_if);
  31136. + retval |= 1;
  31137. + }
  31138. + if (gpwrdn.b.sts_chngint && gpwrdn.b.sts_chngint_msk) {
  31139. + DWC_PRINTF("STS CHNG interrupt asserted\n");
  31140. + CLEAR_GPWRDN_INTR(core_if, sts_chngint);
  31141. + dwc_otg_handle_pwrdn_stschng_intr(otg_dev);
  31142. +
  31143. + retval |= 1;
  31144. + }
  31145. + if (core_if->lock)
  31146. + DWC_SPINUNLOCK(core_if->lock);
  31147. +
  31148. + return retval;
  31149. +}
  31150. --- /dev/null
  31151. +++ b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h
  31152. @@ -0,0 +1,705 @@
  31153. +/* ==========================================================================
  31154. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $
  31155. + * $Revision: #13 $
  31156. + * $Date: 2012/08/10 $
  31157. + * $Change: 2047372 $
  31158. + *
  31159. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  31160. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  31161. + * otherwise expressly agreed to in writing between Synopsys and you.
  31162. + *
  31163. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  31164. + * any End User Software License Agreement or Agreement for Licensed Product
  31165. + * with Synopsys or any supplement thereto. You are permitted to use and
  31166. + * redistribute this Software in source and binary forms, with or without
  31167. + * modification, provided that redistributions of source code must retain this
  31168. + * notice. You may not view, use, disclose, copy or distribute this file or
  31169. + * any information contained herein except pursuant to this license grant from
  31170. + * Synopsys. If you do not agree with this notice, including the disclaimer
  31171. + * below, then you are not authorized to use the Software.
  31172. + *
  31173. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  31174. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  31175. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  31176. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  31177. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  31178. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  31179. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  31180. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31181. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31182. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  31183. + * DAMAGE.
  31184. + * ========================================================================== */
  31185. +#if !defined(__DWC_CORE_IF_H__)
  31186. +#define __DWC_CORE_IF_H__
  31187. +
  31188. +#include "dwc_os.h"
  31189. +
  31190. +/** @file
  31191. + * This file defines DWC_OTG Core API
  31192. + */
  31193. +
  31194. +struct dwc_otg_core_if;
  31195. +typedef struct dwc_otg_core_if dwc_otg_core_if_t;
  31196. +
  31197. +/** Maximum number of Periodic FIFOs */
  31198. +#define MAX_PERIO_FIFOS 15
  31199. +/** Maximum number of Periodic FIFOs */
  31200. +#define MAX_TX_FIFOS 15
  31201. +
  31202. +/** Maximum number of Endpoints/HostChannels */
  31203. +#define MAX_EPS_CHANNELS 16
  31204. +
  31205. +extern dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * _reg_base_addr);
  31206. +extern void dwc_otg_core_init(dwc_otg_core_if_t * _core_if);
  31207. +extern void dwc_otg_cil_remove(dwc_otg_core_if_t * _core_if);
  31208. +
  31209. +extern void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * _core_if);
  31210. +extern void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * _core_if);
  31211. +
  31212. +extern uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if);
  31213. +extern uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if);
  31214. +
  31215. +extern uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if);
  31216. +
  31217. +/** This function should be called on every hardware interrupt. */
  31218. +extern int32_t dwc_otg_handle_common_intr(void *otg_dev);
  31219. +
  31220. +/** @name OTG Core Parameters */
  31221. +/** @{ */
  31222. +
  31223. +/**
  31224. + * Specifies the OTG capabilities. The driver will automatically
  31225. + * detect the value for this parameter if none is specified.
  31226. + * 0 - HNP and SRP capable (default)
  31227. + * 1 - SRP Only capable
  31228. + * 2 - No HNP/SRP capable
  31229. + */
  31230. +extern int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val);
  31231. +extern int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t * core_if);
  31232. +#define DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE 0
  31233. +#define DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE 1
  31234. +#define DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE 2
  31235. +#define dwc_param_otg_cap_default DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE
  31236. +
  31237. +extern int dwc_otg_set_param_opt(dwc_otg_core_if_t * core_if, int32_t val);
  31238. +extern int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t * core_if);
  31239. +#define dwc_param_opt_default 1
  31240. +
  31241. +/**
  31242. + * Specifies whether to use slave or DMA mode for accessing the data
  31243. + * FIFOs. The driver will automatically detect the value for this
  31244. + * parameter if none is specified.
  31245. + * 0 - Slave
  31246. + * 1 - DMA (default, if available)
  31247. + */
  31248. +extern int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t * core_if,
  31249. + int32_t val);
  31250. +extern int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t * core_if);
  31251. +#define dwc_param_dma_enable_default 1
  31252. +
  31253. +/**
  31254. + * When DMA mode is enabled specifies whether to use
  31255. + * address DMA or DMA Descritor mode for accessing the data
  31256. + * FIFOs in device mode. The driver will automatically detect
  31257. + * the value for this parameter if none is specified.
  31258. + * 0 - address DMA
  31259. + * 1 - DMA Descriptor(default, if available)
  31260. + */
  31261. +extern int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t * core_if,
  31262. + int32_t val);
  31263. +extern int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t * core_if);
  31264. +//#define dwc_param_dma_desc_enable_default 1
  31265. +#define dwc_param_dma_desc_enable_default 0 // Broadcom BCM2708
  31266. +
  31267. +/** The DMA Burst size (applicable only for External DMA
  31268. + * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
  31269. + */
  31270. +extern int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t * core_if,
  31271. + int32_t val);
  31272. +extern int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t * core_if);
  31273. +#define dwc_param_dma_burst_size_default 32
  31274. +
  31275. +/**
  31276. + * Specifies the maximum speed of operation in host and device mode.
  31277. + * The actual speed depends on the speed of the attached device and
  31278. + * the value of phy_type. The actual speed depends on the speed of the
  31279. + * attached device.
  31280. + * 0 - High Speed (default)
  31281. + * 1 - Full Speed
  31282. + */
  31283. +extern int dwc_otg_set_param_speed(dwc_otg_core_if_t * core_if, int32_t val);
  31284. +extern int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t * core_if);
  31285. +#define dwc_param_speed_default 0
  31286. +#define DWC_SPEED_PARAM_HIGH 0
  31287. +#define DWC_SPEED_PARAM_FULL 1
  31288. +
  31289. +/** Specifies whether low power mode is supported when attached
  31290. + * to a Full Speed or Low Speed device in host mode.
  31291. + * 0 - Don't support low power mode (default)
  31292. + * 1 - Support low power mode
  31293. + */
  31294. +extern int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *
  31295. + core_if, int32_t val);
  31296. +extern int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t
  31297. + * core_if);
  31298. +#define dwc_param_host_support_fs_ls_low_power_default 0
  31299. +
  31300. +/** Specifies the PHY clock rate in low power mode when connected to a
  31301. + * Low Speed device in host mode. This parameter is applicable only if
  31302. + * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
  31303. + * then defaults to 6 MHZ otherwise 48 MHZ.
  31304. + *
  31305. + * 0 - 48 MHz
  31306. + * 1 - 6 MHz
  31307. + */
  31308. +extern int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *
  31309. + core_if, int32_t val);
  31310. +extern int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *
  31311. + core_if);
  31312. +#define dwc_param_host_ls_low_power_phy_clk_default 0
  31313. +#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0
  31314. +#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1
  31315. +
  31316. +/**
  31317. + * 0 - Use cC FIFO size parameters
  31318. + * 1 - Allow dynamic FIFO sizing (default)
  31319. + */
  31320. +extern int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t * core_if,
  31321. + int32_t val);
  31322. +extern int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t *
  31323. + core_if);
  31324. +#define dwc_param_enable_dynamic_fifo_default 1
  31325. +
  31326. +/** Total number of 4-byte words in the data FIFO memory. This
  31327. + * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic
  31328. + * Tx FIFOs.
  31329. + * 32 to 32768 (default 8192)
  31330. + * Note: The total FIFO memory depth in the FPGA configuration is 8192.
  31331. + */
  31332. +extern int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t * core_if,
  31333. + int32_t val);
  31334. +extern int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t * core_if);
  31335. +//#define dwc_param_data_fifo_size_default 8192
  31336. +#define dwc_param_data_fifo_size_default 0xFF0 // Broadcom BCM2708
  31337. +
  31338. +/** Number of 4-byte words in the Rx FIFO in device mode when dynamic
  31339. + * FIFO sizing is enabled.
  31340. + * 16 to 32768 (default 1064)
  31341. + */
  31342. +extern int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if,
  31343. + int32_t val);
  31344. +extern int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if);
  31345. +#define dwc_param_dev_rx_fifo_size_default 1064
  31346. +
  31347. +/** Number of 4-byte words in the non-periodic Tx FIFO in device mode
  31348. + * when dynamic FIFO sizing is enabled.
  31349. + * 16 to 32768 (default 1024)
  31350. + */
  31351. +extern int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *
  31352. + core_if, int32_t val);
  31353. +extern int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *
  31354. + core_if);
  31355. +#define dwc_param_dev_nperio_tx_fifo_size_default 1024
  31356. +
  31357. +/** Number of 4-byte words in each of the periodic Tx FIFOs in device
  31358. + * mode when dynamic FIFO sizing is enabled.
  31359. + * 4 to 768 (default 256)
  31360. + */
  31361. +extern int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if,
  31362. + int32_t val, int fifo_num);
  31363. +extern int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t *
  31364. + core_if, int fifo_num);
  31365. +#define dwc_param_dev_perio_tx_fifo_size_default 256
  31366. +
  31367. +/** Number of 4-byte words in the Rx FIFO in host mode when dynamic
  31368. + * FIFO sizing is enabled.
  31369. + * 16 to 32768 (default 1024)
  31370. + */
  31371. +extern int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if,
  31372. + int32_t val);
  31373. +extern int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if);
  31374. +//#define dwc_param_host_rx_fifo_size_default 1024
  31375. +#define dwc_param_host_rx_fifo_size_default 774 // Broadcom BCM2708
  31376. +
  31377. +/** Number of 4-byte words in the non-periodic Tx FIFO in host mode
  31378. + * when Dynamic FIFO sizing is enabled in the core.
  31379. + * 16 to 32768 (default 1024)
  31380. + */
  31381. +extern int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
  31382. + core_if, int32_t val);
  31383. +extern int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
  31384. + core_if);
  31385. +//#define dwc_param_host_nperio_tx_fifo_size_default 1024
  31386. +#define dwc_param_host_nperio_tx_fifo_size_default 0x100 // Broadcom BCM2708
  31387. +
  31388. +/** Number of 4-byte words in the host periodic Tx FIFO when dynamic
  31389. + * FIFO sizing is enabled.
  31390. + * 16 to 32768 (default 1024)
  31391. + */
  31392. +extern int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
  31393. + core_if, int32_t val);
  31394. +extern int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
  31395. + core_if);
  31396. +//#define dwc_param_host_perio_tx_fifo_size_default 1024
  31397. +#define dwc_param_host_perio_tx_fifo_size_default 0x200 // Broadcom BCM2708
  31398. +
  31399. +/** The maximum transfer size supported in bytes.
  31400. + * 2047 to 65,535 (default 65,535)
  31401. + */
  31402. +extern int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t * core_if,
  31403. + int32_t val);
  31404. +extern int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t * core_if);
  31405. +#define dwc_param_max_transfer_size_default 65535
  31406. +
  31407. +/** The maximum number of packets in a transfer.
  31408. + * 15 to 511 (default 511)
  31409. + */
  31410. +extern int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if,
  31411. + int32_t val);
  31412. +extern int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t * core_if);
  31413. +#define dwc_param_max_packet_count_default 511
  31414. +
  31415. +/** The number of host channel registers to use.
  31416. + * 1 to 16 (default 12)
  31417. + * Note: The FPGA configuration supports a maximum of 12 host channels.
  31418. + */
  31419. +extern int dwc_otg_set_param_host_channels(dwc_otg_core_if_t * core_if,
  31420. + int32_t val);
  31421. +extern int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if);
  31422. +//#define dwc_param_host_channels_default 12
  31423. +#define dwc_param_host_channels_default 8 // Broadcom BCM2708
  31424. +
  31425. +/** The number of endpoints in addition to EP0 available for device
  31426. + * mode operations.
  31427. + * 1 to 15 (default 6 IN and OUT)
  31428. + * Note: The FPGA configuration supports a maximum of 6 IN and OUT
  31429. + * endpoints in addition to EP0.
  31430. + */
  31431. +extern int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if,
  31432. + int32_t val);
  31433. +extern int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t * core_if);
  31434. +#define dwc_param_dev_endpoints_default 6
  31435. +
  31436. +/**
  31437. + * Specifies the type of PHY interface to use. By default, the driver
  31438. + * will automatically detect the phy_type.
  31439. + *
  31440. + * 0 - Full Speed PHY
  31441. + * 1 - UTMI+ (default)
  31442. + * 2 - ULPI
  31443. + */
  31444. +extern int dwc_otg_set_param_phy_type(dwc_otg_core_if_t * core_if, int32_t val);
  31445. +extern int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t * core_if);
  31446. +#define DWC_PHY_TYPE_PARAM_FS 0
  31447. +#define DWC_PHY_TYPE_PARAM_UTMI 1
  31448. +#define DWC_PHY_TYPE_PARAM_ULPI 2
  31449. +#define dwc_param_phy_type_default DWC_PHY_TYPE_PARAM_UTMI
  31450. +
  31451. +/**
  31452. + * Specifies the UTMI+ Data Width. This parameter is
  31453. + * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
  31454. + * PHY_TYPE, this parameter indicates the data width between
  31455. + * the MAC and the ULPI Wrapper.) Also, this parameter is
  31456. + * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
  31457. + * to "8 and 16 bits", meaning that the core has been
  31458. + * configured to work at either data path width.
  31459. + *
  31460. + * 8 or 16 bits (default 16)
  31461. + */
  31462. +extern int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t * core_if,
  31463. + int32_t val);
  31464. +extern int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t * core_if);
  31465. +//#define dwc_param_phy_utmi_width_default 16
  31466. +#define dwc_param_phy_utmi_width_default 8 // Broadcom BCM2708
  31467. +
  31468. +/**
  31469. + * Specifies whether the ULPI operates at double or single
  31470. + * data rate. This parameter is only applicable if PHY_TYPE is
  31471. + * ULPI.
  31472. + *
  31473. + * 0 - single data rate ULPI interface with 8 bit wide data
  31474. + * bus (default)
  31475. + * 1 - double data rate ULPI interface with 4 bit wide data
  31476. + * bus
  31477. + */
  31478. +extern int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if,
  31479. + int32_t val);
  31480. +extern int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t * core_if);
  31481. +#define dwc_param_phy_ulpi_ddr_default 0
  31482. +
  31483. +/**
  31484. + * Specifies whether to use the internal or external supply to
  31485. + * drive the vbus with a ULPI phy.
  31486. + */
  31487. +extern int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if,
  31488. + int32_t val);
  31489. +extern int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t * core_if);
  31490. +#define DWC_PHY_ULPI_INTERNAL_VBUS 0
  31491. +#define DWC_PHY_ULPI_EXTERNAL_VBUS 1
  31492. +#define dwc_param_phy_ulpi_ext_vbus_default DWC_PHY_ULPI_INTERNAL_VBUS
  31493. +
  31494. +/**
  31495. + * Specifies whether to use the I2Cinterface for full speed PHY. This
  31496. + * parameter is only applicable if PHY_TYPE is FS.
  31497. + * 0 - No (default)
  31498. + * 1 - Yes
  31499. + */
  31500. +extern int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if,
  31501. + int32_t val);
  31502. +extern int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t * core_if);
  31503. +#define dwc_param_i2c_enable_default 0
  31504. +
  31505. +extern int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if,
  31506. + int32_t val);
  31507. +extern int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t * core_if);
  31508. +#define dwc_param_ulpi_fs_ls_default 0
  31509. +
  31510. +extern int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t * core_if, int32_t val);
  31511. +extern int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t * core_if);
  31512. +#define dwc_param_ts_dline_default 0
  31513. +
  31514. +/**
  31515. + * Specifies whether dedicated transmit FIFOs are
  31516. + * enabled for non periodic IN endpoints in device mode
  31517. + * 0 - No
  31518. + * 1 - Yes
  31519. + */
  31520. +extern int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if,
  31521. + int32_t val);
  31522. +extern int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t *
  31523. + core_if);
  31524. +#define dwc_param_en_multiple_tx_fifo_default 1
  31525. +
  31526. +/** Number of 4-byte words in each of the Tx FIFOs in device
  31527. + * mode when dynamic FIFO sizing is enabled.
  31528. + * 4 to 768 (default 256)
  31529. + */
  31530. +extern int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
  31531. + int fifo_num, int32_t val);
  31532. +extern int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if,
  31533. + int fifo_num);
  31534. +#define dwc_param_dev_tx_fifo_size_default 768
  31535. +
  31536. +/** Thresholding enable flag-
  31537. + * bit 0 - enable non-ISO Tx thresholding
  31538. + * bit 1 - enable ISO Tx thresholding
  31539. + * bit 2 - enable Rx thresholding
  31540. + */
  31541. +extern int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val);
  31542. +extern int32_t dwc_otg_get_thr_ctl(dwc_otg_core_if_t * core_if, int fifo_num);
  31543. +#define dwc_param_thr_ctl_default 0
  31544. +
  31545. +/** Thresholding length for Tx
  31546. + * FIFOs in 32 bit DWORDs
  31547. + */
  31548. +extern int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t * core_if,
  31549. + int32_t val);
  31550. +extern int32_t dwc_otg_get_tx_thr_length(dwc_otg_core_if_t * core_if);
  31551. +#define dwc_param_tx_thr_length_default 64
  31552. +
  31553. +/** Thresholding length for Rx
  31554. + * FIFOs in 32 bit DWORDs
  31555. + */
  31556. +extern int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t * core_if,
  31557. + int32_t val);
  31558. +extern int32_t dwc_otg_get_rx_thr_length(dwc_otg_core_if_t * core_if);
  31559. +#define dwc_param_rx_thr_length_default 64
  31560. +
  31561. +/**
  31562. + * Specifies whether LPM (Link Power Management) support is enabled
  31563. + */
  31564. +extern int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if,
  31565. + int32_t val);
  31566. +extern int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t * core_if);
  31567. +#define dwc_param_lpm_enable_default 1
  31568. +
  31569. +/**
  31570. + * Specifies whether PTI enhancement is enabled
  31571. + */
  31572. +extern int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if,
  31573. + int32_t val);
  31574. +extern int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t * core_if);
  31575. +#define dwc_param_pti_enable_default 0
  31576. +
  31577. +/**
  31578. + * Specifies whether MPI enhancement is enabled
  31579. + */
  31580. +extern int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if,
  31581. + int32_t val);
  31582. +extern int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t * core_if);
  31583. +#define dwc_param_mpi_enable_default 0
  31584. +
  31585. +/**
  31586. + * Specifies whether ADP capability is enabled
  31587. + */
  31588. +extern int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if,
  31589. + int32_t val);
  31590. +extern int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if);
  31591. +#define dwc_param_adp_enable_default 0
  31592. +
  31593. +/**
  31594. + * Specifies whether IC_USB capability is enabled
  31595. + */
  31596. +
  31597. +extern int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if,
  31598. + int32_t val);
  31599. +extern int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if);
  31600. +#define dwc_param_ic_usb_cap_default 0
  31601. +
  31602. +extern int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if,
  31603. + int32_t val);
  31604. +extern int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if);
  31605. +#define dwc_param_ahb_thr_ratio_default 0
  31606. +
  31607. +extern int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if,
  31608. + int32_t val);
  31609. +extern int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if);
  31610. +#define dwc_param_power_down_default 0
  31611. +
  31612. +extern int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if,
  31613. + int32_t val);
  31614. +extern int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if);
  31615. +#define dwc_param_reload_ctl_default 0
  31616. +
  31617. +extern int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if,
  31618. + int32_t val);
  31619. +extern int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if);
  31620. +#define dwc_param_dev_out_nak_default 0
  31621. +
  31622. +extern int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if,
  31623. + int32_t val);
  31624. +extern int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if);
  31625. +#define dwc_param_cont_on_bna_default 0
  31626. +
  31627. +extern int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if,
  31628. + int32_t val);
  31629. +extern int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if);
  31630. +#define dwc_param_ahb_single_default 0
  31631. +
  31632. +extern int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val);
  31633. +extern int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if);
  31634. +#define dwc_param_otg_ver_default 0
  31635. +
  31636. +/** @} */
  31637. +
  31638. +/** @name Access to registers and bit-fields */
  31639. +
  31640. +/**
  31641. + * Dump core registers and SPRAM
  31642. + */
  31643. +extern void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * _core_if);
  31644. +extern void dwc_otg_dump_spram(dwc_otg_core_if_t * _core_if);
  31645. +extern void dwc_otg_dump_host_registers(dwc_otg_core_if_t * _core_if);
  31646. +extern void dwc_otg_dump_global_registers(dwc_otg_core_if_t * _core_if);
  31647. +
  31648. +/**
  31649. + * Get host negotiation status.
  31650. + */
  31651. +extern uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if);
  31652. +
  31653. +/**
  31654. + * Get srp status
  31655. + */
  31656. +extern uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if);
  31657. +
  31658. +/**
  31659. + * Set hnpreq bit in the GOTGCTL register.
  31660. + */
  31661. +extern void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val);
  31662. +
  31663. +/**
  31664. + * Get Content of SNPSID register.
  31665. + */
  31666. +extern uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if);
  31667. +
  31668. +/**
  31669. + * Get current mode.
  31670. + * Returns 0 if in device mode, and 1 if in host mode.
  31671. + */
  31672. +extern uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if);
  31673. +
  31674. +/**
  31675. + * Get value of hnpcapable field in the GUSBCFG register
  31676. + */
  31677. +extern uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if);
  31678. +/**
  31679. + * Set value of hnpcapable field in the GUSBCFG register
  31680. + */
  31681. +extern void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val);
  31682. +
  31683. +/**
  31684. + * Get value of srpcapable field in the GUSBCFG register
  31685. + */
  31686. +extern uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if);
  31687. +/**
  31688. + * Set value of srpcapable field in the GUSBCFG register
  31689. + */
  31690. +extern void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val);
  31691. +
  31692. +/**
  31693. + * Get value of devspeed field in the DCFG register
  31694. + */
  31695. +extern uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if);
  31696. +/**
  31697. + * Set value of devspeed field in the DCFG register
  31698. + */
  31699. +extern void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val);
  31700. +
  31701. +/**
  31702. + * Get the value of busconnected field from the HPRT0 register
  31703. + */
  31704. +extern uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if);
  31705. +
  31706. +/**
  31707. + * Gets the device enumeration Speed.
  31708. + */
  31709. +extern uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if);
  31710. +
  31711. +/**
  31712. + * Get value of prtpwr field from the HPRT0 register
  31713. + */
  31714. +extern uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if);
  31715. +
  31716. +/**
  31717. + * Get value of flag indicating core state - hibernated or not
  31718. + */
  31719. +extern uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if);
  31720. +
  31721. +/**
  31722. + * Set value of prtpwr field from the HPRT0 register
  31723. + */
  31724. +extern void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val);
  31725. +
  31726. +/**
  31727. + * Get value of prtsusp field from the HPRT0 regsiter
  31728. + */
  31729. +extern uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if);
  31730. +/**
  31731. + * Set value of prtpwr field from the HPRT0 register
  31732. + */
  31733. +extern void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val);
  31734. +
  31735. +/**
  31736. + * Get value of ModeChTimEn field from the HCFG regsiter
  31737. + */
  31738. +extern uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if);
  31739. +/**
  31740. + * Set value of ModeChTimEn field from the HCFG regsiter
  31741. + */
  31742. +extern void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val);
  31743. +
  31744. +/**
  31745. + * Get value of Fram Interval field from the HFIR regsiter
  31746. + */
  31747. +extern uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if);
  31748. +/**
  31749. + * Set value of Frame Interval field from the HFIR regsiter
  31750. + */
  31751. +extern void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val);
  31752. +
  31753. +/**
  31754. + * Set value of prtres field from the HPRT0 register
  31755. + *FIXME Remove?
  31756. + */
  31757. +extern void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val);
  31758. +
  31759. +/**
  31760. + * Get value of rmtwkupsig bit in DCTL register
  31761. + */
  31762. +extern uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if);
  31763. +
  31764. +/**
  31765. + * Get value of prt_sleep_sts field from the GLPMCFG register
  31766. + */
  31767. +extern uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if);
  31768. +
  31769. +/**
  31770. + * Get value of rem_wkup_en field from the GLPMCFG register
  31771. + */
  31772. +extern uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if);
  31773. +
  31774. +/**
  31775. + * Get value of appl_resp field from the GLPMCFG register
  31776. + */
  31777. +extern uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if);
  31778. +/**
  31779. + * Set value of appl_resp field from the GLPMCFG register
  31780. + */
  31781. +extern void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val);
  31782. +
  31783. +/**
  31784. + * Get value of hsic_connect field from the GLPMCFG register
  31785. + */
  31786. +extern uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if);
  31787. +/**
  31788. + * Set value of hsic_connect field from the GLPMCFG register
  31789. + */
  31790. +extern void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val);
  31791. +
  31792. +/**
  31793. + * Get value of inv_sel_hsic field from the GLPMCFG register.
  31794. + */
  31795. +extern uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if);
  31796. +/**
  31797. + * Set value of inv_sel_hsic field from the GLPMFG register.
  31798. + */
  31799. +extern void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val);
  31800. +
  31801. +/*
  31802. + * Some functions for accessing registers
  31803. + */
  31804. +
  31805. +/**
  31806. + * GOTGCTL register
  31807. + */
  31808. +extern uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if);
  31809. +extern void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val);
  31810. +
  31811. +/**
  31812. + * GUSBCFG register
  31813. + */
  31814. +extern uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if);
  31815. +extern void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val);
  31816. +
  31817. +/**
  31818. + * GRXFSIZ register
  31819. + */
  31820. +extern uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if);
  31821. +extern void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val);
  31822. +
  31823. +/**
  31824. + * GNPTXFSIZ register
  31825. + */
  31826. +extern uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if);
  31827. +extern void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val);
  31828. +
  31829. +extern uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if);
  31830. +extern void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val);
  31831. +
  31832. +/**
  31833. + * GGPIO register
  31834. + */
  31835. +extern uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if);
  31836. +extern void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val);
  31837. +
  31838. +/**
  31839. + * GUID register
  31840. + */
  31841. +extern uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if);
  31842. +extern void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val);
  31843. +
  31844. +/**
  31845. + * HPRT0 register
  31846. + */
  31847. +extern uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if);
  31848. +extern void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val);
  31849. +
  31850. +/**
  31851. + * GHPTXFSIZE
  31852. + */
  31853. +extern uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if);
  31854. +
  31855. +/** @} */
  31856. +
  31857. +#endif /* __DWC_CORE_IF_H__ */
  31858. --- /dev/null
  31859. +++ b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
  31860. @@ -0,0 +1,116 @@
  31861. +/* ==========================================================================
  31862. + *
  31863. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  31864. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  31865. + * otherwise expressly agreed to in writing between Synopsys and you.
  31866. + *
  31867. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  31868. + * any End User Software License Agreement or Agreement for Licensed Product
  31869. + * with Synopsys or any supplement thereto. You are permitted to use and
  31870. + * redistribute this Software in source and binary forms, with or without
  31871. + * modification, provided that redistributions of source code must retain this
  31872. + * notice. You may not view, use, disclose, copy or distribute this file or
  31873. + * any information contained herein except pursuant to this license grant from
  31874. + * Synopsys. If you do not agree with this notice, including the disclaimer
  31875. + * below, then you are not authorized to use the Software.
  31876. + *
  31877. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  31878. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  31879. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  31880. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  31881. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  31882. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  31883. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  31884. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31885. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31886. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  31887. + * DAMAGE.
  31888. + * ========================================================================== */
  31889. +
  31890. +#ifndef __DWC_OTG_DBG_H__
  31891. +#define __DWC_OTG_DBG_H__
  31892. +
  31893. +/** @file
  31894. + * This file defines debug levels.
  31895. + * Debugging support vanishes in non-debug builds.
  31896. + */
  31897. +
  31898. +/**
  31899. + * The Debug Level bit-mask variable.
  31900. + */
  31901. +extern uint32_t g_dbg_lvl;
  31902. +/**
  31903. + * Set the Debug Level variable.
  31904. + */
  31905. +static inline uint32_t SET_DEBUG_LEVEL(const uint32_t new)
  31906. +{
  31907. + uint32_t old = g_dbg_lvl;
  31908. + g_dbg_lvl = new;
  31909. + return old;
  31910. +}
  31911. +
  31912. +/** When debug level has the DBG_CIL bit set, display CIL Debug messages. */
  31913. +#define DBG_CIL (0x2)
  31914. +/** When debug level has the DBG_CILV bit set, display CIL Verbose debug
  31915. + * messages */
  31916. +#define DBG_CILV (0x20)
  31917. +/** When debug level has the DBG_PCD bit set, display PCD (Device) debug
  31918. + * messages */
  31919. +#define DBG_PCD (0x4)
  31920. +/** When debug level has the DBG_PCDV set, display PCD (Device) Verbose debug
  31921. + * messages */
  31922. +#define DBG_PCDV (0x40)
  31923. +/** When debug level has the DBG_HCD bit set, display Host debug messages */
  31924. +#define DBG_HCD (0x8)
  31925. +/** When debug level has the DBG_HCDV bit set, display Verbose Host debug
  31926. + * messages */
  31927. +#define DBG_HCDV (0x80)
  31928. +/** When debug level has the DBG_HCD_URB bit set, display enqueued URBs in host
  31929. + * mode. */
  31930. +#define DBG_HCD_URB (0x800)
  31931. +/** When debug level has the DBG_HCDI bit set, display host interrupt
  31932. + * messages. */
  31933. +#define DBG_HCDI (0x1000)
  31934. +
  31935. +/** When debug level has any bit set, display debug messages */
  31936. +#define DBG_ANY (0xFF)
  31937. +
  31938. +/** All debug messages off */
  31939. +#define DBG_OFF 0
  31940. +
  31941. +/** Prefix string for DWC_DEBUG print macros. */
  31942. +#define USB_DWC "DWC_otg: "
  31943. +
  31944. +/**
  31945. + * Print a debug message when the Global debug level variable contains
  31946. + * the bit defined in <code>lvl</code>.
  31947. + *
  31948. + * @param[in] lvl - Debug level, use one of the DBG_ constants above.
  31949. + * @param[in] x - like printf
  31950. + *
  31951. + * Example:<p>
  31952. + * <code>
  31953. + * DWC_DEBUGPL( DBG_ANY, "%s(%p)\n", __func__, _reg_base_addr);
  31954. + * </code>
  31955. + * <br>
  31956. + * results in:<br>
  31957. + * <code>
  31958. + * usb-DWC_otg: dwc_otg_cil_init(ca867000)
  31959. + * </code>
  31960. + */
  31961. +#ifdef DEBUG
  31962. +
  31963. +# define DWC_DEBUGPL(lvl, x...) do{ if ((lvl)&g_dbg_lvl)__DWC_DEBUG(USB_DWC x ); }while(0)
  31964. +# define DWC_DEBUGP(x...) DWC_DEBUGPL(DBG_ANY, x )
  31965. +
  31966. +# define CHK_DEBUG_LEVEL(level) ((level) & g_dbg_lvl)
  31967. +
  31968. +#else
  31969. +
  31970. +# define DWC_DEBUGPL(lvl, x...) do{}while(0)
  31971. +# define DWC_DEBUGP(x...)
  31972. +
  31973. +# define CHK_DEBUG_LEVEL(level) (0)
  31974. +
  31975. +#endif /*DEBUG*/
  31976. +#endif
  31977. --- /dev/null
  31978. +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
  31979. @@ -0,0 +1,1700 @@
  31980. +/* ==========================================================================
  31981. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $
  31982. + * $Revision: #92 $
  31983. + * $Date: 2012/08/10 $
  31984. + * $Change: 2047372 $
  31985. + *
  31986. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  31987. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  31988. + * otherwise expressly agreed to in writing between Synopsys and you.
  31989. + *
  31990. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  31991. + * any End User Software License Agreement or Agreement for Licensed Product
  31992. + * with Synopsys or any supplement thereto. You are permitted to use and
  31993. + * redistribute this Software in source and binary forms, with or without
  31994. + * modification, provided that redistributions of source code must retain this
  31995. + * notice. You may not view, use, disclose, copy or distribute this file or
  31996. + * any information contained herein except pursuant to this license grant from
  31997. + * Synopsys. If you do not agree with this notice, including the disclaimer
  31998. + * below, then you are not authorized to use the Software.
  31999. + *
  32000. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  32001. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  32002. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  32003. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  32004. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  32005. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  32006. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  32007. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32008. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  32009. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  32010. + * DAMAGE.
  32011. + * ========================================================================== */
  32012. +
  32013. +/** @file
  32014. + * The dwc_otg_driver module provides the initialization and cleanup entry
  32015. + * points for the DWC_otg driver. This module will be dynamically installed
  32016. + * after Linux is booted using the insmod command. When the module is
  32017. + * installed, the dwc_otg_driver_init function is called. When the module is
  32018. + * removed (using rmmod), the dwc_otg_driver_cleanup function is called.
  32019. + *
  32020. + * This module also defines a data structure for the dwc_otg_driver, which is
  32021. + * used in conjunction with the standard ARM lm_device structure. These
  32022. + * structures allow the OTG driver to comply with the standard Linux driver
  32023. + * model in which devices and drivers are registered with a bus driver. This
  32024. + * has the benefit that Linux can expose attributes of the driver and device
  32025. + * in its special sysfs file system. Users can then read or write files in
  32026. + * this file system to perform diagnostics on the driver components or the
  32027. + * device.
  32028. + */
  32029. +
  32030. +#include "dwc_otg_os_dep.h"
  32031. +#include "dwc_os.h"
  32032. +#include "dwc_otg_dbg.h"
  32033. +#include "dwc_otg_driver.h"
  32034. +#include "dwc_otg_attr.h"
  32035. +#include "dwc_otg_core_if.h"
  32036. +#include "dwc_otg_pcd_if.h"
  32037. +#include "dwc_otg_hcd_if.h"
  32038. +
  32039. +#define DWC_DRIVER_VERSION "3.00a 10-AUG-2012"
  32040. +#define DWC_DRIVER_DESC "HS OTG USB Controller driver"
  32041. +
  32042. +bool microframe_schedule=true;
  32043. +
  32044. +static const char dwc_driver_name[] = "dwc_otg";
  32045. +
  32046. +extern int pcd_init(
  32047. +#ifdef LM_INTERFACE
  32048. + struct lm_device *_dev
  32049. +#elif defined(PCI_INTERFACE)
  32050. + struct pci_dev *_dev
  32051. +#elif defined(PLATFORM_INTERFACE)
  32052. + struct platform_device *dev
  32053. +#endif
  32054. + );
  32055. +extern int hcd_init(
  32056. +#ifdef LM_INTERFACE
  32057. + struct lm_device *_dev
  32058. +#elif defined(PCI_INTERFACE)
  32059. + struct pci_dev *_dev
  32060. +#elif defined(PLATFORM_INTERFACE)
  32061. + struct platform_device *dev
  32062. +#endif
  32063. + );
  32064. +
  32065. +extern int pcd_remove(
  32066. +#ifdef LM_INTERFACE
  32067. + struct lm_device *_dev
  32068. +#elif defined(PCI_INTERFACE)
  32069. + struct pci_dev *_dev
  32070. +#elif defined(PLATFORM_INTERFACE)
  32071. + struct platform_device *_dev
  32072. +#endif
  32073. + );
  32074. +
  32075. +extern void hcd_remove(
  32076. +#ifdef LM_INTERFACE
  32077. + struct lm_device *_dev
  32078. +#elif defined(PCI_INTERFACE)
  32079. + struct pci_dev *_dev
  32080. +#elif defined(PLATFORM_INTERFACE)
  32081. + struct platform_device *_dev
  32082. +#endif
  32083. + );
  32084. +
  32085. +extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host);
  32086. +
  32087. +/*-------------------------------------------------------------------------*/
  32088. +/* Encapsulate the module parameter settings */
  32089. +
  32090. +struct dwc_otg_driver_module_params {
  32091. + int32_t opt;
  32092. + int32_t otg_cap;
  32093. + int32_t dma_enable;
  32094. + int32_t dma_desc_enable;
  32095. + int32_t dma_burst_size;
  32096. + int32_t speed;
  32097. + int32_t host_support_fs_ls_low_power;
  32098. + int32_t host_ls_low_power_phy_clk;
  32099. + int32_t enable_dynamic_fifo;
  32100. + int32_t data_fifo_size;
  32101. + int32_t dev_rx_fifo_size;
  32102. + int32_t dev_nperio_tx_fifo_size;
  32103. + uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
  32104. + int32_t host_rx_fifo_size;
  32105. + int32_t host_nperio_tx_fifo_size;
  32106. + int32_t host_perio_tx_fifo_size;
  32107. + int32_t max_transfer_size;
  32108. + int32_t max_packet_count;
  32109. + int32_t host_channels;
  32110. + int32_t dev_endpoints;
  32111. + int32_t phy_type;
  32112. + int32_t phy_utmi_width;
  32113. + int32_t phy_ulpi_ddr;
  32114. + int32_t phy_ulpi_ext_vbus;
  32115. + int32_t i2c_enable;
  32116. + int32_t ulpi_fs_ls;
  32117. + int32_t ts_dline;
  32118. + int32_t en_multiple_tx_fifo;
  32119. + uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
  32120. + uint32_t thr_ctl;
  32121. + uint32_t tx_thr_length;
  32122. + uint32_t rx_thr_length;
  32123. + int32_t pti_enable;
  32124. + int32_t mpi_enable;
  32125. + int32_t lpm_enable;
  32126. + int32_t ic_usb_cap;
  32127. + int32_t ahb_thr_ratio;
  32128. + int32_t power_down;
  32129. + int32_t reload_ctl;
  32130. + int32_t dev_out_nak;
  32131. + int32_t cont_on_bna;
  32132. + int32_t ahb_single;
  32133. + int32_t otg_ver;
  32134. + int32_t adp_enable;
  32135. +};
  32136. +
  32137. +static struct dwc_otg_driver_module_params dwc_otg_module_params = {
  32138. + .opt = -1,
  32139. + .otg_cap = -1,
  32140. + .dma_enable = -1,
  32141. + .dma_desc_enable = -1,
  32142. + .dma_burst_size = -1,
  32143. + .speed = -1,
  32144. + .host_support_fs_ls_low_power = -1,
  32145. + .host_ls_low_power_phy_clk = -1,
  32146. + .enable_dynamic_fifo = -1,
  32147. + .data_fifo_size = -1,
  32148. + .dev_rx_fifo_size = -1,
  32149. + .dev_nperio_tx_fifo_size = -1,
  32150. + .dev_perio_tx_fifo_size = {
  32151. + /* dev_perio_tx_fifo_size_1 */
  32152. + -1,
  32153. + -1,
  32154. + -1,
  32155. + -1,
  32156. + -1,
  32157. + -1,
  32158. + -1,
  32159. + -1,
  32160. + -1,
  32161. + -1,
  32162. + -1,
  32163. + -1,
  32164. + -1,
  32165. + -1,
  32166. + -1
  32167. + /* 15 */
  32168. + },
  32169. + .host_rx_fifo_size = -1,
  32170. + .host_nperio_tx_fifo_size = -1,
  32171. + .host_perio_tx_fifo_size = -1,
  32172. + .max_transfer_size = -1,
  32173. + .max_packet_count = -1,
  32174. + .host_channels = -1,
  32175. + .dev_endpoints = -1,
  32176. + .phy_type = -1,
  32177. + .phy_utmi_width = -1,
  32178. + .phy_ulpi_ddr = -1,
  32179. + .phy_ulpi_ext_vbus = -1,
  32180. + .i2c_enable = -1,
  32181. + .ulpi_fs_ls = -1,
  32182. + .ts_dline = -1,
  32183. + .en_multiple_tx_fifo = -1,
  32184. + .dev_tx_fifo_size = {
  32185. + /* dev_tx_fifo_size */
  32186. + -1,
  32187. + -1,
  32188. + -1,
  32189. + -1,
  32190. + -1,
  32191. + -1,
  32192. + -1,
  32193. + -1,
  32194. + -1,
  32195. + -1,
  32196. + -1,
  32197. + -1,
  32198. + -1,
  32199. + -1,
  32200. + -1
  32201. + /* 15 */
  32202. + },
  32203. + .thr_ctl = -1,
  32204. + .tx_thr_length = -1,
  32205. + .rx_thr_length = -1,
  32206. + .pti_enable = -1,
  32207. + .mpi_enable = -1,
  32208. + .lpm_enable = 0,
  32209. + .ic_usb_cap = -1,
  32210. + .ahb_thr_ratio = -1,
  32211. + .power_down = -1,
  32212. + .reload_ctl = -1,
  32213. + .dev_out_nak = -1,
  32214. + .cont_on_bna = -1,
  32215. + .ahb_single = -1,
  32216. + .otg_ver = -1,
  32217. + .adp_enable = -1,
  32218. +};
  32219. +
  32220. +/**
  32221. + * This function shows the Driver Version.
  32222. + */
  32223. +static ssize_t version_show(struct device_driver *dev, char *buf)
  32224. +{
  32225. + return snprintf(buf, sizeof(DWC_DRIVER_VERSION) + 2, "%s\n",
  32226. + DWC_DRIVER_VERSION);
  32227. +}
  32228. +
  32229. +static DRIVER_ATTR(version, S_IRUGO, version_show, NULL);
  32230. +
  32231. +/**
  32232. + * Global Debug Level Mask.
  32233. + */
  32234. +uint32_t g_dbg_lvl = 0; /* OFF */
  32235. +
  32236. +/**
  32237. + * This function shows the driver Debug Level.
  32238. + */
  32239. +static ssize_t dbg_level_show(struct device_driver *drv, char *buf)
  32240. +{
  32241. + return sprintf(buf, "0x%0x\n", g_dbg_lvl);
  32242. +}
  32243. +
  32244. +/**
  32245. + * This function stores the driver Debug Level.
  32246. + */
  32247. +static ssize_t dbg_level_store(struct device_driver *drv, const char *buf,
  32248. + size_t count)
  32249. +{
  32250. + g_dbg_lvl = simple_strtoul(buf, NULL, 16);
  32251. + return count;
  32252. +}
  32253. +
  32254. +static DRIVER_ATTR(debuglevel, S_IRUGO | S_IWUSR, dbg_level_show,
  32255. + dbg_level_store);
  32256. +
  32257. +/**
  32258. + * This function is called during module intialization
  32259. + * to pass module parameters to the DWC_OTG CORE.
  32260. + */
  32261. +static int set_parameters(dwc_otg_core_if_t * core_if)
  32262. +{
  32263. + int retval = 0;
  32264. + int i;
  32265. +
  32266. + if (dwc_otg_module_params.otg_cap != -1) {
  32267. + retval +=
  32268. + dwc_otg_set_param_otg_cap(core_if,
  32269. + dwc_otg_module_params.otg_cap);
  32270. + }
  32271. + if (dwc_otg_module_params.dma_enable != -1) {
  32272. + retval +=
  32273. + dwc_otg_set_param_dma_enable(core_if,
  32274. + dwc_otg_module_params.
  32275. + dma_enable);
  32276. + }
  32277. + if (dwc_otg_module_params.dma_desc_enable != -1) {
  32278. + retval +=
  32279. + dwc_otg_set_param_dma_desc_enable(core_if,
  32280. + dwc_otg_module_params.
  32281. + dma_desc_enable);
  32282. + }
  32283. + if (dwc_otg_module_params.opt != -1) {
  32284. + retval +=
  32285. + dwc_otg_set_param_opt(core_if, dwc_otg_module_params.opt);
  32286. + }
  32287. + if (dwc_otg_module_params.dma_burst_size != -1) {
  32288. + retval +=
  32289. + dwc_otg_set_param_dma_burst_size(core_if,
  32290. + dwc_otg_module_params.
  32291. + dma_burst_size);
  32292. + }
  32293. + if (dwc_otg_module_params.host_support_fs_ls_low_power != -1) {
  32294. + retval +=
  32295. + dwc_otg_set_param_host_support_fs_ls_low_power(core_if,
  32296. + dwc_otg_module_params.
  32297. + host_support_fs_ls_low_power);
  32298. + }
  32299. + if (dwc_otg_module_params.enable_dynamic_fifo != -1) {
  32300. + retval +=
  32301. + dwc_otg_set_param_enable_dynamic_fifo(core_if,
  32302. + dwc_otg_module_params.
  32303. + enable_dynamic_fifo);
  32304. + }
  32305. + if (dwc_otg_module_params.data_fifo_size != -1) {
  32306. + retval +=
  32307. + dwc_otg_set_param_data_fifo_size(core_if,
  32308. + dwc_otg_module_params.
  32309. + data_fifo_size);
  32310. + }
  32311. + if (dwc_otg_module_params.dev_rx_fifo_size != -1) {
  32312. + retval +=
  32313. + dwc_otg_set_param_dev_rx_fifo_size(core_if,
  32314. + dwc_otg_module_params.
  32315. + dev_rx_fifo_size);
  32316. + }
  32317. + if (dwc_otg_module_params.dev_nperio_tx_fifo_size != -1) {
  32318. + retval +=
  32319. + dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,
  32320. + dwc_otg_module_params.
  32321. + dev_nperio_tx_fifo_size);
  32322. + }
  32323. + if (dwc_otg_module_params.host_rx_fifo_size != -1) {
  32324. + retval +=
  32325. + dwc_otg_set_param_host_rx_fifo_size(core_if,
  32326. + dwc_otg_module_params.host_rx_fifo_size);
  32327. + }
  32328. + if (dwc_otg_module_params.host_nperio_tx_fifo_size != -1) {
  32329. + retval +=
  32330. + dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,
  32331. + dwc_otg_module_params.
  32332. + host_nperio_tx_fifo_size);
  32333. + }
  32334. + if (dwc_otg_module_params.host_perio_tx_fifo_size != -1) {
  32335. + retval +=
  32336. + dwc_otg_set_param_host_perio_tx_fifo_size(core_if,
  32337. + dwc_otg_module_params.
  32338. + host_perio_tx_fifo_size);
  32339. + }
  32340. + if (dwc_otg_module_params.max_transfer_size != -1) {
  32341. + retval +=
  32342. + dwc_otg_set_param_max_transfer_size(core_if,
  32343. + dwc_otg_module_params.
  32344. + max_transfer_size);
  32345. + }
  32346. + if (dwc_otg_module_params.max_packet_count != -1) {
  32347. + retval +=
  32348. + dwc_otg_set_param_max_packet_count(core_if,
  32349. + dwc_otg_module_params.
  32350. + max_packet_count);
  32351. + }
  32352. + if (dwc_otg_module_params.host_channels != -1) {
  32353. + retval +=
  32354. + dwc_otg_set_param_host_channels(core_if,
  32355. + dwc_otg_module_params.
  32356. + host_channels);
  32357. + }
  32358. + if (dwc_otg_module_params.dev_endpoints != -1) {
  32359. + retval +=
  32360. + dwc_otg_set_param_dev_endpoints(core_if,
  32361. + dwc_otg_module_params.
  32362. + dev_endpoints);
  32363. + }
  32364. + if (dwc_otg_module_params.phy_type != -1) {
  32365. + retval +=
  32366. + dwc_otg_set_param_phy_type(core_if,
  32367. + dwc_otg_module_params.phy_type);
  32368. + }
  32369. + if (dwc_otg_module_params.speed != -1) {
  32370. + retval +=
  32371. + dwc_otg_set_param_speed(core_if,
  32372. + dwc_otg_module_params.speed);
  32373. + }
  32374. + if (dwc_otg_module_params.host_ls_low_power_phy_clk != -1) {
  32375. + retval +=
  32376. + dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,
  32377. + dwc_otg_module_params.
  32378. + host_ls_low_power_phy_clk);
  32379. + }
  32380. + if (dwc_otg_module_params.phy_ulpi_ddr != -1) {
  32381. + retval +=
  32382. + dwc_otg_set_param_phy_ulpi_ddr(core_if,
  32383. + dwc_otg_module_params.
  32384. + phy_ulpi_ddr);
  32385. + }
  32386. + if (dwc_otg_module_params.phy_ulpi_ext_vbus != -1) {
  32387. + retval +=
  32388. + dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,
  32389. + dwc_otg_module_params.
  32390. + phy_ulpi_ext_vbus);
  32391. + }
  32392. + if (dwc_otg_module_params.phy_utmi_width != -1) {
  32393. + retval +=
  32394. + dwc_otg_set_param_phy_utmi_width(core_if,
  32395. + dwc_otg_module_params.
  32396. + phy_utmi_width);
  32397. + }
  32398. + if (dwc_otg_module_params.ulpi_fs_ls != -1) {
  32399. + retval +=
  32400. + dwc_otg_set_param_ulpi_fs_ls(core_if,
  32401. + dwc_otg_module_params.ulpi_fs_ls);
  32402. + }
  32403. + if (dwc_otg_module_params.ts_dline != -1) {
  32404. + retval +=
  32405. + dwc_otg_set_param_ts_dline(core_if,
  32406. + dwc_otg_module_params.ts_dline);
  32407. + }
  32408. + if (dwc_otg_module_params.i2c_enable != -1) {
  32409. + retval +=
  32410. + dwc_otg_set_param_i2c_enable(core_if,
  32411. + dwc_otg_module_params.
  32412. + i2c_enable);
  32413. + }
  32414. + if (dwc_otg_module_params.en_multiple_tx_fifo != -1) {
  32415. + retval +=
  32416. + dwc_otg_set_param_en_multiple_tx_fifo(core_if,
  32417. + dwc_otg_module_params.
  32418. + en_multiple_tx_fifo);
  32419. + }
  32420. + for (i = 0; i < 15; i++) {
  32421. + if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] != -1) {
  32422. + retval +=
  32423. + dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,
  32424. + dwc_otg_module_params.
  32425. + dev_perio_tx_fifo_size
  32426. + [i], i);
  32427. + }
  32428. + }
  32429. +
  32430. + for (i = 0; i < 15; i++) {
  32431. + if (dwc_otg_module_params.dev_tx_fifo_size[i] != -1) {
  32432. + retval += dwc_otg_set_param_dev_tx_fifo_size(core_if,
  32433. + dwc_otg_module_params.
  32434. + dev_tx_fifo_size
  32435. + [i], i);
  32436. + }
  32437. + }
  32438. + if (dwc_otg_module_params.thr_ctl != -1) {
  32439. + retval +=
  32440. + dwc_otg_set_param_thr_ctl(core_if,
  32441. + dwc_otg_module_params.thr_ctl);
  32442. + }
  32443. + if (dwc_otg_module_params.mpi_enable != -1) {
  32444. + retval +=
  32445. + dwc_otg_set_param_mpi_enable(core_if,
  32446. + dwc_otg_module_params.
  32447. + mpi_enable);
  32448. + }
  32449. + if (dwc_otg_module_params.pti_enable != -1) {
  32450. + retval +=
  32451. + dwc_otg_set_param_pti_enable(core_if,
  32452. + dwc_otg_module_params.
  32453. + pti_enable);
  32454. + }
  32455. + if (dwc_otg_module_params.lpm_enable != -1) {
  32456. + retval +=
  32457. + dwc_otg_set_param_lpm_enable(core_if,
  32458. + dwc_otg_module_params.
  32459. + lpm_enable);
  32460. + }
  32461. + if (dwc_otg_module_params.ic_usb_cap != -1) {
  32462. + retval +=
  32463. + dwc_otg_set_param_ic_usb_cap(core_if,
  32464. + dwc_otg_module_params.
  32465. + ic_usb_cap);
  32466. + }
  32467. + if (dwc_otg_module_params.tx_thr_length != -1) {
  32468. + retval +=
  32469. + dwc_otg_set_param_tx_thr_length(core_if,
  32470. + dwc_otg_module_params.tx_thr_length);
  32471. + }
  32472. + if (dwc_otg_module_params.rx_thr_length != -1) {
  32473. + retval +=
  32474. + dwc_otg_set_param_rx_thr_length(core_if,
  32475. + dwc_otg_module_params.
  32476. + rx_thr_length);
  32477. + }
  32478. + if (dwc_otg_module_params.ahb_thr_ratio != -1) {
  32479. + retval +=
  32480. + dwc_otg_set_param_ahb_thr_ratio(core_if,
  32481. + dwc_otg_module_params.ahb_thr_ratio);
  32482. + }
  32483. + if (dwc_otg_module_params.power_down != -1) {
  32484. + retval +=
  32485. + dwc_otg_set_param_power_down(core_if,
  32486. + dwc_otg_module_params.power_down);
  32487. + }
  32488. + if (dwc_otg_module_params.reload_ctl != -1) {
  32489. + retval +=
  32490. + dwc_otg_set_param_reload_ctl(core_if,
  32491. + dwc_otg_module_params.reload_ctl);
  32492. + }
  32493. +
  32494. + if (dwc_otg_module_params.dev_out_nak != -1) {
  32495. + retval +=
  32496. + dwc_otg_set_param_dev_out_nak(core_if,
  32497. + dwc_otg_module_params.dev_out_nak);
  32498. + }
  32499. +
  32500. + if (dwc_otg_module_params.cont_on_bna != -1) {
  32501. + retval +=
  32502. + dwc_otg_set_param_cont_on_bna(core_if,
  32503. + dwc_otg_module_params.cont_on_bna);
  32504. + }
  32505. +
  32506. + if (dwc_otg_module_params.ahb_single != -1) {
  32507. + retval +=
  32508. + dwc_otg_set_param_ahb_single(core_if,
  32509. + dwc_otg_module_params.ahb_single);
  32510. + }
  32511. +
  32512. + if (dwc_otg_module_params.otg_ver != -1) {
  32513. + retval +=
  32514. + dwc_otg_set_param_otg_ver(core_if,
  32515. + dwc_otg_module_params.otg_ver);
  32516. + }
  32517. + if (dwc_otg_module_params.adp_enable != -1) {
  32518. + retval +=
  32519. + dwc_otg_set_param_adp_enable(core_if,
  32520. + dwc_otg_module_params.
  32521. + adp_enable);
  32522. + }
  32523. + return retval;
  32524. +}
  32525. +
  32526. +/**
  32527. + * This function is the top level interrupt handler for the Common
  32528. + * (Device and host modes) interrupts.
  32529. + */
  32530. +static irqreturn_t dwc_otg_common_irq(int irq, void *dev)
  32531. +{
  32532. + int32_t retval = IRQ_NONE;
  32533. +
  32534. + retval = dwc_otg_handle_common_intr(dev);
  32535. + if (retval != 0) {
  32536. + S3C2410X_CLEAR_EINTPEND();
  32537. + }
  32538. + return IRQ_RETVAL(retval);
  32539. +}
  32540. +
  32541. +/**
  32542. + * This function is called when a lm_device is unregistered with the
  32543. + * dwc_otg_driver. This happens, for example, when the rmmod command is
  32544. + * executed. The device may or may not be electrically present. If it is
  32545. + * present, the driver stops device processing. Any resources used on behalf
  32546. + * of this device are freed.
  32547. + *
  32548. + * @param _dev
  32549. + */
  32550. +#ifdef LM_INTERFACE
  32551. +#define REM_RETVAL(n)
  32552. +static void dwc_otg_driver_remove( struct lm_device *_dev )
  32553. +{ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
  32554. +#elif defined(PCI_INTERFACE)
  32555. +#define REM_RETVAL(n)
  32556. +static void dwc_otg_driver_remove( struct pci_dev *_dev )
  32557. +{ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
  32558. +#elif defined(PLATFORM_INTERFACE)
  32559. +#define REM_RETVAL(n) n
  32560. +static int dwc_otg_driver_remove( struct platform_device *_dev )
  32561. +{ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev);
  32562. +#endif
  32563. +
  32564. + DWC_DEBUGPL(DBG_ANY, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev);
  32565. +
  32566. + if (!otg_dev) {
  32567. + /* Memory allocation for the dwc_otg_device failed. */
  32568. + DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);
  32569. + return REM_RETVAL(-ENOMEM);
  32570. + }
  32571. +#ifndef DWC_DEVICE_ONLY
  32572. + if (otg_dev->hcd) {
  32573. + hcd_remove(_dev);
  32574. + } else {
  32575. + DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__);
  32576. + return REM_RETVAL(-EINVAL);
  32577. + }
  32578. +#endif
  32579. +
  32580. +#ifndef DWC_HOST_ONLY
  32581. + if (otg_dev->pcd) {
  32582. + pcd_remove(_dev);
  32583. + } else {
  32584. + DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->pcd NULL!\n", __func__);
  32585. + return REM_RETVAL(-EINVAL);
  32586. + }
  32587. +#endif
  32588. + /*
  32589. + * Free the IRQ
  32590. + */
  32591. + if (otg_dev->common_irq_installed) {
  32592. +#ifdef PLATFORM_INTERFACE
  32593. + free_irq(platform_get_irq(_dev, 0), otg_dev);
  32594. +#else
  32595. + free_irq(_dev->irq, otg_dev);
  32596. +#endif
  32597. + } else {
  32598. + DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__);
  32599. + return REM_RETVAL(-ENXIO);
  32600. + }
  32601. +
  32602. + if (otg_dev->core_if) {
  32603. + dwc_otg_cil_remove(otg_dev->core_if);
  32604. + } else {
  32605. + DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->core_if NULL!\n", __func__);
  32606. + return REM_RETVAL(-ENXIO);
  32607. + }
  32608. +
  32609. + /*
  32610. + * Remove the device attributes
  32611. + */
  32612. + dwc_otg_attr_remove(_dev);
  32613. +
  32614. + /*
  32615. + * Return the memory.
  32616. + */
  32617. + if (otg_dev->os_dep.base) {
  32618. + iounmap(otg_dev->os_dep.base);
  32619. + }
  32620. + DWC_FREE(otg_dev);
  32621. +
  32622. + /*
  32623. + * Clear the drvdata pointer.
  32624. + */
  32625. +#ifdef LM_INTERFACE
  32626. + lm_set_drvdata(_dev, 0);
  32627. +#elif defined(PCI_INTERFACE)
  32628. + release_mem_region(otg_dev->os_dep.rsrc_start,
  32629. + otg_dev->os_dep.rsrc_len);
  32630. + pci_set_drvdata(_dev, 0);
  32631. +#elif defined(PLATFORM_INTERFACE)
  32632. + platform_set_drvdata(_dev, 0);
  32633. +#endif
  32634. + return REM_RETVAL(0);
  32635. +}
  32636. +
  32637. +/**
  32638. + * This function is called when an lm_device is bound to a
  32639. + * dwc_otg_driver. It creates the driver components required to
  32640. + * control the device (CIL, HCD, and PCD) and it initializes the
  32641. + * device. The driver components are stored in a dwc_otg_device
  32642. + * structure. A reference to the dwc_otg_device is saved in the
  32643. + * lm_device. This allows the driver to access the dwc_otg_device
  32644. + * structure on subsequent calls to driver methods for this device.
  32645. + *
  32646. + * @param _dev Bus device
  32647. + */
  32648. +static int dwc_otg_driver_probe(
  32649. +#ifdef LM_INTERFACE
  32650. + struct lm_device *_dev
  32651. +#elif defined(PCI_INTERFACE)
  32652. + struct pci_dev *_dev,
  32653. + const struct pci_device_id *id
  32654. +#elif defined(PLATFORM_INTERFACE)
  32655. + struct platform_device *_dev
  32656. +#endif
  32657. + )
  32658. +{
  32659. + int retval = 0;
  32660. + dwc_otg_device_t *dwc_otg_device;
  32661. + int devirq;
  32662. +
  32663. + dev_dbg(&_dev->dev, "dwc_otg_driver_probe(%p)\n", _dev);
  32664. +#ifdef LM_INTERFACE
  32665. + dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)_dev->resource.start);
  32666. +#elif defined(PCI_INTERFACE)
  32667. + if (!id) {
  32668. + DWC_ERROR("Invalid pci_device_id %p", id);
  32669. + return -EINVAL;
  32670. + }
  32671. +
  32672. + if (!_dev || (pci_enable_device(_dev) < 0)) {
  32673. + DWC_ERROR("Invalid pci_device %p", _dev);
  32674. + return -ENODEV;
  32675. + }
  32676. + dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)pci_resource_start(_dev,0));
  32677. + /* other stuff needed as well? */
  32678. +
  32679. +#elif defined(PLATFORM_INTERFACE)
  32680. + dev_dbg(&_dev->dev, "start=0x%08x (len 0x%x)\n",
  32681. + (unsigned)_dev->resource->start,
  32682. + (unsigned)(_dev->resource->end - _dev->resource->start));
  32683. +#endif
  32684. +
  32685. + dwc_otg_device = DWC_ALLOC(sizeof(dwc_otg_device_t));
  32686. +
  32687. + if (!dwc_otg_device) {
  32688. + dev_err(&_dev->dev, "kmalloc of dwc_otg_device failed\n");
  32689. + return -ENOMEM;
  32690. + }
  32691. +
  32692. + memset(dwc_otg_device, 0, sizeof(*dwc_otg_device));
  32693. + dwc_otg_device->os_dep.reg_offset = 0xFFFFFFFF;
  32694. +
  32695. + /*
  32696. + * Map the DWC_otg Core memory into virtual address space.
  32697. + */
  32698. +#ifdef LM_INTERFACE
  32699. + dwc_otg_device->os_dep.base = ioremap(_dev->resource.start, SZ_256K);
  32700. +
  32701. + if (!dwc_otg_device->os_dep.base) {
  32702. + dev_err(&_dev->dev, "ioremap() failed\n");
  32703. + DWC_FREE(dwc_otg_device);
  32704. + return -ENOMEM;
  32705. + }
  32706. + dev_dbg(&_dev->dev, "base=0x%08x\n",
  32707. + (unsigned)dwc_otg_device->os_dep.base);
  32708. +#elif defined(PCI_INTERFACE)
  32709. + _dev->current_state = PCI_D0;
  32710. + _dev->dev.power.power_state = PMSG_ON;
  32711. +
  32712. + if (!_dev->irq) {
  32713. + DWC_ERROR("Found HC with no IRQ. Check BIOS/PCI %s setup!",
  32714. + pci_name(_dev));
  32715. + iounmap(dwc_otg_device->os_dep.base);
  32716. + DWC_FREE(dwc_otg_device);
  32717. + return -ENODEV;
  32718. + }
  32719. +
  32720. + dwc_otg_device->os_dep.rsrc_start = pci_resource_start(_dev, 0);
  32721. + dwc_otg_device->os_dep.rsrc_len = pci_resource_len(_dev, 0);
  32722. + DWC_DEBUGPL(DBG_ANY, "PCI resource: start=%08x, len=%08x\n",
  32723. + (unsigned)dwc_otg_device->os_dep.rsrc_start,
  32724. + (unsigned)dwc_otg_device->os_dep.rsrc_len);
  32725. + if (!request_mem_region
  32726. + (dwc_otg_device->os_dep.rsrc_start, dwc_otg_device->os_dep.rsrc_len,
  32727. + "dwc_otg")) {
  32728. + dev_dbg(&_dev->dev, "error requesting memory\n");
  32729. + iounmap(dwc_otg_device->os_dep.base);
  32730. + DWC_FREE(dwc_otg_device);
  32731. + return -EFAULT;
  32732. + }
  32733. +
  32734. + dwc_otg_device->os_dep.base =
  32735. + ioremap_nocache(dwc_otg_device->os_dep.rsrc_start,
  32736. + dwc_otg_device->os_dep.rsrc_len);
  32737. + if (dwc_otg_device->os_dep.base == NULL) {
  32738. + dev_dbg(&_dev->dev, "error mapping memory\n");
  32739. + release_mem_region(dwc_otg_device->os_dep.rsrc_start,
  32740. + dwc_otg_device->os_dep.rsrc_len);
  32741. + iounmap(dwc_otg_device->os_dep.base);
  32742. + DWC_FREE(dwc_otg_device);
  32743. + return -EFAULT;
  32744. + }
  32745. + dev_dbg(&_dev->dev, "base=0x%p (before adjust) \n",
  32746. + dwc_otg_device->os_dep.base);
  32747. + dwc_otg_device->os_dep.base = (char *)dwc_otg_device->os_dep.base;
  32748. + dev_dbg(&_dev->dev, "base=0x%p (after adjust) \n",
  32749. + dwc_otg_device->os_dep.base);
  32750. + dev_dbg(&_dev->dev, "%s: mapped PA 0x%x to VA 0x%p\n", __func__,
  32751. + (unsigned)dwc_otg_device->os_dep.rsrc_start,
  32752. + dwc_otg_device->os_dep.base);
  32753. +
  32754. + pci_set_master(_dev);
  32755. + pci_set_drvdata(_dev, dwc_otg_device);
  32756. +#elif defined(PLATFORM_INTERFACE)
  32757. + DWC_DEBUGPL(DBG_ANY,"Platform resource: start=%08x, len=%08x\n",
  32758. + _dev->resource->start,
  32759. + _dev->resource->end - _dev->resource->start + 1);
  32760. +#if 1
  32761. + if (!request_mem_region(_dev->resource->start,
  32762. + _dev->resource->end - _dev->resource->start + 1,
  32763. + "dwc_otg")) {
  32764. + dev_dbg(&_dev->dev, "error reserving mapped memory\n");
  32765. + retval = -EFAULT;
  32766. + goto fail;
  32767. + }
  32768. +
  32769. + dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource->start,
  32770. + _dev->resource->end -
  32771. + _dev->resource->start+1);
  32772. +#else
  32773. + {
  32774. + struct map_desc desc = {
  32775. + .virtual = IO_ADDRESS((unsigned)_dev->resource->start),
  32776. + .pfn = __phys_to_pfn((unsigned)_dev->resource->start),
  32777. + .length = SZ_128K,
  32778. + .type = MT_DEVICE
  32779. + };
  32780. + iotable_init(&desc, 1);
  32781. + dwc_otg_device->os_dep.base = (void *)desc.virtual;
  32782. + }
  32783. +#endif
  32784. + if (!dwc_otg_device->os_dep.base) {
  32785. + dev_err(&_dev->dev, "ioremap() failed\n");
  32786. + retval = -ENOMEM;
  32787. + goto fail;
  32788. + }
  32789. + dev_dbg(&_dev->dev, "base=0x%08x\n",
  32790. + (unsigned)dwc_otg_device->os_dep.base);
  32791. +#endif
  32792. +
  32793. + /*
  32794. + * Initialize driver data to point to the global DWC_otg
  32795. + * Device structure.
  32796. + */
  32797. +#ifdef LM_INTERFACE
  32798. + lm_set_drvdata(_dev, dwc_otg_device);
  32799. +#elif defined(PLATFORM_INTERFACE)
  32800. + platform_set_drvdata(_dev, dwc_otg_device);
  32801. +#endif
  32802. + dev_dbg(&_dev->dev, "dwc_otg_device=0x%p\n", dwc_otg_device);
  32803. +
  32804. + dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->os_dep.base);
  32805. + DWC_DEBUGPL(DBG_HCDV, "probe of device %p given core_if %p\n",
  32806. + dwc_otg_device, dwc_otg_device->core_if);//GRAYG
  32807. +
  32808. + if (!dwc_otg_device->core_if) {
  32809. + dev_err(&_dev->dev, "CIL initialization failed!\n");
  32810. + retval = -ENOMEM;
  32811. + goto fail;
  32812. + }
  32813. +
  32814. + dev_dbg(&_dev->dev, "Calling get_gsnpsid\n");
  32815. + /*
  32816. + * Attempt to ensure this device is really a DWC_otg Controller.
  32817. + * Read and verify the SNPSID register contents. The value should be
  32818. + * 0x45F42XXX or 0x45F42XXX, which corresponds to either "OT2" or "OTG3",
  32819. + * as in "OTG version 2.XX" or "OTG version 3.XX".
  32820. + */
  32821. +
  32822. + if (((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F542000) &&
  32823. + ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) {
  32824. + dev_err(&_dev->dev, "Bad value for SNPSID: 0x%08x\n",
  32825. + dwc_otg_get_gsnpsid(dwc_otg_device->core_if));
  32826. + retval = -EINVAL;
  32827. + goto fail;
  32828. + }
  32829. +
  32830. + /*
  32831. + * Validate parameter values.
  32832. + */
  32833. + dev_dbg(&_dev->dev, "Calling set_parameters\n");
  32834. + if (set_parameters(dwc_otg_device->core_if)) {
  32835. + retval = -EINVAL;
  32836. + goto fail;
  32837. + }
  32838. +
  32839. + /*
  32840. + * Create Device Attributes in sysfs
  32841. + */
  32842. + dev_dbg(&_dev->dev, "Calling attr_create\n");
  32843. + dwc_otg_attr_create(_dev);
  32844. +
  32845. + /*
  32846. + * Disable the global interrupt until all the interrupt
  32847. + * handlers are installed.
  32848. + */
  32849. + dev_dbg(&_dev->dev, "Calling disable_global_interrupts\n");
  32850. + dwc_otg_disable_global_interrupts(dwc_otg_device->core_if);
  32851. +
  32852. + /*
  32853. + * Install the interrupt handler for the common interrupts before
  32854. + * enabling common interrupts in core_init below.
  32855. + */
  32856. +
  32857. +#if defined(PLATFORM_INTERFACE)
  32858. + devirq = platform_get_irq(_dev, 0);
  32859. +#else
  32860. + devirq = _dev->irq;
  32861. +#endif
  32862. + DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n",
  32863. + devirq);
  32864. + dev_dbg(&_dev->dev, "Calling request_irq(%d)\n", devirq);
  32865. + retval = request_irq(devirq, dwc_otg_common_irq,
  32866. + IRQF_SHARED,
  32867. + "dwc_otg", dwc_otg_device);
  32868. + if (retval) {
  32869. + DWC_ERROR("request of irq%d failed\n", devirq);
  32870. + retval = -EBUSY;
  32871. + goto fail;
  32872. + } else {
  32873. + dwc_otg_device->common_irq_installed = 1;
  32874. + }
  32875. +
  32876. +#ifndef IRQF_TRIGGER_LOW
  32877. +#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
  32878. + dev_dbg(&_dev->dev, "Calling set_irq_type\n");
  32879. + set_irq_type(devirq,
  32880. +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
  32881. + IRQT_LOW
  32882. +#else
  32883. + IRQ_TYPE_LEVEL_LOW
  32884. +#endif
  32885. + );
  32886. +#endif
  32887. +#endif /*IRQF_TRIGGER_LOW*/
  32888. +
  32889. + /*
  32890. + * Initialize the DWC_otg core.
  32891. + */
  32892. + dev_dbg(&_dev->dev, "Calling dwc_otg_core_init\n");
  32893. + dwc_otg_core_init(dwc_otg_device->core_if);
  32894. +
  32895. +#ifndef DWC_HOST_ONLY
  32896. + /*
  32897. + * Initialize the PCD
  32898. + */
  32899. + dev_dbg(&_dev->dev, "Calling pcd_init\n");
  32900. + retval = pcd_init(_dev);
  32901. + if (retval != 0) {
  32902. + DWC_ERROR("pcd_init failed\n");
  32903. + dwc_otg_device->pcd = NULL;
  32904. + goto fail;
  32905. + }
  32906. +#endif
  32907. +#ifndef DWC_DEVICE_ONLY
  32908. + /*
  32909. + * Initialize the HCD
  32910. + */
  32911. + dev_dbg(&_dev->dev, "Calling hcd_init\n");
  32912. + retval = hcd_init(_dev);
  32913. + if (retval != 0) {
  32914. + DWC_ERROR("hcd_init failed\n");
  32915. + dwc_otg_device->hcd = NULL;
  32916. + goto fail;
  32917. + }
  32918. +#endif
  32919. + /* Recover from drvdata having been overwritten by hcd_init() */
  32920. +#ifdef LM_INTERFACE
  32921. + lm_set_drvdata(_dev, dwc_otg_device);
  32922. +#elif defined(PLATFORM_INTERFACE)
  32923. + platform_set_drvdata(_dev, dwc_otg_device);
  32924. +#elif defined(PCI_INTERFACE)
  32925. + pci_set_drvdata(_dev, dwc_otg_device);
  32926. + dwc_otg_device->os_dep.pcidev = _dev;
  32927. +#endif
  32928. +
  32929. + /*
  32930. + * Enable the global interrupt after all the interrupt
  32931. + * handlers are installed if there is no ADP support else
  32932. + * perform initial actions required for Internal ADP logic.
  32933. + */
  32934. + if (!dwc_otg_get_param_adp_enable(dwc_otg_device->core_if)) {
  32935. + dev_dbg(&_dev->dev, "Calling enable_global_interrupts\n");
  32936. + dwc_otg_enable_global_interrupts(dwc_otg_device->core_if);
  32937. + dev_dbg(&_dev->dev, "Done\n");
  32938. + } else
  32939. + dwc_otg_adp_start(dwc_otg_device->core_if,
  32940. + dwc_otg_is_host_mode(dwc_otg_device->core_if));
  32941. +
  32942. + return 0;
  32943. +
  32944. +fail:
  32945. + dwc_otg_driver_remove(_dev);
  32946. + return retval;
  32947. +}
  32948. +
  32949. +/**
  32950. + * This structure defines the methods to be called by a bus driver
  32951. + * during the lifecycle of a device on that bus. Both drivers and
  32952. + * devices are registered with a bus driver. The bus driver matches
  32953. + * devices to drivers based on information in the device and driver
  32954. + * structures.
  32955. + *
  32956. + * The probe function is called when the bus driver matches a device
  32957. + * to this driver. The remove function is called when a device is
  32958. + * unregistered with the bus driver.
  32959. + */
  32960. +#ifdef LM_INTERFACE
  32961. +static struct lm_driver dwc_otg_driver = {
  32962. + .drv = {.name = (char *)dwc_driver_name,},
  32963. + .probe = dwc_otg_driver_probe,
  32964. + .remove = dwc_otg_driver_remove,
  32965. + // 'suspend' and 'resume' absent
  32966. +};
  32967. +#elif defined(PCI_INTERFACE)
  32968. +static const struct pci_device_id pci_ids[] = { {
  32969. + PCI_DEVICE(0x16c3, 0xabcd),
  32970. + .driver_data =
  32971. + (unsigned long)0xdeadbeef,
  32972. + }, { /* end: all zeroes */ }
  32973. +};
  32974. +
  32975. +MODULE_DEVICE_TABLE(pci, pci_ids);
  32976. +
  32977. +/* pci driver glue; this is a "new style" PCI driver module */
  32978. +static struct pci_driver dwc_otg_driver = {
  32979. + .name = "dwc_otg",
  32980. + .id_table = pci_ids,
  32981. +
  32982. + .probe = dwc_otg_driver_probe,
  32983. + .remove = dwc_otg_driver_remove,
  32984. +
  32985. + .driver = {
  32986. + .name = (char *)dwc_driver_name,
  32987. + },
  32988. +};
  32989. +#elif defined(PLATFORM_INTERFACE)
  32990. +static struct platform_device_id platform_ids[] = {
  32991. + {
  32992. + .name = "bcm2708_usb",
  32993. + .driver_data = (kernel_ulong_t) 0xdeadbeef,
  32994. + },
  32995. + { /* end: all zeroes */ }
  32996. +};
  32997. +MODULE_DEVICE_TABLE(platform, platform_ids);
  32998. +
  32999. +static struct platform_driver dwc_otg_driver = {
  33000. + .driver = {
  33001. + .name = (char *)dwc_driver_name,
  33002. + },
  33003. + .id_table = platform_ids,
  33004. +
  33005. + .probe = dwc_otg_driver_probe,
  33006. + .remove = dwc_otg_driver_remove,
  33007. + // no 'shutdown', 'suspend', 'resume', 'suspend_late' or 'resume_early'
  33008. +};
  33009. +#endif
  33010. +
  33011. +/**
  33012. + * This function is called when the dwc_otg_driver is installed with the
  33013. + * insmod command. It registers the dwc_otg_driver structure with the
  33014. + * appropriate bus driver. This will cause the dwc_otg_driver_probe function
  33015. + * to be called. In addition, the bus driver will automatically expose
  33016. + * attributes defined for the device and driver in the special sysfs file
  33017. + * system.
  33018. + *
  33019. + * @return
  33020. + */
  33021. +static int __init dwc_otg_driver_init(void)
  33022. +{
  33023. + int retval = 0;
  33024. + int error;
  33025. + struct device_driver *drv;
  33026. + printk(KERN_INFO "%s: version %s (%s bus)\n", dwc_driver_name,
  33027. + DWC_DRIVER_VERSION,
  33028. +#ifdef LM_INTERFACE
  33029. + "logicmodule");
  33030. + retval = lm_driver_register(&dwc_otg_driver);
  33031. + drv = &dwc_otg_driver.drv;
  33032. +#elif defined(PCI_INTERFACE)
  33033. + "pci");
  33034. + retval = pci_register_driver(&dwc_otg_driver);
  33035. + drv = &dwc_otg_driver.driver;
  33036. +#elif defined(PLATFORM_INTERFACE)
  33037. + "platform");
  33038. + retval = platform_driver_register(&dwc_otg_driver);
  33039. + drv = &dwc_otg_driver.driver;
  33040. +#endif
  33041. + if (retval < 0) {
  33042. + printk(KERN_ERR "%s retval=%d\n", __func__, retval);
  33043. + return retval;
  33044. + }
  33045. +
  33046. + error = driver_create_file(drv, &driver_attr_version);
  33047. +#ifdef DEBUG
  33048. + error = driver_create_file(drv, &driver_attr_debuglevel);
  33049. +#endif
  33050. + return retval;
  33051. +}
  33052. +
  33053. +module_init(dwc_otg_driver_init);
  33054. +
  33055. +/**
  33056. + * This function is called when the driver is removed from the kernel
  33057. + * with the rmmod command. The driver unregisters itself with its bus
  33058. + * driver.
  33059. + *
  33060. + */
  33061. +static void __exit dwc_otg_driver_cleanup(void)
  33062. +{
  33063. + printk(KERN_DEBUG "dwc_otg_driver_cleanup()\n");
  33064. +
  33065. +#ifdef LM_INTERFACE
  33066. + driver_remove_file(&dwc_otg_driver.drv, &driver_attr_debuglevel);
  33067. + driver_remove_file(&dwc_otg_driver.drv, &driver_attr_version);
  33068. + lm_driver_unregister(&dwc_otg_driver);
  33069. +#elif defined(PCI_INTERFACE)
  33070. + driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);
  33071. + driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);
  33072. + pci_unregister_driver(&dwc_otg_driver);
  33073. +#elif defined(PLATFORM_INTERFACE)
  33074. + driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);
  33075. + driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);
  33076. + platform_driver_unregister(&dwc_otg_driver);
  33077. +#endif
  33078. +
  33079. + printk(KERN_INFO "%s module removed\n", dwc_driver_name);
  33080. +}
  33081. +
  33082. +module_exit(dwc_otg_driver_cleanup);
  33083. +
  33084. +MODULE_DESCRIPTION(DWC_DRIVER_DESC);
  33085. +MODULE_AUTHOR("Synopsys Inc.");
  33086. +MODULE_LICENSE("GPL");
  33087. +
  33088. +module_param_named(otg_cap, dwc_otg_module_params.otg_cap, int, 0444);
  33089. +MODULE_PARM_DESC(otg_cap, "OTG Capabilities 0=HNP&SRP 1=SRP Only 2=None");
  33090. +module_param_named(opt, dwc_otg_module_params.opt, int, 0444);
  33091. +MODULE_PARM_DESC(opt, "OPT Mode");
  33092. +module_param_named(dma_enable, dwc_otg_module_params.dma_enable, int, 0444);
  33093. +MODULE_PARM_DESC(dma_enable, "DMA Mode 0=Slave 1=DMA enabled");
  33094. +
  33095. +module_param_named(dma_desc_enable, dwc_otg_module_params.dma_desc_enable, int,
  33096. + 0444);
  33097. +MODULE_PARM_DESC(dma_desc_enable,
  33098. + "DMA Desc Mode 0=Address DMA 1=DMA Descriptor enabled");
  33099. +
  33100. +module_param_named(dma_burst_size, dwc_otg_module_params.dma_burst_size, int,
  33101. + 0444);
  33102. +MODULE_PARM_DESC(dma_burst_size,
  33103. + "DMA Burst Size 1, 4, 8, 16, 32, 64, 128, 256");
  33104. +module_param_named(speed, dwc_otg_module_params.speed, int, 0444);
  33105. +MODULE_PARM_DESC(speed, "Speed 0=High Speed 1=Full Speed");
  33106. +module_param_named(host_support_fs_ls_low_power,
  33107. + dwc_otg_module_params.host_support_fs_ls_low_power, int,
  33108. + 0444);
  33109. +MODULE_PARM_DESC(host_support_fs_ls_low_power,
  33110. + "Support Low Power w/FS or LS 0=Support 1=Don't Support");
  33111. +module_param_named(host_ls_low_power_phy_clk,
  33112. + dwc_otg_module_params.host_ls_low_power_phy_clk, int, 0444);
  33113. +MODULE_PARM_DESC(host_ls_low_power_phy_clk,
  33114. + "Low Speed Low Power Clock 0=48Mhz 1=6Mhz");
  33115. +module_param_named(enable_dynamic_fifo,
  33116. + dwc_otg_module_params.enable_dynamic_fifo, int, 0444);
  33117. +MODULE_PARM_DESC(enable_dynamic_fifo, "0=cC Setting 1=Allow Dynamic Sizing");
  33118. +module_param_named(data_fifo_size, dwc_otg_module_params.data_fifo_size, int,
  33119. + 0444);
  33120. +MODULE_PARM_DESC(data_fifo_size,
  33121. + "Total number of words in the data FIFO memory 32-32768");
  33122. +module_param_named(dev_rx_fifo_size, dwc_otg_module_params.dev_rx_fifo_size,
  33123. + int, 0444);
  33124. +MODULE_PARM_DESC(dev_rx_fifo_size, "Number of words in the Rx FIFO 16-32768");
  33125. +module_param_named(dev_nperio_tx_fifo_size,
  33126. + dwc_otg_module_params.dev_nperio_tx_fifo_size, int, 0444);
  33127. +MODULE_PARM_DESC(dev_nperio_tx_fifo_size,
  33128. + "Number of words in the non-periodic Tx FIFO 16-32768");
  33129. +module_param_named(dev_perio_tx_fifo_size_1,
  33130. + dwc_otg_module_params.dev_perio_tx_fifo_size[0], int, 0444);
  33131. +MODULE_PARM_DESC(dev_perio_tx_fifo_size_1,
  33132. + "Number of words in the periodic Tx FIFO 4-768");
  33133. +module_param_named(dev_perio_tx_fifo_size_2,
  33134. + dwc_otg_module_params.dev_perio_tx_fifo_size[1], int, 0444);
  33135. +MODULE_PARM_DESC(dev_perio_tx_fifo_size_2,
  33136. + "Number of words in the periodic Tx FIFO 4-768");
  33137. +module_param_named(dev_perio_tx_fifo_size_3,
  33138. + dwc_otg_module_params.dev_perio_tx_fifo_size[2], int, 0444);
  33139. +MODULE_PARM_DESC(dev_perio_tx_fifo_size_3,
  33140. + "Number of words in the periodic Tx FIFO 4-768");
  33141. +module_param_named(dev_perio_tx_fifo_size_4,
  33142. + dwc_otg_module_params.dev_perio_tx_fifo_size[3], int, 0444);
  33143. +MODULE_PARM_DESC(dev_perio_tx_fifo_size_4,
  33144. + "Number of words in the periodic Tx FIFO 4-768");
  33145. +module_param_named(dev_perio_tx_fifo_size_5,
  33146. + dwc_otg_module_params.dev_perio_tx_fifo_size[4], int, 0444);
  33147. +MODULE_PARM_DESC(dev_perio_tx_fifo_size_5,
  33148. + "Number of words in the periodic Tx FIFO 4-768");
  33149. +module_param_named(dev_perio_tx_fifo_size_6,
  33150. + dwc_otg_module_params.dev_perio_tx_fifo_size[5], int, 0444);
  33151. +MODULE_PARM_DESC(dev_perio_tx_fifo_size_6,
  33152. + "Number of words in the periodic Tx FIFO 4-768");
  33153. +module_param_named(dev_perio_tx_fifo_size_7,
  33154. + dwc_otg_module_params.dev_perio_tx_fifo_size[6], int, 0444);
  33155. +MODULE_PARM_DESC(dev_perio_tx_fifo_size_7,
  33156. + "Number of words in the periodic Tx FIFO 4-768");
  33157. +module_param_named(dev_perio_tx_fifo_size_8,
  33158. + dwc_otg_module_params.dev_perio_tx_fifo_size[7], int, 0444);
  33159. +MODULE_PARM_DESC(dev_perio_tx_fifo_size_8,
  33160. + "Number of words in the periodic Tx FIFO 4-768");
  33161. +module_param_named(dev_perio_tx_fifo_size_9,
  33162. + dwc_otg_module_params.dev_perio_tx_fifo_size[8], int, 0444);
  33163. +MODULE_PARM_DESC(dev_perio_tx_fifo_size_9,
  33164. + "Number of words in the periodic Tx FIFO 4-768");
  33165. +module_param_named(dev_perio_tx_fifo_size_10,
  33166. + dwc_otg_module_params.dev_perio_tx_fifo_size[9], int, 0444);
  33167. +MODULE_PARM_DESC(dev_perio_tx_fifo_size_10,
  33168. + "Number of words in the periodic Tx FIFO 4-768");
  33169. +module_param_named(dev_perio_tx_fifo_size_11,
  33170. + dwc_otg_module_params.dev_perio_tx_fifo_size[10], int, 0444);
  33171. +MODULE_PARM_DESC(dev_perio_tx_fifo_size_11,
  33172. + "Number of words in the periodic Tx FIFO 4-768");
  33173. +module_param_named(dev_perio_tx_fifo_size_12,
  33174. + dwc_otg_module_params.dev_perio_tx_fifo_size[11], int, 0444);
  33175. +MODULE_PARM_DESC(dev_perio_tx_fifo_size_12,
  33176. + "Number of words in the periodic Tx FIFO 4-768");
  33177. +module_param_named(dev_perio_tx_fifo_size_13,
  33178. + dwc_otg_module_params.dev_perio_tx_fifo_size[12], int, 0444);
  33179. +MODULE_PARM_DESC(dev_perio_tx_fifo_size_13,
  33180. + "Number of words in the periodic Tx FIFO 4-768");
  33181. +module_param_named(dev_perio_tx_fifo_size_14,
  33182. + dwc_otg_module_params.dev_perio_tx_fifo_size[13], int, 0444);
  33183. +MODULE_PARM_DESC(dev_perio_tx_fifo_size_14,
  33184. + "Number of words in the periodic Tx FIFO 4-768");
  33185. +module_param_named(dev_perio_tx_fifo_size_15,
  33186. + dwc_otg_module_params.dev_perio_tx_fifo_size[14], int, 0444);
  33187. +MODULE_PARM_DESC(dev_perio_tx_fifo_size_15,
  33188. + "Number of words in the periodic Tx FIFO 4-768");
  33189. +module_param_named(host_rx_fifo_size, dwc_otg_module_params.host_rx_fifo_size,
  33190. + int, 0444);
  33191. +MODULE_PARM_DESC(host_rx_fifo_size, "Number of words in the Rx FIFO 16-32768");
  33192. +module_param_named(host_nperio_tx_fifo_size,
  33193. + dwc_otg_module_params.host_nperio_tx_fifo_size, int, 0444);
  33194. +MODULE_PARM_DESC(host_nperio_tx_fifo_size,
  33195. + "Number of words in the non-periodic Tx FIFO 16-32768");
  33196. +module_param_named(host_perio_tx_fifo_size,
  33197. + dwc_otg_module_params.host_perio_tx_fifo_size, int, 0444);
  33198. +MODULE_PARM_DESC(host_perio_tx_fifo_size,
  33199. + "Number of words in the host periodic Tx FIFO 16-32768");
  33200. +module_param_named(max_transfer_size, dwc_otg_module_params.max_transfer_size,
  33201. + int, 0444);
  33202. +/** @todo Set the max to 512K, modify checks */
  33203. +MODULE_PARM_DESC(max_transfer_size,
  33204. + "The maximum transfer size supported in bytes 2047-65535");
  33205. +module_param_named(max_packet_count, dwc_otg_module_params.max_packet_count,
  33206. + int, 0444);
  33207. +MODULE_PARM_DESC(max_packet_count,
  33208. + "The maximum number of packets in a transfer 15-511");
  33209. +module_param_named(host_channels, dwc_otg_module_params.host_channels, int,
  33210. + 0444);
  33211. +MODULE_PARM_DESC(host_channels,
  33212. + "The number of host channel registers to use 1-16");
  33213. +module_param_named(dev_endpoints, dwc_otg_module_params.dev_endpoints, int,
  33214. + 0444);
  33215. +MODULE_PARM_DESC(dev_endpoints,
  33216. + "The number of endpoints in addition to EP0 available for device mode 1-15");
  33217. +module_param_named(phy_type, dwc_otg_module_params.phy_type, int, 0444);
  33218. +MODULE_PARM_DESC(phy_type, "0=Reserved 1=UTMI+ 2=ULPI");
  33219. +module_param_named(phy_utmi_width, dwc_otg_module_params.phy_utmi_width, int,
  33220. + 0444);
  33221. +MODULE_PARM_DESC(phy_utmi_width, "Specifies the UTMI+ Data Width 8 or 16 bits");
  33222. +module_param_named(phy_ulpi_ddr, dwc_otg_module_params.phy_ulpi_ddr, int, 0444);
  33223. +MODULE_PARM_DESC(phy_ulpi_ddr,
  33224. + "ULPI at double or single data rate 0=Single 1=Double");
  33225. +module_param_named(phy_ulpi_ext_vbus, dwc_otg_module_params.phy_ulpi_ext_vbus,
  33226. + int, 0444);
  33227. +MODULE_PARM_DESC(phy_ulpi_ext_vbus,
  33228. + "ULPI PHY using internal or external vbus 0=Internal");
  33229. +module_param_named(i2c_enable, dwc_otg_module_params.i2c_enable, int, 0444);
  33230. +MODULE_PARM_DESC(i2c_enable, "FS PHY Interface");
  33231. +module_param_named(ulpi_fs_ls, dwc_otg_module_params.ulpi_fs_ls, int, 0444);
  33232. +MODULE_PARM_DESC(ulpi_fs_ls, "ULPI PHY FS/LS mode only");
  33233. +module_param_named(ts_dline, dwc_otg_module_params.ts_dline, int, 0444);
  33234. +MODULE_PARM_DESC(ts_dline, "Term select Dline pulsing for all PHYs");
  33235. +module_param_named(debug, g_dbg_lvl, int, 0444);
  33236. +MODULE_PARM_DESC(debug, "");
  33237. +
  33238. +module_param_named(en_multiple_tx_fifo,
  33239. + dwc_otg_module_params.en_multiple_tx_fifo, int, 0444);
  33240. +MODULE_PARM_DESC(en_multiple_tx_fifo,
  33241. + "Dedicated Non Periodic Tx FIFOs 0=disabled 1=enabled");
  33242. +module_param_named(dev_tx_fifo_size_1,
  33243. + dwc_otg_module_params.dev_tx_fifo_size[0], int, 0444);
  33244. +MODULE_PARM_DESC(dev_tx_fifo_size_1, "Number of words in the Tx FIFO 4-768");
  33245. +module_param_named(dev_tx_fifo_size_2,
  33246. + dwc_otg_module_params.dev_tx_fifo_size[1], int, 0444);
  33247. +MODULE_PARM_DESC(dev_tx_fifo_size_2, "Number of words in the Tx FIFO 4-768");
  33248. +module_param_named(dev_tx_fifo_size_3,
  33249. + dwc_otg_module_params.dev_tx_fifo_size[2], int, 0444);
  33250. +MODULE_PARM_DESC(dev_tx_fifo_size_3, "Number of words in the Tx FIFO 4-768");
  33251. +module_param_named(dev_tx_fifo_size_4,
  33252. + dwc_otg_module_params.dev_tx_fifo_size[3], int, 0444);
  33253. +MODULE_PARM_DESC(dev_tx_fifo_size_4, "Number of words in the Tx FIFO 4-768");
  33254. +module_param_named(dev_tx_fifo_size_5,
  33255. + dwc_otg_module_params.dev_tx_fifo_size[4], int, 0444);
  33256. +MODULE_PARM_DESC(dev_tx_fifo_size_5, "Number of words in the Tx FIFO 4-768");
  33257. +module_param_named(dev_tx_fifo_size_6,
  33258. + dwc_otg_module_params.dev_tx_fifo_size[5], int, 0444);
  33259. +MODULE_PARM_DESC(dev_tx_fifo_size_6, "Number of words in the Tx FIFO 4-768");
  33260. +module_param_named(dev_tx_fifo_size_7,
  33261. + dwc_otg_module_params.dev_tx_fifo_size[6], int, 0444);
  33262. +MODULE_PARM_DESC(dev_tx_fifo_size_7, "Number of words in the Tx FIFO 4-768");
  33263. +module_param_named(dev_tx_fifo_size_8,
  33264. + dwc_otg_module_params.dev_tx_fifo_size[7], int, 0444);
  33265. +MODULE_PARM_DESC(dev_tx_fifo_size_8, "Number of words in the Tx FIFO 4-768");
  33266. +module_param_named(dev_tx_fifo_size_9,
  33267. + dwc_otg_module_params.dev_tx_fifo_size[8], int, 0444);
  33268. +MODULE_PARM_DESC(dev_tx_fifo_size_9, "Number of words in the Tx FIFO 4-768");
  33269. +module_param_named(dev_tx_fifo_size_10,
  33270. + dwc_otg_module_params.dev_tx_fifo_size[9], int, 0444);
  33271. +MODULE_PARM_DESC(dev_tx_fifo_size_10, "Number of words in the Tx FIFO 4-768");
  33272. +module_param_named(dev_tx_fifo_size_11,
  33273. + dwc_otg_module_params.dev_tx_fifo_size[10], int, 0444);
  33274. +MODULE_PARM_DESC(dev_tx_fifo_size_11, "Number of words in the Tx FIFO 4-768");
  33275. +module_param_named(dev_tx_fifo_size_12,
  33276. + dwc_otg_module_params.dev_tx_fifo_size[11], int, 0444);
  33277. +MODULE_PARM_DESC(dev_tx_fifo_size_12, "Number of words in the Tx FIFO 4-768");
  33278. +module_param_named(dev_tx_fifo_size_13,
  33279. + dwc_otg_module_params.dev_tx_fifo_size[12], int, 0444);
  33280. +MODULE_PARM_DESC(dev_tx_fifo_size_13, "Number of words in the Tx FIFO 4-768");
  33281. +module_param_named(dev_tx_fifo_size_14,
  33282. + dwc_otg_module_params.dev_tx_fifo_size[13], int, 0444);
  33283. +MODULE_PARM_DESC(dev_tx_fifo_size_14, "Number of words in the Tx FIFO 4-768");
  33284. +module_param_named(dev_tx_fifo_size_15,
  33285. + dwc_otg_module_params.dev_tx_fifo_size[14], int, 0444);
  33286. +MODULE_PARM_DESC(dev_tx_fifo_size_15, "Number of words in the Tx FIFO 4-768");
  33287. +
  33288. +module_param_named(thr_ctl, dwc_otg_module_params.thr_ctl, int, 0444);
  33289. +MODULE_PARM_DESC(thr_ctl,
  33290. + "Thresholding enable flag bit 0 - non ISO Tx thr., 1 - ISO Tx thr., 2 - Rx thr.- bit 0=disabled 1=enabled");
  33291. +module_param_named(tx_thr_length, dwc_otg_module_params.tx_thr_length, int,
  33292. + 0444);
  33293. +MODULE_PARM_DESC(tx_thr_length, "Tx Threshold length in 32 bit DWORDs");
  33294. +module_param_named(rx_thr_length, dwc_otg_module_params.rx_thr_length, int,
  33295. + 0444);
  33296. +MODULE_PARM_DESC(rx_thr_length, "Rx Threshold length in 32 bit DWORDs");
  33297. +
  33298. +module_param_named(pti_enable, dwc_otg_module_params.pti_enable, int, 0444);
  33299. +module_param_named(mpi_enable, dwc_otg_module_params.mpi_enable, int, 0444);
  33300. +module_param_named(lpm_enable, dwc_otg_module_params.lpm_enable, int, 0444);
  33301. +MODULE_PARM_DESC(lpm_enable, "LPM Enable 0=LPM Disabled 1=LPM Enabled");
  33302. +module_param_named(ic_usb_cap, dwc_otg_module_params.ic_usb_cap, int, 0444);
  33303. +MODULE_PARM_DESC(ic_usb_cap,
  33304. + "IC_USB Capability 0=IC_USB Disabled 1=IC_USB Enabled");
  33305. +module_param_named(ahb_thr_ratio, dwc_otg_module_params.ahb_thr_ratio, int,
  33306. + 0444);
  33307. +MODULE_PARM_DESC(ahb_thr_ratio, "AHB Threshold Ratio");
  33308. +module_param_named(power_down, dwc_otg_module_params.power_down, int, 0444);
  33309. +MODULE_PARM_DESC(power_down, "Power Down Mode");
  33310. +module_param_named(reload_ctl, dwc_otg_module_params.reload_ctl, int, 0444);
  33311. +MODULE_PARM_DESC(reload_ctl, "HFIR Reload Control");
  33312. +module_param_named(dev_out_nak, dwc_otg_module_params.dev_out_nak, int, 0444);
  33313. +MODULE_PARM_DESC(dev_out_nak, "Enable Device OUT NAK");
  33314. +module_param_named(cont_on_bna, dwc_otg_module_params.cont_on_bna, int, 0444);
  33315. +MODULE_PARM_DESC(cont_on_bna, "Enable Enable Continue on BNA");
  33316. +module_param_named(ahb_single, dwc_otg_module_params.ahb_single, int, 0444);
  33317. +MODULE_PARM_DESC(ahb_single, "Enable AHB Single Support");
  33318. +module_param_named(adp_enable, dwc_otg_module_params.adp_enable, int, 0444);
  33319. +MODULE_PARM_DESC(adp_enable, "ADP Enable 0=ADP Disabled 1=ADP Enabled");
  33320. +module_param_named(otg_ver, dwc_otg_module_params.otg_ver, int, 0444);
  33321. +MODULE_PARM_DESC(otg_ver, "OTG revision supported 0=OTG 1.3 1=OTG 2.0");
  33322. +module_param(microframe_schedule, bool, 0444);
  33323. +MODULE_PARM_DESC(microframe_schedule, "Enable the microframe scheduler");
  33324. +
  33325. +/** @page "Module Parameters"
  33326. + *
  33327. + * The following parameters may be specified when starting the module.
  33328. + * These parameters define how the DWC_otg controller should be
  33329. + * configured. Parameter values are passed to the CIL initialization
  33330. + * function dwc_otg_cil_init
  33331. + *
  33332. + * Example: <code>modprobe dwc_otg speed=1 otg_cap=1</code>
  33333. + *
  33334. +
  33335. + <table>
  33336. + <tr><td>Parameter Name</td><td>Meaning</td></tr>
  33337. +
  33338. + <tr>
  33339. + <td>otg_cap</td>
  33340. + <td>Specifies the OTG capabilities. The driver will automatically detect the
  33341. + value for this parameter if none is specified.
  33342. + - 0: HNP and SRP capable (default, if available)
  33343. + - 1: SRP Only capable
  33344. + - 2: No HNP/SRP capable
  33345. + </td></tr>
  33346. +
  33347. + <tr>
  33348. + <td>dma_enable</td>
  33349. + <td>Specifies whether to use slave or DMA mode for accessing the data FIFOs.
  33350. + The driver will automatically detect the value for this parameter if none is
  33351. + specified.
  33352. + - 0: Slave
  33353. + - 1: DMA (default, if available)
  33354. + </td></tr>
  33355. +
  33356. + <tr>
  33357. + <td>dma_burst_size</td>
  33358. + <td>The DMA Burst size (applicable only for External DMA Mode).
  33359. + - Values: 1, 4, 8 16, 32, 64, 128, 256 (default 32)
  33360. + </td></tr>
  33361. +
  33362. + <tr>
  33363. + <td>speed</td>
  33364. + <td>Specifies the maximum speed of operation in host and device mode. The
  33365. + actual speed depends on the speed of the attached device and the value of
  33366. + phy_type.
  33367. + - 0: High Speed (default)
  33368. + - 1: Full Speed
  33369. + </td></tr>
  33370. +
  33371. + <tr>
  33372. + <td>host_support_fs_ls_low_power</td>
  33373. + <td>Specifies whether low power mode is supported when attached to a Full
  33374. + Speed or Low Speed device in host mode.
  33375. + - 0: Don't support low power mode (default)
  33376. + - 1: Support low power mode
  33377. + </td></tr>
  33378. +
  33379. + <tr>
  33380. + <td>host_ls_low_power_phy_clk</td>
  33381. + <td>Specifies the PHY clock rate in low power mode when connected to a Low
  33382. + Speed device in host mode. This parameter is applicable only if
  33383. + HOST_SUPPORT_FS_LS_LOW_POWER is enabled.
  33384. + - 0: 48 MHz (default)
  33385. + - 1: 6 MHz
  33386. + </td></tr>
  33387. +
  33388. + <tr>
  33389. + <td>enable_dynamic_fifo</td>
  33390. + <td> Specifies whether FIFOs may be resized by the driver software.
  33391. + - 0: Use cC FIFO size parameters
  33392. + - 1: Allow dynamic FIFO sizing (default)
  33393. + </td></tr>
  33394. +
  33395. + <tr>
  33396. + <td>data_fifo_size</td>
  33397. + <td>Total number of 4-byte words in the data FIFO memory. This memory
  33398. + includes the Rx FIFO, non-periodic Tx FIFO, and periodic Tx FIFOs.
  33399. + - Values: 32 to 32768 (default 8192)
  33400. +
  33401. + Note: The total FIFO memory depth in the FPGA configuration is 8192.
  33402. + </td></tr>
  33403. +
  33404. + <tr>
  33405. + <td>dev_rx_fifo_size</td>
  33406. + <td>Number of 4-byte words in the Rx FIFO in device mode when dynamic
  33407. + FIFO sizing is enabled.
  33408. + - Values: 16 to 32768 (default 1064)
  33409. + </td></tr>
  33410. +
  33411. + <tr>
  33412. + <td>dev_nperio_tx_fifo_size</td>
  33413. + <td>Number of 4-byte words in the non-periodic Tx FIFO in device mode when
  33414. + dynamic FIFO sizing is enabled.
  33415. + - Values: 16 to 32768 (default 1024)
  33416. + </td></tr>
  33417. +
  33418. + <tr>
  33419. + <td>dev_perio_tx_fifo_size_n (n = 1 to 15)</td>
  33420. + <td>Number of 4-byte words in each of the periodic Tx FIFOs in device mode
  33421. + when dynamic FIFO sizing is enabled.
  33422. + - Values: 4 to 768 (default 256)
  33423. + </td></tr>
  33424. +
  33425. + <tr>
  33426. + <td>host_rx_fifo_size</td>
  33427. + <td>Number of 4-byte words in the Rx FIFO in host mode when dynamic FIFO
  33428. + sizing is enabled.
  33429. + - Values: 16 to 32768 (default 1024)
  33430. + </td></tr>
  33431. +
  33432. + <tr>
  33433. + <td>host_nperio_tx_fifo_size</td>
  33434. + <td>Number of 4-byte words in the non-periodic Tx FIFO in host mode when
  33435. + dynamic FIFO sizing is enabled in the core.
  33436. + - Values: 16 to 32768 (default 1024)
  33437. + </td></tr>
  33438. +
  33439. + <tr>
  33440. + <td>host_perio_tx_fifo_size</td>
  33441. + <td>Number of 4-byte words in the host periodic Tx FIFO when dynamic FIFO
  33442. + sizing is enabled.
  33443. + - Values: 16 to 32768 (default 1024)
  33444. + </td></tr>
  33445. +
  33446. + <tr>
  33447. + <td>max_transfer_size</td>
  33448. + <td>The maximum transfer size supported in bytes.
  33449. + - Values: 2047 to 65,535 (default 65,535)
  33450. + </td></tr>
  33451. +
  33452. + <tr>
  33453. + <td>max_packet_count</td>
  33454. + <td>The maximum number of packets in a transfer.
  33455. + - Values: 15 to 511 (default 511)
  33456. + </td></tr>
  33457. +
  33458. + <tr>
  33459. + <td>host_channels</td>
  33460. + <td>The number of host channel registers to use.
  33461. + - Values: 1 to 16 (default 12)
  33462. +
  33463. + Note: The FPGA configuration supports a maximum of 12 host channels.
  33464. + </td></tr>
  33465. +
  33466. + <tr>
  33467. + <td>dev_endpoints</td>
  33468. + <td>The number of endpoints in addition to EP0 available for device mode
  33469. + operations.
  33470. + - Values: 1 to 15 (default 6 IN and OUT)
  33471. +
  33472. + Note: The FPGA configuration supports a maximum of 6 IN and OUT endpoints in
  33473. + addition to EP0.
  33474. + </td></tr>
  33475. +
  33476. + <tr>
  33477. + <td>phy_type</td>
  33478. + <td>Specifies the type of PHY interface to use. By default, the driver will
  33479. + automatically detect the phy_type.
  33480. + - 0: Full Speed
  33481. + - 1: UTMI+ (default, if available)
  33482. + - 2: ULPI
  33483. + </td></tr>
  33484. +
  33485. + <tr>
  33486. + <td>phy_utmi_width</td>
  33487. + <td>Specifies the UTMI+ Data Width. This parameter is applicable for a
  33488. + phy_type of UTMI+. Also, this parameter is applicable only if the
  33489. + OTG_HSPHY_WIDTH cC parameter was set to "8 and 16 bits", meaning that the
  33490. + core has been configured to work at either data path width.
  33491. + - Values: 8 or 16 bits (default 16)
  33492. + </td></tr>
  33493. +
  33494. + <tr>
  33495. + <td>phy_ulpi_ddr</td>
  33496. + <td>Specifies whether the ULPI operates at double or single data rate. This
  33497. + parameter is only applicable if phy_type is ULPI.
  33498. + - 0: single data rate ULPI interface with 8 bit wide data bus (default)
  33499. + - 1: double data rate ULPI interface with 4 bit wide data bus
  33500. + </td></tr>
  33501. +
  33502. + <tr>
  33503. + <td>i2c_enable</td>
  33504. + <td>Specifies whether to use the I2C interface for full speed PHY. This
  33505. + parameter is only applicable if PHY_TYPE is FS.
  33506. + - 0: Disabled (default)
  33507. + - 1: Enabled
  33508. + </td></tr>
  33509. +
  33510. + <tr>
  33511. + <td>ulpi_fs_ls</td>
  33512. + <td>Specifies whether to use ULPI FS/LS mode only.
  33513. + - 0: Disabled (default)
  33514. + - 1: Enabled
  33515. + </td></tr>
  33516. +
  33517. + <tr>
  33518. + <td>ts_dline</td>
  33519. + <td>Specifies whether term select D-Line pulsing for all PHYs is enabled.
  33520. + - 0: Disabled (default)
  33521. + - 1: Enabled
  33522. + </td></tr>
  33523. +
  33524. + <tr>
  33525. + <td>en_multiple_tx_fifo</td>
  33526. + <td>Specifies whether dedicatedto tx fifos are enabled for non periodic IN EPs.
  33527. + The driver will automatically detect the value for this parameter if none is
  33528. + specified.
  33529. + - 0: Disabled
  33530. + - 1: Enabled (default, if available)
  33531. + </td></tr>
  33532. +
  33533. + <tr>
  33534. + <td>dev_tx_fifo_size_n (n = 1 to 15)</td>
  33535. + <td>Number of 4-byte words in each of the Tx FIFOs in device mode
  33536. + when dynamic FIFO sizing is enabled.
  33537. + - Values: 4 to 768 (default 256)
  33538. + </td></tr>
  33539. +
  33540. + <tr>
  33541. + <td>tx_thr_length</td>
  33542. + <td>Transmit Threshold length in 32 bit double words
  33543. + - Values: 8 to 128 (default 64)
  33544. + </td></tr>
  33545. +
  33546. + <tr>
  33547. + <td>rx_thr_length</td>
  33548. + <td>Receive Threshold length in 32 bit double words
  33549. + - Values: 8 to 128 (default 64)
  33550. + </td></tr>
  33551. +
  33552. +<tr>
  33553. + <td>thr_ctl</td>
  33554. + <td>Specifies whether to enable Thresholding for Device mode. Bits 0, 1, 2 of
  33555. + this parmater specifies if thresholding is enabled for non-Iso Tx, Iso Tx and
  33556. + Rx transfers accordingly.
  33557. + The driver will automatically detect the value for this parameter if none is
  33558. + specified.
  33559. + - Values: 0 to 7 (default 0)
  33560. + Bit values indicate:
  33561. + - 0: Thresholding disabled
  33562. + - 1: Thresholding enabled
  33563. + </td></tr>
  33564. +
  33565. +<tr>
  33566. + <td>dma_desc_enable</td>
  33567. + <td>Specifies whether to enable Descriptor DMA mode.
  33568. + The driver will automatically detect the value for this parameter if none is
  33569. + specified.
  33570. + - 0: Descriptor DMA disabled
  33571. + - 1: Descriptor DMA (default, if available)
  33572. + </td></tr>
  33573. +
  33574. +<tr>
  33575. + <td>mpi_enable</td>
  33576. + <td>Specifies whether to enable MPI enhancement mode.
  33577. + The driver will automatically detect the value for this parameter if none is
  33578. + specified.
  33579. + - 0: MPI disabled (default)
  33580. + - 1: MPI enable
  33581. + </td></tr>
  33582. +
  33583. +<tr>
  33584. + <td>pti_enable</td>
  33585. + <td>Specifies whether to enable PTI enhancement support.
  33586. + The driver will automatically detect the value for this parameter if none is
  33587. + specified.
  33588. + - 0: PTI disabled (default)
  33589. + - 1: PTI enable
  33590. + </td></tr>
  33591. +
  33592. +<tr>
  33593. + <td>lpm_enable</td>
  33594. + <td>Specifies whether to enable LPM support.
  33595. + The driver will automatically detect the value for this parameter if none is
  33596. + specified.
  33597. + - 0: LPM disabled
  33598. + - 1: LPM enable (default, if available)
  33599. + </td></tr>
  33600. +
  33601. +<tr>
  33602. + <td>ic_usb_cap</td>
  33603. + <td>Specifies whether to enable IC_USB capability.
  33604. + The driver will automatically detect the value for this parameter if none is
  33605. + specified.
  33606. + - 0: IC_USB disabled (default, if available)
  33607. + - 1: IC_USB enable
  33608. + </td></tr>
  33609. +
  33610. +<tr>
  33611. + <td>ahb_thr_ratio</td>
  33612. + <td>Specifies AHB Threshold ratio.
  33613. + - Values: 0 to 3 (default 0)
  33614. + </td></tr>
  33615. +
  33616. +<tr>
  33617. + <td>power_down</td>
  33618. + <td>Specifies Power Down(Hibernation) Mode.
  33619. + The driver will automatically detect the value for this parameter if none is
  33620. + specified.
  33621. + - 0: Power Down disabled (default)
  33622. + - 2: Power Down enabled
  33623. + </td></tr>
  33624. +
  33625. + <tr>
  33626. + <td>reload_ctl</td>
  33627. + <td>Specifies whether dynamic reloading of the HFIR register is allowed during
  33628. + run time. The driver will automatically detect the value for this parameter if
  33629. + none is specified. In case the HFIR value is reloaded when HFIR.RldCtrl == 1'b0
  33630. + the core might misbehave.
  33631. + - 0: Reload Control disabled (default)
  33632. + - 1: Reload Control enabled
  33633. + </td></tr>
  33634. +
  33635. + <tr>
  33636. + <td>dev_out_nak</td>
  33637. + <td>Specifies whether Device OUT NAK enhancement enabled or no.
  33638. + The driver will automatically detect the value for this parameter if
  33639. + none is specified. This parameter is valid only when OTG_EN_DESC_DMA == 1b1.
  33640. + - 0: The core does not set NAK after Bulk OUT transfer complete (default)
  33641. + - 1: The core sets NAK after Bulk OUT transfer complete
  33642. + </td></tr>
  33643. +
  33644. + <tr>
  33645. + <td>cont_on_bna</td>
  33646. + <td>Specifies whether Enable Continue on BNA enabled or no.
  33647. + After receiving BNA interrupt the core disables the endpoint,when the
  33648. + endpoint is re-enabled by the application the
  33649. + - 0: Core starts processing from the DOEPDMA descriptor (default)
  33650. + - 1: Core starts processing from the descriptor which received the BNA.
  33651. + This parameter is valid only when OTG_EN_DESC_DMA == 1b1.
  33652. + </td></tr>
  33653. +
  33654. + <tr>
  33655. + <td>ahb_single</td>
  33656. + <td>This bit when programmed supports SINGLE transfers for remainder data
  33657. + in a transfer for DMA mode of operation.
  33658. + - 0: The remainder data will be sent using INCR burst size (default)
  33659. + - 1: The remainder data will be sent using SINGLE burst size.
  33660. + </td></tr>
  33661. +
  33662. +<tr>
  33663. + <td>adp_enable</td>
  33664. + <td>Specifies whether ADP feature is enabled.
  33665. + The driver will automatically detect the value for this parameter if none is
  33666. + specified.
  33667. + - 0: ADP feature disabled (default)
  33668. + - 1: ADP feature enabled
  33669. + </td></tr>
  33670. +
  33671. + <tr>
  33672. + <td>otg_ver</td>
  33673. + <td>Specifies whether OTG is performing as USB OTG Revision 2.0 or Revision 1.3
  33674. + USB OTG device.
  33675. + - 0: OTG 2.0 support disabled (default)
  33676. + - 1: OTG 2.0 support enabled
  33677. + </td></tr>
  33678. +
  33679. +*/
  33680. --- /dev/null
  33681. +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.h
  33682. @@ -0,0 +1,86 @@
  33683. +/* ==========================================================================
  33684. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $
  33685. + * $Revision: #19 $
  33686. + * $Date: 2010/11/15 $
  33687. + * $Change: 1627671 $
  33688. + *
  33689. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  33690. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  33691. + * otherwise expressly agreed to in writing between Synopsys and you.
  33692. + *
  33693. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  33694. + * any End User Software License Agreement or Agreement for Licensed Product
  33695. + * with Synopsys or any supplement thereto. You are permitted to use and
  33696. + * redistribute this Software in source and binary forms, with or without
  33697. + * modification, provided that redistributions of source code must retain this
  33698. + * notice. You may not view, use, disclose, copy or distribute this file or
  33699. + * any information contained herein except pursuant to this license grant from
  33700. + * Synopsys. If you do not agree with this notice, including the disclaimer
  33701. + * below, then you are not authorized to use the Software.
  33702. + *
  33703. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  33704. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  33705. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33706. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  33707. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  33708. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  33709. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  33710. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33711. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33712. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  33713. + * DAMAGE.
  33714. + * ========================================================================== */
  33715. +
  33716. +#ifndef __DWC_OTG_DRIVER_H__
  33717. +#define __DWC_OTG_DRIVER_H__
  33718. +
  33719. +/** @file
  33720. + * This file contains the interface to the Linux driver.
  33721. + */
  33722. +#include "dwc_otg_os_dep.h"
  33723. +#include "dwc_otg_core_if.h"
  33724. +
  33725. +/* Type declarations */
  33726. +struct dwc_otg_pcd;
  33727. +struct dwc_otg_hcd;
  33728. +
  33729. +/**
  33730. + * This structure is a wrapper that encapsulates the driver components used to
  33731. + * manage a single DWC_otg controller.
  33732. + */
  33733. +typedef struct dwc_otg_device {
  33734. + /** Structure containing OS-dependent stuff. KEEP THIS STRUCT AT THE
  33735. + * VERY BEGINNING OF THE DEVICE STRUCT. OSes such as FreeBSD and NetBSD
  33736. + * require this. */
  33737. + struct os_dependent os_dep;
  33738. +
  33739. + /** Pointer to the core interface structure. */
  33740. + dwc_otg_core_if_t *core_if;
  33741. +
  33742. + /** Pointer to the PCD structure. */
  33743. + struct dwc_otg_pcd *pcd;
  33744. +
  33745. + /** Pointer to the HCD structure. */
  33746. + struct dwc_otg_hcd *hcd;
  33747. +
  33748. + /** Flag to indicate whether the common IRQ handler is installed. */
  33749. + uint8_t common_irq_installed;
  33750. +
  33751. +} dwc_otg_device_t;
  33752. +
  33753. +/*We must clear S3C24XX_EINTPEND external interrupt register
  33754. + * because after clearing in this register trigerred IRQ from
  33755. + * H/W core in kernel interrupt can be occured again before OTG
  33756. + * handlers clear all IRQ sources of Core registers because of
  33757. + * timing latencies and Low Level IRQ Type.
  33758. + */
  33759. +#ifdef CONFIG_MACH_IPMATE
  33760. +#define S3C2410X_CLEAR_EINTPEND() \
  33761. +do { \
  33762. + __raw_writel(1UL << 11,S3C24XX_EINTPEND); \
  33763. +} while (0)
  33764. +#else
  33765. +#define S3C2410X_CLEAR_EINTPEND() do { } while (0)
  33766. +#endif
  33767. +
  33768. +#endif
  33769. --- /dev/null
  33770. +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
  33771. @@ -0,0 +1,3479 @@
  33772. +
  33773. +/* ==========================================================================
  33774. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $
  33775. + * $Revision: #104 $
  33776. + * $Date: 2011/10/24 $
  33777. + * $Change: 1871159 $
  33778. + *
  33779. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  33780. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  33781. + * otherwise expressly agreed to in writing between Synopsys and you.
  33782. + *
  33783. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  33784. + * any End User Software License Agreement or Agreement for Licensed Product
  33785. + * with Synopsys or any supplement thereto. You are permitted to use and
  33786. + * redistribute this Software in source and binary forms, with or without
  33787. + * modification, provided that redistributions of source code must retain this
  33788. + * notice. You may not view, use, disclose, copy or distribute this file or
  33789. + * any information contained herein except pursuant to this license grant from
  33790. + * Synopsys. If you do not agree with this notice, including the disclaimer
  33791. + * below, then you are not authorized to use the Software.
  33792. + *
  33793. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  33794. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  33795. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33796. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  33797. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  33798. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  33799. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  33800. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33801. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33802. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  33803. + * DAMAGE.
  33804. + * ========================================================================== */
  33805. +#ifndef DWC_DEVICE_ONLY
  33806. +
  33807. +/** @file
  33808. + * This file implements HCD Core. All code in this file is portable and doesn't
  33809. + * use any OS specific functions.
  33810. + * Interface provided by HCD Core is defined in <code><hcd_if.h></code>
  33811. + * header file.
  33812. + */
  33813. +
  33814. +#include "dwc_otg_hcd.h"
  33815. +#include "dwc_otg_regs.h"
  33816. +
  33817. +extern bool microframe_schedule;
  33818. +
  33819. +//#define DEBUG_HOST_CHANNELS
  33820. +#ifdef DEBUG_HOST_CHANNELS
  33821. +static int last_sel_trans_num_per_scheduled = 0;
  33822. +static int last_sel_trans_num_nonper_scheduled = 0;
  33823. +static int last_sel_trans_num_avail_hc_at_start = 0;
  33824. +static int last_sel_trans_num_avail_hc_at_end = 0;
  33825. +#endif /* DEBUG_HOST_CHANNELS */
  33826. +
  33827. +dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)
  33828. +{
  33829. + return DWC_ALLOC(sizeof(dwc_otg_hcd_t));
  33830. +}
  33831. +
  33832. +/**
  33833. + * Connection timeout function. An OTG host is required to display a
  33834. + * message if the device does not connect within 10 seconds.
  33835. + */
  33836. +void dwc_otg_hcd_connect_timeout(void *ptr)
  33837. +{
  33838. + DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, ptr);
  33839. + DWC_PRINTF("Connect Timeout\n");
  33840. + __DWC_ERROR("Device Not Connected/Responding\n");
  33841. +}
  33842. +
  33843. +#if defined(DEBUG)
  33844. +static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
  33845. +{
  33846. + if (qh->channel != NULL) {
  33847. + dwc_hc_t *hc = qh->channel;
  33848. + dwc_list_link_t *item;
  33849. + dwc_otg_qh_t *qh_item;
  33850. + int num_channels = hcd->core_if->core_params->host_channels;
  33851. + int i;
  33852. +
  33853. + dwc_otg_hc_regs_t *hc_regs;
  33854. + hcchar_data_t hcchar;
  33855. + hcsplt_data_t hcsplt;
  33856. + hctsiz_data_t hctsiz;
  33857. + uint32_t hcdma;
  33858. +
  33859. + hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num];
  33860. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  33861. + hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
  33862. + hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
  33863. + hcdma = DWC_READ_REG32(&hc_regs->hcdma);
  33864. +
  33865. + DWC_PRINTF(" Assigned to channel %p:\n", hc);
  33866. + DWC_PRINTF(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32,
  33867. + hcsplt.d32);
  33868. + DWC_PRINTF(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32,
  33869. + hcdma);
  33870. + DWC_PRINTF(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
  33871. + hc->dev_addr, hc->ep_num, hc->ep_is_in);
  33872. + DWC_PRINTF(" ep_type: %d\n", hc->ep_type);
  33873. + DWC_PRINTF(" max_packet: %d\n", hc->max_packet);
  33874. + DWC_PRINTF(" data_pid_start: %d\n", hc->data_pid_start);
  33875. + DWC_PRINTF(" xfer_started: %d\n", hc->xfer_started);
  33876. + DWC_PRINTF(" halt_status: %d\n", hc->halt_status);
  33877. + DWC_PRINTF(" xfer_buff: %p\n", hc->xfer_buff);
  33878. + DWC_PRINTF(" xfer_len: %d\n", hc->xfer_len);
  33879. + DWC_PRINTF(" qh: %p\n", hc->qh);
  33880. + DWC_PRINTF(" NP inactive sched:\n");
  33881. + DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_inactive) {
  33882. + qh_item =
  33883. + DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
  33884. + DWC_PRINTF(" %p\n", qh_item);
  33885. + }
  33886. + DWC_PRINTF(" NP active sched:\n");
  33887. + DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_active) {
  33888. + qh_item =
  33889. + DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
  33890. + DWC_PRINTF(" %p\n", qh_item);
  33891. + }
  33892. + DWC_PRINTF(" Channels: \n");
  33893. + for (i = 0; i < num_channels; i++) {
  33894. + dwc_hc_t *hc = hcd->hc_ptr_array[i];
  33895. + DWC_PRINTF(" %2d: %p\n", i, hc);
  33896. + }
  33897. + }
  33898. +}
  33899. +#else
  33900. +#define dump_channel_info(hcd, qh)
  33901. +#endif /* DEBUG */
  33902. +
  33903. +/**
  33904. + * Work queue function for starting the HCD when A-Cable is connected.
  33905. + * The hcd_start() must be called in a process context.
  33906. + */
  33907. +static void hcd_start_func(void *_vp)
  33908. +{
  33909. + dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) _vp;
  33910. +
  33911. + DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, hcd);
  33912. + if (hcd) {
  33913. + hcd->fops->start(hcd);
  33914. + }
  33915. +}
  33916. +
  33917. +static void del_xfer_timers(dwc_otg_hcd_t * hcd)
  33918. +{
  33919. +#ifdef DEBUG
  33920. + int i;
  33921. + int num_channels = hcd->core_if->core_params->host_channels;
  33922. + for (i = 0; i < num_channels; i++) {
  33923. + DWC_TIMER_CANCEL(hcd->core_if->hc_xfer_timer[i]);
  33924. + }
  33925. +#endif
  33926. +}
  33927. +
  33928. +static void del_timers(dwc_otg_hcd_t * hcd)
  33929. +{
  33930. + del_xfer_timers(hcd);
  33931. + DWC_TIMER_CANCEL(hcd->conn_timer);
  33932. +}
  33933. +
  33934. +/**
  33935. + * Processes all the URBs in a single list of QHs. Completes them with
  33936. + * -ETIMEDOUT and frees the QTD.
  33937. + */
  33938. +static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
  33939. +{
  33940. + dwc_list_link_t *qh_item;
  33941. + dwc_otg_qh_t *qh;
  33942. + dwc_otg_qtd_t *qtd, *qtd_tmp;
  33943. +
  33944. + DWC_LIST_FOREACH(qh_item, qh_list) {
  33945. + qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry);
  33946. + DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp,
  33947. + &qh->qtd_list, qtd_list_entry) {
  33948. + qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
  33949. + if (qtd->urb != NULL) {
  33950. + hcd->fops->complete(hcd, qtd->urb->priv,
  33951. + qtd->urb, -DWC_E_TIMEOUT);
  33952. + dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
  33953. + }
  33954. +
  33955. + }
  33956. + }
  33957. +}
  33958. +
  33959. +/**
  33960. + * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic
  33961. + * and periodic schedules. The QTD associated with each URB is removed from
  33962. + * the schedule and freed. This function may be called when a disconnect is
  33963. + * detected or when the HCD is being stopped.
  33964. + */
  33965. +static void kill_all_urbs(dwc_otg_hcd_t * hcd)
  33966. +{
  33967. + kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive);
  33968. + kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active);
  33969. + kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive);
  33970. + kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready);
  33971. + kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned);
  33972. + kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued);
  33973. +}
  33974. +
  33975. +/**
  33976. + * Start the connection timer. An OTG host is required to display a
  33977. + * message if the device does not connect within 10 seconds. The
  33978. + * timer is deleted if a port connect interrupt occurs before the
  33979. + * timer expires.
  33980. + */
  33981. +static void dwc_otg_hcd_start_connect_timer(dwc_otg_hcd_t * hcd)
  33982. +{
  33983. + DWC_TIMER_SCHEDULE(hcd->conn_timer, 10000 /* 10 secs */ );
  33984. +}
  33985. +
  33986. +/**
  33987. + * HCD Callback function for disconnect of the HCD.
  33988. + *
  33989. + * @param p void pointer to the <code>struct usb_hcd</code>
  33990. + */
  33991. +static int32_t dwc_otg_hcd_session_start_cb(void *p)
  33992. +{
  33993. + dwc_otg_hcd_t *dwc_otg_hcd;
  33994. + DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
  33995. + dwc_otg_hcd = p;
  33996. + dwc_otg_hcd_start_connect_timer(dwc_otg_hcd);
  33997. + return 1;
  33998. +}
  33999. +
  34000. +/**
  34001. + * HCD Callback function for starting the HCD when A-Cable is
  34002. + * connected.
  34003. + *
  34004. + * @param p void pointer to the <code>struct usb_hcd</code>
  34005. + */
  34006. +static int32_t dwc_otg_hcd_start_cb(void *p)
  34007. +{
  34008. + dwc_otg_hcd_t *dwc_otg_hcd = p;
  34009. + dwc_otg_core_if_t *core_if;
  34010. + hprt0_data_t hprt0;
  34011. +
  34012. + core_if = dwc_otg_hcd->core_if;
  34013. +
  34014. + if (core_if->op_state == B_HOST) {
  34015. + /*
  34016. + * Reset the port. During a HNP mode switch the reset
  34017. + * needs to occur within 1ms and have a duration of at
  34018. + * least 50ms.
  34019. + */
  34020. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  34021. + hprt0.b.prtrst = 1;
  34022. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  34023. + }
  34024. + DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg,
  34025. + hcd_start_func, dwc_otg_hcd, 50,
  34026. + "start hcd");
  34027. +
  34028. + return 1;
  34029. +}
  34030. +
  34031. +/**
  34032. + * HCD Callback function for disconnect of the HCD.
  34033. + *
  34034. + * @param p void pointer to the <code>struct usb_hcd</code>
  34035. + */
  34036. +static int32_t dwc_otg_hcd_disconnect_cb(void *p)
  34037. +{
  34038. + gintsts_data_t intr;
  34039. + dwc_otg_hcd_t *dwc_otg_hcd = p;
  34040. +
  34041. + /*
  34042. + * Set status flags for the hub driver.
  34043. + */
  34044. + dwc_otg_hcd->flags.b.port_connect_status_change = 1;
  34045. + dwc_otg_hcd->flags.b.port_connect_status = 0;
  34046. +
  34047. + /*
  34048. + * Shutdown any transfers in process by clearing the Tx FIFO Empty
  34049. + * interrupt mask and status bits and disabling subsequent host
  34050. + * channel interrupts.
  34051. + */
  34052. + intr.d32 = 0;
  34053. + intr.b.nptxfempty = 1;
  34054. + intr.b.ptxfempty = 1;
  34055. + intr.b.hcintr = 1;
  34056. + DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk,
  34057. + intr.d32, 0);
  34058. + DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintsts,
  34059. + intr.d32, 0);
  34060. +
  34061. + del_timers(dwc_otg_hcd);
  34062. +
  34063. + /*
  34064. + * Turn off the vbus power only if the core has transitioned to device
  34065. + * mode. If still in host mode, need to keep power on to detect a
  34066. + * reconnection.
  34067. + */
  34068. + if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) {
  34069. + if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) {
  34070. + hprt0_data_t hprt0 = {.d32 = 0 };
  34071. + DWC_PRINTF("Disconnect: PortPower off\n");
  34072. + hprt0.b.prtpwr = 0;
  34073. + DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0,
  34074. + hprt0.d32);
  34075. + }
  34076. +
  34077. + dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if);
  34078. + }
  34079. +
  34080. + /* Respond with an error status to all URBs in the schedule. */
  34081. + kill_all_urbs(dwc_otg_hcd);
  34082. +
  34083. + if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) {
  34084. + /* Clean up any host channels that were in use. */
  34085. + int num_channels;
  34086. + int i;
  34087. + dwc_hc_t *channel;
  34088. + dwc_otg_hc_regs_t *hc_regs;
  34089. + hcchar_data_t hcchar;
  34090. +
  34091. + num_channels = dwc_otg_hcd->core_if->core_params->host_channels;
  34092. +
  34093. + if (!dwc_otg_hcd->core_if->dma_enable) {
  34094. + /* Flush out any channel requests in slave mode. */
  34095. + for (i = 0; i < num_channels; i++) {
  34096. + channel = dwc_otg_hcd->hc_ptr_array[i];
  34097. + if (DWC_CIRCLEQ_EMPTY_ENTRY
  34098. + (channel, hc_list_entry)) {
  34099. + hc_regs =
  34100. + dwc_otg_hcd->core_if->
  34101. + host_if->hc_regs[i];
  34102. + hcchar.d32 =
  34103. + DWC_READ_REG32(&hc_regs->hcchar);
  34104. + if (hcchar.b.chen) {
  34105. + hcchar.b.chen = 0;
  34106. + hcchar.b.chdis = 1;
  34107. + hcchar.b.epdir = 0;
  34108. + DWC_WRITE_REG32
  34109. + (&hc_regs->hcchar,
  34110. + hcchar.d32);
  34111. + }
  34112. + }
  34113. + }
  34114. + }
  34115. +
  34116. + for (i = 0; i < num_channels; i++) {
  34117. + channel = dwc_otg_hcd->hc_ptr_array[i];
  34118. + if (DWC_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) {
  34119. + hc_regs =
  34120. + dwc_otg_hcd->core_if->host_if->hc_regs[i];
  34121. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  34122. + if (hcchar.b.chen) {
  34123. + /* Halt the channel. */
  34124. + hcchar.b.chdis = 1;
  34125. + DWC_WRITE_REG32(&hc_regs->hcchar,
  34126. + hcchar.d32);
  34127. + }
  34128. +
  34129. + dwc_otg_hc_cleanup(dwc_otg_hcd->core_if,
  34130. + channel);
  34131. + DWC_CIRCLEQ_INSERT_TAIL
  34132. + (&dwc_otg_hcd->free_hc_list, channel,
  34133. + hc_list_entry);
  34134. + /*
  34135. + * Added for Descriptor DMA to prevent channel double cleanup
  34136. + * in release_channel_ddma(). Which called from ep_disable
  34137. + * when device disconnect.
  34138. + */
  34139. + channel->qh = NULL;
  34140. + }
  34141. + }
  34142. + }
  34143. +
  34144. + if (dwc_otg_hcd->fops->disconnect) {
  34145. + dwc_otg_hcd->fops->disconnect(dwc_otg_hcd);
  34146. + }
  34147. +
  34148. + return 1;
  34149. +}
  34150. +
  34151. +/**
  34152. + * HCD Callback function for stopping the HCD.
  34153. + *
  34154. + * @param p void pointer to the <code>struct usb_hcd</code>
  34155. + */
  34156. +static int32_t dwc_otg_hcd_stop_cb(void *p)
  34157. +{
  34158. + dwc_otg_hcd_t *dwc_otg_hcd = p;
  34159. +
  34160. + DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p);
  34161. + dwc_otg_hcd_stop(dwc_otg_hcd);
  34162. + return 1;
  34163. +}
  34164. +
  34165. +#ifdef CONFIG_USB_DWC_OTG_LPM
  34166. +/**
  34167. + * HCD Callback function for sleep of HCD.
  34168. + *
  34169. + * @param p void pointer to the <code>struct usb_hcd</code>
  34170. + */
  34171. +static int dwc_otg_hcd_sleep_cb(void *p)
  34172. +{
  34173. + dwc_otg_hcd_t *hcd = p;
  34174. +
  34175. + dwc_otg_hcd_free_hc_from_lpm(hcd);
  34176. +
  34177. + return 0;
  34178. +}
  34179. +#endif
  34180. +
  34181. +/**
  34182. + * HCD Callback function for Remote Wakeup.
  34183. + *
  34184. + * @param p void pointer to the <code>struct usb_hcd</code>
  34185. + */
  34186. +static int dwc_otg_hcd_rem_wakeup_cb(void *p)
  34187. +{
  34188. + dwc_otg_hcd_t *hcd = p;
  34189. +
  34190. + if (hcd->core_if->lx_state == DWC_OTG_L2) {
  34191. + hcd->flags.b.port_suspend_change = 1;
  34192. + }
  34193. +#ifdef CONFIG_USB_DWC_OTG_LPM
  34194. + else {
  34195. + hcd->flags.b.port_l1_change = 1;
  34196. + }
  34197. +#endif
  34198. + return 0;
  34199. +}
  34200. +
  34201. +/**
  34202. + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
  34203. + * stopped.
  34204. + */
  34205. +void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd)
  34206. +{
  34207. + hprt0_data_t hprt0 = {.d32 = 0 };
  34208. +
  34209. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n");
  34210. +
  34211. + /*
  34212. + * The root hub should be disconnected before this function is called.
  34213. + * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue)
  34214. + * and the QH lists (via ..._hcd_endpoint_disable).
  34215. + */
  34216. +
  34217. + /* Turn off all host-specific interrupts. */
  34218. + dwc_otg_disable_host_interrupts(hcd->core_if);
  34219. +
  34220. + /* Turn off the vbus power */
  34221. + DWC_PRINTF("PortPower off\n");
  34222. + hprt0.b.prtpwr = 0;
  34223. + DWC_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32);
  34224. + dwc_mdelay(1);
  34225. +}
  34226. +
  34227. +int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd,
  34228. + dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle,
  34229. + int atomic_alloc)
  34230. +{
  34231. + dwc_irqflags_t flags;
  34232. + int retval = 0;
  34233. + dwc_otg_qtd_t *qtd;
  34234. + gintmsk_data_t intr_mask = {.d32 = 0 };
  34235. +
  34236. +#ifdef DEBUG /* integrity checks (Broadcom) */
  34237. + if (NULL == hcd->core_if) {
  34238. + DWC_ERROR("**** DWC OTG HCD URB Enqueue - HCD has NULL core_if\n");
  34239. + /* No longer connected. */
  34240. + return -DWC_E_INVALID;
  34241. + }
  34242. +#endif
  34243. + if (!hcd->flags.b.port_connect_status) {
  34244. + /* No longer connected. */
  34245. + DWC_ERROR("Not connected\n");
  34246. + return -DWC_E_NO_DEVICE;
  34247. + }
  34248. +
  34249. + qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc);
  34250. + if (qtd == NULL) {
  34251. + DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n");
  34252. + return -DWC_E_NO_MEMORY;
  34253. + }
  34254. +#ifdef DEBUG /* integrity checks (Broadcom) */
  34255. + if (qtd->urb == NULL) {
  34256. + DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD with no URBs\n");
  34257. + return -DWC_E_NO_MEMORY;
  34258. + }
  34259. + if (qtd->urb->priv == NULL) {
  34260. + DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD URB with no URB handle\n");
  34261. + return -DWC_E_NO_MEMORY;
  34262. + }
  34263. +#endif
  34264. + retval =
  34265. + dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc);
  34266. + // creates a new queue in ep_handle if it doesn't exist already
  34267. + if (retval < 0) {
  34268. + DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. "
  34269. + "Error status %d\n", retval);
  34270. + dwc_otg_hcd_qtd_free(qtd);
  34271. + } else {
  34272. + qtd->qh = *ep_handle;
  34273. + }
  34274. + intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);
  34275. + if (!intr_mask.b.sofintr && retval == 0) {
  34276. + dwc_otg_transaction_type_e tr_type;
  34277. + if ((qtd->qh->ep_type == UE_BULK)
  34278. + && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) {
  34279. + /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */
  34280. + return 0;
  34281. + }
  34282. + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
  34283. + tr_type = dwc_otg_hcd_select_transactions(hcd);
  34284. + if (tr_type != DWC_OTG_TRANSACTION_NONE) {
  34285. + dwc_otg_hcd_queue_transactions(hcd, tr_type);
  34286. + }
  34287. + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
  34288. + }
  34289. +
  34290. + return retval;
  34291. +}
  34292. +
  34293. +int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
  34294. + dwc_otg_hcd_urb_t * dwc_otg_urb)
  34295. +{
  34296. + dwc_otg_qh_t *qh;
  34297. + dwc_otg_qtd_t *urb_qtd;
  34298. +
  34299. +#ifdef DEBUG /* integrity checks (Broadcom) */
  34300. +
  34301. + if (hcd == NULL) {
  34302. + DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL HCD\n");
  34303. + return -DWC_E_INVALID;
  34304. + }
  34305. + if (dwc_otg_urb == NULL) {
  34306. + DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL URB\n");
  34307. + return -DWC_E_INVALID;
  34308. + }
  34309. + if (dwc_otg_urb->qtd == NULL) {
  34310. + DWC_ERROR("**** DWC OTG HCD URB Dequeue with NULL QTD\n");
  34311. + return -DWC_E_INVALID;
  34312. + }
  34313. + urb_qtd = dwc_otg_urb->qtd;
  34314. + if (urb_qtd->qh == NULL) {
  34315. + DWC_ERROR("**** DWC OTG HCD URB Dequeue with QTD with NULL Q handler\n");
  34316. + return -DWC_E_INVALID;
  34317. + }
  34318. +#else
  34319. + urb_qtd = dwc_otg_urb->qtd;
  34320. +#endif
  34321. + qh = urb_qtd->qh;
  34322. + if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
  34323. + if (urb_qtd->in_process) {
  34324. + dump_channel_info(hcd, qh);
  34325. + }
  34326. + }
  34327. +#ifdef DEBUG /* integrity checks (Broadcom) */
  34328. + if (hcd->core_if == NULL) {
  34329. + DWC_ERROR("**** DWC OTG HCD URB Dequeue HCD has NULL core_if\n");
  34330. + return -DWC_E_INVALID;
  34331. + }
  34332. +#endif
  34333. + if (urb_qtd->in_process && qh->channel) {
  34334. + /* The QTD is in process (it has been assigned to a channel). */
  34335. + if (hcd->flags.b.port_connect_status) {
  34336. + /*
  34337. + * If still connected (i.e. in host mode), halt the
  34338. + * channel so it can be used for other transfers. If
  34339. + * no longer connected, the host registers can't be
  34340. + * written to halt the channel since the core is in
  34341. + * device mode.
  34342. + */
  34343. + dwc_otg_hc_halt(hcd->core_if, qh->channel,
  34344. + DWC_OTG_HC_XFER_URB_DEQUEUE);
  34345. + }
  34346. + }
  34347. +
  34348. + /*
  34349. + * Free the QTD and clean up the associated QH. Leave the QH in the
  34350. + * schedule if it has any remaining QTDs.
  34351. + */
  34352. +
  34353. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue - "
  34354. + "delete %sQueue handler\n",
  34355. + hcd->core_if->dma_desc_enable?"DMA ":"");
  34356. + if (!hcd->core_if->dma_desc_enable) {
  34357. + uint8_t b = urb_qtd->in_process;
  34358. + dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
  34359. + if (b) {
  34360. + dwc_otg_hcd_qh_deactivate(hcd, qh, 0);
  34361. + qh->channel = NULL;
  34362. + } else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
  34363. + dwc_otg_hcd_qh_remove(hcd, qh);
  34364. + }
  34365. + } else {
  34366. + dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
  34367. + }
  34368. + return 0;
  34369. +}
  34370. +
  34371. +int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,
  34372. + int retry)
  34373. +{
  34374. + dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
  34375. + int retval = 0;
  34376. + dwc_irqflags_t flags;
  34377. +
  34378. + if (retry < 0) {
  34379. + retval = -DWC_E_INVALID;
  34380. + goto done;
  34381. + }
  34382. +
  34383. + if (!qh) {
  34384. + retval = -DWC_E_INVALID;
  34385. + goto done;
  34386. + }
  34387. +
  34388. + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
  34389. +
  34390. + while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) {
  34391. + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
  34392. + retry--;
  34393. + dwc_msleep(5);
  34394. + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
  34395. + }
  34396. +
  34397. + dwc_otg_hcd_qh_remove(hcd, qh);
  34398. +
  34399. + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
  34400. + /*
  34401. + * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove
  34402. + * and qh_free to prevent stack dump on DWC_DMA_FREE() with
  34403. + * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free()
  34404. + * and dwc_otg_hcd_frame_list_alloc().
  34405. + */
  34406. + dwc_otg_hcd_qh_free(hcd, qh);
  34407. +
  34408. +done:
  34409. + return retval;
  34410. +}
  34411. +
  34412. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
  34413. +int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle)
  34414. +{
  34415. + int retval = 0;
  34416. + dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
  34417. + if (!qh)
  34418. + return -DWC_E_INVALID;
  34419. +
  34420. + qh->data_toggle = DWC_OTG_HC_PID_DATA0;
  34421. + return retval;
  34422. +}
  34423. +#endif
  34424. +
  34425. +/**
  34426. + * HCD Callback structure for handling mode switching.
  34427. + */
  34428. +static dwc_otg_cil_callbacks_t hcd_cil_callbacks = {
  34429. + .start = dwc_otg_hcd_start_cb,
  34430. + .stop = dwc_otg_hcd_stop_cb,
  34431. + .disconnect = dwc_otg_hcd_disconnect_cb,
  34432. + .session_start = dwc_otg_hcd_session_start_cb,
  34433. + .resume_wakeup = dwc_otg_hcd_rem_wakeup_cb,
  34434. +#ifdef CONFIG_USB_DWC_OTG_LPM
  34435. + .sleep = dwc_otg_hcd_sleep_cb,
  34436. +#endif
  34437. + .p = 0,
  34438. +};
  34439. +
  34440. +/**
  34441. + * Reset tasklet function
  34442. + */
  34443. +static void reset_tasklet_func(void *data)
  34444. +{
  34445. + dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *) data;
  34446. + dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
  34447. + hprt0_data_t hprt0;
  34448. +
  34449. + DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n");
  34450. +
  34451. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  34452. + hprt0.b.prtrst = 1;
  34453. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  34454. + dwc_mdelay(60);
  34455. +
  34456. + hprt0.b.prtrst = 0;
  34457. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  34458. + dwc_otg_hcd->flags.b.port_reset_change = 1;
  34459. +}
  34460. +
  34461. +static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
  34462. +{
  34463. + dwc_list_link_t *item;
  34464. + dwc_otg_qh_t *qh;
  34465. + dwc_irqflags_t flags;
  34466. +
  34467. + if (!qh_list->next) {
  34468. + /* The list hasn't been initialized yet. */
  34469. + return;
  34470. + }
  34471. + /*
  34472. + * Hold spinlock here. Not needed in that case if bellow
  34473. + * function is being called from ISR
  34474. + */
  34475. + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
  34476. + /* Ensure there are no QTDs or URBs left. */
  34477. + kill_urbs_in_qh_list(hcd, qh_list);
  34478. + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
  34479. +
  34480. + DWC_LIST_FOREACH(item, qh_list) {
  34481. + qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry);
  34482. + dwc_otg_hcd_qh_remove_and_free(hcd, qh);
  34483. + }
  34484. +}
  34485. +
  34486. +/**
  34487. + * Exit from Hibernation if Host did not detect SRP from connected SRP capable
  34488. + * Device during SRP time by host power up.
  34489. + */
  34490. +void dwc_otg_hcd_power_up(void *ptr)
  34491. +{
  34492. + gpwrdn_data_t gpwrdn = {.d32 = 0 };
  34493. + dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
  34494. +
  34495. + DWC_PRINTF("%s called\n", __FUNCTION__);
  34496. +
  34497. + if (!core_if->hibernation_suspend) {
  34498. + DWC_PRINTF("Already exited from Hibernation\n");
  34499. + return;
  34500. + }
  34501. +
  34502. + /* Switch on the voltage to the core */
  34503. + gpwrdn.b.pwrdnswtch = 1;
  34504. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  34505. + dwc_udelay(10);
  34506. +
  34507. + /* Reset the core */
  34508. + gpwrdn.d32 = 0;
  34509. + gpwrdn.b.pwrdnrstn = 1;
  34510. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  34511. + dwc_udelay(10);
  34512. +
  34513. + /* Disable power clamps */
  34514. + gpwrdn.d32 = 0;
  34515. + gpwrdn.b.pwrdnclmp = 1;
  34516. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  34517. +
  34518. + /* Remove reset the core signal */
  34519. + gpwrdn.d32 = 0;
  34520. + gpwrdn.b.pwrdnrstn = 1;
  34521. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32);
  34522. + dwc_udelay(10);
  34523. +
  34524. + /* Disable PMU interrupt */
  34525. + gpwrdn.d32 = 0;
  34526. + gpwrdn.b.pmuintsel = 1;
  34527. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  34528. +
  34529. + core_if->hibernation_suspend = 0;
  34530. +
  34531. + /* Disable PMU */
  34532. + gpwrdn.d32 = 0;
  34533. + gpwrdn.b.pmuactv = 1;
  34534. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  34535. + dwc_udelay(10);
  34536. +
  34537. + /* Enable VBUS */
  34538. + gpwrdn.d32 = 0;
  34539. + gpwrdn.b.dis_vbus = 1;
  34540. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0);
  34541. +
  34542. + core_if->op_state = A_HOST;
  34543. + dwc_otg_core_init(core_if);
  34544. + dwc_otg_enable_global_interrupts(core_if);
  34545. + cil_hcd_start(core_if);
  34546. +}
  34547. +
  34548. +/**
  34549. + * Frees secondary storage associated with the dwc_otg_hcd structure contained
  34550. + * in the struct usb_hcd field.
  34551. + */
  34552. +static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd)
  34553. +{
  34554. + int i;
  34555. +
  34556. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n");
  34557. +
  34558. + del_timers(dwc_otg_hcd);
  34559. +
  34560. + /* Free memory for QH/QTD lists */
  34561. + qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive);
  34562. + qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active);
  34563. + qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive);
  34564. + qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready);
  34565. + qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned);
  34566. + qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued);
  34567. +
  34568. + /* Free memory for the host channels. */
  34569. + for (i = 0; i < MAX_EPS_CHANNELS; i++) {
  34570. + dwc_hc_t *hc = dwc_otg_hcd->hc_ptr_array[i];
  34571. +
  34572. +#ifdef DEBUG
  34573. + if (dwc_otg_hcd->core_if->hc_xfer_timer[i]) {
  34574. + DWC_TIMER_FREE(dwc_otg_hcd->core_if->hc_xfer_timer[i]);
  34575. + }
  34576. +#endif
  34577. + if (hc != NULL) {
  34578. + DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n",
  34579. + i, hc);
  34580. + DWC_FREE(hc);
  34581. + }
  34582. + }
  34583. +
  34584. + if (dwc_otg_hcd->core_if->dma_enable) {
  34585. + if (dwc_otg_hcd->status_buf_dma) {
  34586. + DWC_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE,
  34587. + dwc_otg_hcd->status_buf,
  34588. + dwc_otg_hcd->status_buf_dma);
  34589. + }
  34590. + } else if (dwc_otg_hcd->status_buf != NULL) {
  34591. + DWC_FREE(dwc_otg_hcd->status_buf);
  34592. + }
  34593. + DWC_SPINLOCK_FREE(dwc_otg_hcd->lock);
  34594. + /* Set core_if's lock pointer to NULL */
  34595. + dwc_otg_hcd->core_if->lock = NULL;
  34596. +
  34597. + DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
  34598. + DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
  34599. +
  34600. +#ifdef DWC_DEV_SRPCAP
  34601. + if (dwc_otg_hcd->core_if->power_down == 2 &&
  34602. + dwc_otg_hcd->core_if->pwron_timer) {
  34603. + DWC_TIMER_FREE(dwc_otg_hcd->core_if->pwron_timer);
  34604. + }
  34605. +#endif
  34606. + DWC_FREE(dwc_otg_hcd);
  34607. +}
  34608. +
  34609. +int init_hcd_usecs(dwc_otg_hcd_t *_hcd);
  34610. +
  34611. +int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
  34612. +{
  34613. + int retval = 0;
  34614. + int num_channels;
  34615. + int i;
  34616. + dwc_hc_t *channel;
  34617. +
  34618. +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_SPINLOCK))
  34619. + DWC_SPINLOCK_ALLOC_LINUX_DEBUG(hcd->lock);
  34620. + DWC_SPINLOCK_ALLOC_LINUX_DEBUG(hcd->channel_lock);
  34621. +#else
  34622. + hcd->lock = DWC_SPINLOCK_ALLOC();
  34623. + hcd->channel_lock = DWC_SPINLOCK_ALLOC();
  34624. +#endif
  34625. + DWC_DEBUGPL(DBG_HCDV, "init of HCD %p given core_if %p\n",
  34626. + hcd, core_if);
  34627. + if (!hcd->lock) {
  34628. + DWC_ERROR("Could not allocate lock for pcd");
  34629. + DWC_FREE(hcd);
  34630. + retval = -DWC_E_NO_MEMORY;
  34631. + goto out;
  34632. + }
  34633. + hcd->core_if = core_if;
  34634. +
  34635. + /* Register the HCD CIL Callbacks */
  34636. + dwc_otg_cil_register_hcd_callbacks(hcd->core_if,
  34637. + &hcd_cil_callbacks, hcd);
  34638. +
  34639. + /* Initialize the non-periodic schedule. */
  34640. + DWC_LIST_INIT(&hcd->non_periodic_sched_inactive);
  34641. + DWC_LIST_INIT(&hcd->non_periodic_sched_active);
  34642. +
  34643. + /* Initialize the periodic schedule. */
  34644. + DWC_LIST_INIT(&hcd->periodic_sched_inactive);
  34645. + DWC_LIST_INIT(&hcd->periodic_sched_ready);
  34646. + DWC_LIST_INIT(&hcd->periodic_sched_assigned);
  34647. + DWC_LIST_INIT(&hcd->periodic_sched_queued);
  34648. +
  34649. + /*
  34650. + * Create a host channel descriptor for each host channel implemented
  34651. + * in the controller. Initialize the channel descriptor array.
  34652. + */
  34653. + DWC_CIRCLEQ_INIT(&hcd->free_hc_list);
  34654. + num_channels = hcd->core_if->core_params->host_channels;
  34655. + DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array));
  34656. + for (i = 0; i < num_channels; i++) {
  34657. + channel = DWC_ALLOC(sizeof(dwc_hc_t));
  34658. + if (channel == NULL) {
  34659. + retval = -DWC_E_NO_MEMORY;
  34660. + DWC_ERROR("%s: host channel allocation failed\n",
  34661. + __func__);
  34662. + dwc_otg_hcd_free(hcd);
  34663. + goto out;
  34664. + }
  34665. + channel->hc_num = i;
  34666. + hcd->hc_ptr_array[i] = channel;
  34667. +#ifdef DEBUG
  34668. + hcd->core_if->hc_xfer_timer[i] =
  34669. + DWC_TIMER_ALLOC("hc timer", hc_xfer_timeout,
  34670. + &hcd->core_if->hc_xfer_info[i]);
  34671. +#endif
  34672. + DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i,
  34673. + channel);
  34674. + }
  34675. +
  34676. + /* Initialize the Connection timeout timer. */
  34677. + hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer",
  34678. + dwc_otg_hcd_connect_timeout, 0);
  34679. +
  34680. + printk(KERN_DEBUG "dwc_otg: Microframe scheduler %s\n", microframe_schedule ? "enabled":"disabled");
  34681. + if (microframe_schedule)
  34682. + init_hcd_usecs(hcd);
  34683. +
  34684. + /* Initialize reset tasklet. */
  34685. + hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd);
  34686. +#ifdef DWC_DEV_SRPCAP
  34687. + if (hcd->core_if->power_down == 2) {
  34688. + /* Initialize Power on timer for Host power up in case hibernation */
  34689. + hcd->core_if->pwron_timer = DWC_TIMER_ALLOC("PWRON TIMER",
  34690. + dwc_otg_hcd_power_up, core_if);
  34691. + }
  34692. +#endif
  34693. +
  34694. + /*
  34695. + * Allocate space for storing data on status transactions. Normally no
  34696. + * data is sent, but this space acts as a bit bucket. This must be
  34697. + * done after usb_add_hcd since that function allocates the DMA buffer
  34698. + * pool.
  34699. + */
  34700. + if (hcd->core_if->dma_enable) {
  34701. + hcd->status_buf =
  34702. + DWC_DMA_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE,
  34703. + &hcd->status_buf_dma);
  34704. + } else {
  34705. + hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE);
  34706. + }
  34707. + if (!hcd->status_buf) {
  34708. + retval = -DWC_E_NO_MEMORY;
  34709. + DWC_ERROR("%s: status_buf allocation failed\n", __func__);
  34710. + dwc_otg_hcd_free(hcd);
  34711. + goto out;
  34712. + }
  34713. +
  34714. + hcd->otg_port = 1;
  34715. + hcd->frame_list = NULL;
  34716. + hcd->frame_list_dma = 0;
  34717. + hcd->periodic_qh_count = 0;
  34718. +out:
  34719. + return retval;
  34720. +}
  34721. +
  34722. +void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd)
  34723. +{
  34724. + /* Turn off all host-specific interrupts. */
  34725. + dwc_otg_disable_host_interrupts(hcd->core_if);
  34726. +
  34727. + dwc_otg_hcd_free(hcd);
  34728. +}
  34729. +
  34730. +/**
  34731. + * Initializes dynamic portions of the DWC_otg HCD state.
  34732. + */
  34733. +static void dwc_otg_hcd_reinit(dwc_otg_hcd_t * hcd)
  34734. +{
  34735. + int num_channels;
  34736. + int i;
  34737. + dwc_hc_t *channel;
  34738. + dwc_hc_t *channel_tmp;
  34739. +
  34740. + hcd->flags.d32 = 0;
  34741. +
  34742. + hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active;
  34743. + if (!microframe_schedule) {
  34744. + hcd->non_periodic_channels = 0;
  34745. + hcd->periodic_channels = 0;
  34746. + } else {
  34747. + hcd->available_host_channels = hcd->core_if->core_params->host_channels;
  34748. + }
  34749. + /*
  34750. + * Put all channels in the free channel list and clean up channel
  34751. + * states.
  34752. + */
  34753. + DWC_CIRCLEQ_FOREACH_SAFE(channel, channel_tmp,
  34754. + &hcd->free_hc_list, hc_list_entry) {
  34755. + DWC_CIRCLEQ_REMOVE(&hcd->free_hc_list, channel, hc_list_entry);
  34756. + }
  34757. +
  34758. + num_channels = hcd->core_if->core_params->host_channels;
  34759. + for (i = 0; i < num_channels; i++) {
  34760. + channel = hcd->hc_ptr_array[i];
  34761. + DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, channel,
  34762. + hc_list_entry);
  34763. + dwc_otg_hc_cleanup(hcd->core_if, channel);
  34764. + }
  34765. +
  34766. + /* Initialize the DWC core for host mode operation. */
  34767. + dwc_otg_core_host_init(hcd->core_if);
  34768. +
  34769. + /* Set core_if's lock pointer to the hcd->lock */
  34770. + hcd->core_if->lock = hcd->lock;
  34771. +}
  34772. +
  34773. +/**
  34774. + * Assigns transactions from a QTD to a free host channel and initializes the
  34775. + * host channel to perform the transactions. The host channel is removed from
  34776. + * the free list.
  34777. + *
  34778. + * @param hcd The HCD state structure.
  34779. + * @param qh Transactions from the first QTD for this QH are selected and
  34780. + * assigned to a free host channel.
  34781. + */
  34782. +static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
  34783. +{
  34784. + dwc_hc_t *hc;
  34785. + dwc_otg_qtd_t *qtd;
  34786. + dwc_otg_hcd_urb_t *urb;
  34787. + void* ptr = NULL;
  34788. +
  34789. + qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
  34790. +
  34791. + urb = qtd->urb;
  34792. +
  34793. + DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p) - urb %x, actual_length %d\n", __func__, hcd, qh, (unsigned int)urb, urb->actual_length);
  34794. +
  34795. + if (((urb->actual_length < 0) || (urb->actual_length > urb->length)) && !dwc_otg_hcd_is_pipe_in(&urb->pipe_info))
  34796. + urb->actual_length = urb->length;
  34797. +
  34798. +
  34799. + hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
  34800. +
  34801. + /* Remove the host channel from the free list. */
  34802. + DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
  34803. +
  34804. + qh->channel = hc;
  34805. +
  34806. + qtd->in_process = 1;
  34807. +
  34808. + /*
  34809. + * Use usb_pipedevice to determine device address. This address is
  34810. + * 0 before the SET_ADDRESS command and the correct address afterward.
  34811. + */
  34812. + hc->dev_addr = dwc_otg_hcd_get_dev_addr(&urb->pipe_info);
  34813. + hc->ep_num = dwc_otg_hcd_get_ep_num(&urb->pipe_info);
  34814. + hc->speed = qh->dev_speed;
  34815. + hc->max_packet = dwc_max_packet(qh->maxp);
  34816. +
  34817. + hc->xfer_started = 0;
  34818. + hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS;
  34819. + hc->error_state = (qtd->error_count > 0);
  34820. + hc->halt_on_queue = 0;
  34821. + hc->halt_pending = 0;
  34822. + hc->requests = 0;
  34823. +
  34824. + /*
  34825. + * The following values may be modified in the transfer type section
  34826. + * below. The xfer_len value may be reduced when the transfer is
  34827. + * started to accommodate the max widths of the XferSize and PktCnt
  34828. + * fields in the HCTSIZn register.
  34829. + */
  34830. +
  34831. + hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0);
  34832. + if (hc->ep_is_in) {
  34833. + hc->do_ping = 0;
  34834. + } else {
  34835. + hc->do_ping = qh->ping_state;
  34836. + }
  34837. +
  34838. + hc->data_pid_start = qh->data_toggle;
  34839. + hc->multi_count = 1;
  34840. +
  34841. + if (hcd->core_if->dma_enable) {
  34842. + hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length;
  34843. +
  34844. + /* For non-dword aligned case */
  34845. + if (((unsigned long)hc->xfer_buff & 0x3)
  34846. + && !hcd->core_if->dma_desc_enable) {
  34847. + ptr = (uint8_t *) urb->buf + urb->actual_length;
  34848. + }
  34849. + } else {
  34850. + hc->xfer_buff = (uint8_t *) urb->buf + urb->actual_length;
  34851. + }
  34852. + hc->xfer_len = urb->length - urb->actual_length;
  34853. + hc->xfer_count = 0;
  34854. +
  34855. + /*
  34856. + * Set the split attributes
  34857. + */
  34858. + hc->do_split = 0;
  34859. + if (qh->do_split) {
  34860. + uint32_t hub_addr, port_addr;
  34861. + hc->do_split = 1;
  34862. + hc->xact_pos = qtd->isoc_split_pos;
  34863. + hc->complete_split = qtd->complete_split;
  34864. + hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr);
  34865. + hc->hub_addr = (uint8_t) hub_addr;
  34866. + hc->port_addr = (uint8_t) port_addr;
  34867. + }
  34868. +
  34869. + switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
  34870. + case UE_CONTROL:
  34871. + hc->ep_type = DWC_OTG_EP_TYPE_CONTROL;
  34872. + switch (qtd->control_phase) {
  34873. + case DWC_OTG_CONTROL_SETUP:
  34874. + DWC_DEBUGPL(DBG_HCDV, " Control setup transaction\n");
  34875. + hc->do_ping = 0;
  34876. + hc->ep_is_in = 0;
  34877. + hc->data_pid_start = DWC_OTG_HC_PID_SETUP;
  34878. + if (hcd->core_if->dma_enable) {
  34879. + hc->xfer_buff = (uint8_t *) urb->setup_dma;
  34880. + } else {
  34881. + hc->xfer_buff = (uint8_t *) urb->setup_packet;
  34882. + }
  34883. + hc->xfer_len = 8;
  34884. + ptr = NULL;
  34885. + break;
  34886. + case DWC_OTG_CONTROL_DATA:
  34887. + DWC_DEBUGPL(DBG_HCDV, " Control data transaction\n");
  34888. + hc->data_pid_start = qtd->data_toggle;
  34889. + break;
  34890. + case DWC_OTG_CONTROL_STATUS:
  34891. + /*
  34892. + * Direction is opposite of data direction or IN if no
  34893. + * data.
  34894. + */
  34895. + DWC_DEBUGPL(DBG_HCDV, " Control status transaction\n");
  34896. + if (urb->length == 0) {
  34897. + hc->ep_is_in = 1;
  34898. + } else {
  34899. + hc->ep_is_in =
  34900. + dwc_otg_hcd_is_pipe_out(&urb->pipe_info);
  34901. + }
  34902. + if (hc->ep_is_in) {
  34903. + hc->do_ping = 0;
  34904. + }
  34905. +
  34906. + hc->data_pid_start = DWC_OTG_HC_PID_DATA1;
  34907. +
  34908. + hc->xfer_len = 0;
  34909. + if (hcd->core_if->dma_enable) {
  34910. + hc->xfer_buff = (uint8_t *) hcd->status_buf_dma;
  34911. + } else {
  34912. + hc->xfer_buff = (uint8_t *) hcd->status_buf;
  34913. + }
  34914. + ptr = NULL;
  34915. + break;
  34916. + }
  34917. + break;
  34918. + case UE_BULK:
  34919. + hc->ep_type = DWC_OTG_EP_TYPE_BULK;
  34920. + break;
  34921. + case UE_INTERRUPT:
  34922. + hc->ep_type = DWC_OTG_EP_TYPE_INTR;
  34923. + break;
  34924. + case UE_ISOCHRONOUS:
  34925. + {
  34926. + struct dwc_otg_hcd_iso_packet_desc *frame_desc;
  34927. +
  34928. + hc->ep_type = DWC_OTG_EP_TYPE_ISOC;
  34929. +
  34930. + if (hcd->core_if->dma_desc_enable)
  34931. + break;
  34932. +
  34933. + frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
  34934. +
  34935. + frame_desc->status = 0;
  34936. +
  34937. + if (hcd->core_if->dma_enable) {
  34938. + hc->xfer_buff = (uint8_t *) urb->dma;
  34939. + } else {
  34940. + hc->xfer_buff = (uint8_t *) urb->buf;
  34941. + }
  34942. + hc->xfer_buff +=
  34943. + frame_desc->offset + qtd->isoc_split_offset;
  34944. + hc->xfer_len =
  34945. + frame_desc->length - qtd->isoc_split_offset;
  34946. +
  34947. + /* For non-dword aligned buffers */
  34948. + if (((unsigned long)hc->xfer_buff & 0x3)
  34949. + && hcd->core_if->dma_enable) {
  34950. + ptr =
  34951. + (uint8_t *) urb->buf + frame_desc->offset +
  34952. + qtd->isoc_split_offset;
  34953. + } else
  34954. + ptr = NULL;
  34955. +
  34956. + if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) {
  34957. + if (hc->xfer_len <= 188) {
  34958. + hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL;
  34959. + } else {
  34960. + hc->xact_pos =
  34961. + DWC_HCSPLIT_XACTPOS_BEGIN;
  34962. + }
  34963. + }
  34964. + }
  34965. + break;
  34966. + }
  34967. + /* non DWORD-aligned buffer case */
  34968. + if (ptr) {
  34969. + uint32_t buf_size;
  34970. + if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
  34971. + buf_size = hcd->core_if->core_params->max_transfer_size;
  34972. + } else {
  34973. + buf_size = 4096;
  34974. + }
  34975. + if (!qh->dw_align_buf) {
  34976. + qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(buf_size,
  34977. + &qh->dw_align_buf_dma);
  34978. + if (!qh->dw_align_buf) {
  34979. + DWC_ERROR
  34980. + ("%s: Failed to allocate memory to handle "
  34981. + "non-dword aligned buffer case\n",
  34982. + __func__);
  34983. + return;
  34984. + }
  34985. + }
  34986. + if (!hc->ep_is_in) {
  34987. + dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len);
  34988. + }
  34989. + hc->align_buff = qh->dw_align_buf_dma;
  34990. + } else {
  34991. + hc->align_buff = 0;
  34992. + }
  34993. +
  34994. + if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
  34995. + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
  34996. + /*
  34997. + * This value may be modified when the transfer is started to
  34998. + * reflect the actual transfer length.
  34999. + */
  35000. + hc->multi_count = dwc_hb_mult(qh->maxp);
  35001. + }
  35002. +
  35003. + if (hcd->core_if->dma_desc_enable)
  35004. + hc->desc_list_addr = qh->desc_list_dma;
  35005. +
  35006. + dwc_otg_hc_init(hcd->core_if, hc);
  35007. + hc->qh = qh;
  35008. +}
  35009. +
  35010. +/**
  35011. + * This function selects transactions from the HCD transfer schedule and
  35012. + * assigns them to available host channels. It is called from HCD interrupt
  35013. + * handler functions.
  35014. + *
  35015. + * @param hcd The HCD state structure.
  35016. + *
  35017. + * @return The types of new transactions that were assigned to host channels.
  35018. + */
  35019. +dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
  35020. +{
  35021. + dwc_list_link_t *qh_ptr;
  35022. + dwc_otg_qh_t *qh;
  35023. + int num_channels;
  35024. + dwc_irqflags_t flags;
  35025. + dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
  35026. + dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE;
  35027. +
  35028. +#ifdef DEBUG_SOF
  35029. + DWC_DEBUGPL(DBG_HCD, " Select Transactions\n");
  35030. +#endif
  35031. +
  35032. +#ifdef DEBUG_HOST_CHANNELS
  35033. + last_sel_trans_num_per_scheduled = 0;
  35034. + last_sel_trans_num_nonper_scheduled = 0;
  35035. + last_sel_trans_num_avail_hc_at_start = hcd->available_host_channels;
  35036. +#endif /* DEBUG_HOST_CHANNELS */
  35037. +
  35038. + /* Process entries in the periodic ready list. */
  35039. + qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready);
  35040. +
  35041. + while (qh_ptr != &hcd->periodic_sched_ready &&
  35042. + !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
  35043. + if (microframe_schedule) {
  35044. + // Make sure we leave one channel for non periodic transactions.
  35045. + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
  35046. + if (hcd->available_host_channels <= 1) {
  35047. + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
  35048. + break;
  35049. + }
  35050. + hcd->available_host_channels--;
  35051. + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
  35052. +#ifdef DEBUG_HOST_CHANNELS
  35053. + last_sel_trans_num_per_scheduled++;
  35054. +#endif /* DEBUG_HOST_CHANNELS */
  35055. + }
  35056. + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
  35057. + assign_and_init_hc(hcd, qh);
  35058. +
  35059. + /*
  35060. + * Move the QH from the periodic ready schedule to the
  35061. + * periodic assigned schedule.
  35062. + */
  35063. + qh_ptr = DWC_LIST_NEXT(qh_ptr);
  35064. + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
  35065. + DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
  35066. + &qh->qh_list_entry);
  35067. + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
  35068. +
  35069. + ret_val = DWC_OTG_TRANSACTION_PERIODIC;
  35070. + }
  35071. +
  35072. + /*
  35073. + * Process entries in the inactive portion of the non-periodic
  35074. + * schedule. Some free host channels may not be used if they are
  35075. + * reserved for periodic transfers.
  35076. + */
  35077. + qh_ptr = hcd->non_periodic_sched_inactive.next;
  35078. + num_channels = hcd->core_if->core_params->host_channels;
  35079. + while (qh_ptr != &hcd->non_periodic_sched_inactive &&
  35080. + (microframe_schedule || hcd->non_periodic_channels <
  35081. + num_channels - hcd->periodic_channels) &&
  35082. + !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
  35083. +
  35084. + if (microframe_schedule) {
  35085. + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
  35086. + if (hcd->available_host_channels < 1) {
  35087. + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
  35088. + break;
  35089. + }
  35090. + hcd->available_host_channels--;
  35091. + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
  35092. +#ifdef DEBUG_HOST_CHANNELS
  35093. + last_sel_trans_num_nonper_scheduled++;
  35094. +#endif /* DEBUG_HOST_CHANNELS */
  35095. + }
  35096. + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
  35097. +
  35098. + assign_and_init_hc(hcd, qh);
  35099. +
  35100. + /*
  35101. + * Move the QH from the non-periodic inactive schedule to the
  35102. + * non-periodic active schedule.
  35103. + */
  35104. + qh_ptr = DWC_LIST_NEXT(qh_ptr);
  35105. + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
  35106. + DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active,
  35107. + &qh->qh_list_entry);
  35108. + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
  35109. +
  35110. + if (ret_val == DWC_OTG_TRANSACTION_NONE) {
  35111. + ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC;
  35112. + } else {
  35113. + ret_val = DWC_OTG_TRANSACTION_ALL;
  35114. + }
  35115. +
  35116. + if (!microframe_schedule)
  35117. + hcd->non_periodic_channels++;
  35118. + }
  35119. +
  35120. +#ifdef DEBUG_HOST_CHANNELS
  35121. + last_sel_trans_num_avail_hc_at_end = hcd->available_host_channels;
  35122. +#endif /* DEBUG_HOST_CHANNELS */
  35123. +
  35124. + DWC_SPINLOCK_FREE(channel_lock);
  35125. + return ret_val;
  35126. +}
  35127. +
  35128. +/**
  35129. + * Attempts to queue a single transaction request for a host channel
  35130. + * associated with either a periodic or non-periodic transfer. This function
  35131. + * assumes that there is space available in the appropriate request queue. For
  35132. + * an OUT transfer or SETUP transaction in Slave mode, it checks whether space
  35133. + * is available in the appropriate Tx FIFO.
  35134. + *
  35135. + * @param hcd The HCD state structure.
  35136. + * @param hc Host channel descriptor associated with either a periodic or
  35137. + * non-periodic transfer.
  35138. + * @param fifo_dwords_avail Number of DWORDs available in the periodic Tx
  35139. + * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic
  35140. + * transfers.
  35141. + *
  35142. + * @return 1 if a request is queued and more requests may be needed to
  35143. + * complete the transfer, 0 if no more requests are required for this
  35144. + * transfer, -1 if there is insufficient space in the Tx FIFO.
  35145. + */
  35146. +static int queue_transaction(dwc_otg_hcd_t * hcd,
  35147. + dwc_hc_t * hc, uint16_t fifo_dwords_avail)
  35148. +{
  35149. + int retval;
  35150. +
  35151. + if (hcd->core_if->dma_enable) {
  35152. + if (hcd->core_if->dma_desc_enable) {
  35153. + if (!hc->xfer_started
  35154. + || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) {
  35155. + dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh);
  35156. + hc->qh->ping_state = 0;
  35157. + }
  35158. + } else if (!hc->xfer_started) {
  35159. + dwc_otg_hc_start_transfer(hcd->core_if, hc);
  35160. + hc->qh->ping_state = 0;
  35161. + }
  35162. + retval = 0;
  35163. + } else if (hc->halt_pending) {
  35164. + /* Don't queue a request if the channel has been halted. */
  35165. + retval = 0;
  35166. + } else if (hc->halt_on_queue) {
  35167. + dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status);
  35168. + retval = 0;
  35169. + } else if (hc->do_ping) {
  35170. + if (!hc->xfer_started) {
  35171. + dwc_otg_hc_start_transfer(hcd->core_if, hc);
  35172. + }
  35173. + retval = 0;
  35174. + } else if (!hc->ep_is_in || hc->data_pid_start == DWC_OTG_HC_PID_SETUP) {
  35175. + if ((fifo_dwords_avail * 4) >= hc->max_packet) {
  35176. + if (!hc->xfer_started) {
  35177. + dwc_otg_hc_start_transfer(hcd->core_if, hc);
  35178. + retval = 1;
  35179. + } else {
  35180. + retval =
  35181. + dwc_otg_hc_continue_transfer(hcd->core_if,
  35182. + hc);
  35183. + }
  35184. + } else {
  35185. + retval = -1;
  35186. + }
  35187. + } else {
  35188. + if (!hc->xfer_started) {
  35189. + dwc_otg_hc_start_transfer(hcd->core_if, hc);
  35190. + retval = 1;
  35191. + } else {
  35192. + retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc);
  35193. + }
  35194. + }
  35195. +
  35196. + return retval;
  35197. +}
  35198. +
  35199. +/**
  35200. + * Processes periodic channels for the next frame and queues transactions for
  35201. + * these channels to the DWC_otg controller. After queueing transactions, the
  35202. + * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions
  35203. + * to queue as Periodic Tx FIFO or request queue space becomes available.
  35204. + * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled.
  35205. + */
  35206. +static void process_periodic_channels(dwc_otg_hcd_t * hcd)
  35207. +{
  35208. + hptxsts_data_t tx_status;
  35209. + dwc_list_link_t *qh_ptr;
  35210. + dwc_otg_qh_t *qh;
  35211. + int status;
  35212. + int no_queue_space = 0;
  35213. + int no_fifo_space = 0;
  35214. +
  35215. + dwc_otg_host_global_regs_t *host_regs;
  35216. + host_regs = hcd->core_if->host_if->host_global_regs;
  35217. +
  35218. + DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n");
  35219. +#ifdef DEBUG
  35220. + tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
  35221. + DWC_DEBUGPL(DBG_HCDV,
  35222. + " P Tx Req Queue Space Avail (before queue): %d\n",
  35223. + tx_status.b.ptxqspcavail);
  35224. + DWC_DEBUGPL(DBG_HCDV, " P Tx FIFO Space Avail (before queue): %d\n",
  35225. + tx_status.b.ptxfspcavail);
  35226. +#endif
  35227. +
  35228. + qh_ptr = hcd->periodic_sched_assigned.next;
  35229. + while (qh_ptr != &hcd->periodic_sched_assigned) {
  35230. + tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
  35231. + if (tx_status.b.ptxqspcavail == 0) {
  35232. + no_queue_space = 1;
  35233. + break;
  35234. + }
  35235. +
  35236. + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
  35237. +
  35238. + /*
  35239. + * Set a flag if we're queuing high-bandwidth in slave mode.
  35240. + * The flag prevents any halts to get into the request queue in
  35241. + * the middle of multiple high-bandwidth packets getting queued.
  35242. + */
  35243. + if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) {
  35244. + hcd->core_if->queuing_high_bandwidth = 1;
  35245. + }
  35246. + status =
  35247. + queue_transaction(hcd, qh->channel,
  35248. + tx_status.b.ptxfspcavail);
  35249. + if (status < 0) {
  35250. + no_fifo_space = 1;
  35251. + break;
  35252. + }
  35253. +
  35254. + /*
  35255. + * In Slave mode, stay on the current transfer until there is
  35256. + * nothing more to do or the high-bandwidth request count is
  35257. + * reached. In DMA mode, only need to queue one request. The
  35258. + * controller automatically handles multiple packets for
  35259. + * high-bandwidth transfers.
  35260. + */
  35261. + if (hcd->core_if->dma_enable || status == 0 ||
  35262. + qh->channel->requests == qh->channel->multi_count) {
  35263. + qh_ptr = qh_ptr->next;
  35264. + /*
  35265. + * Move the QH from the periodic assigned schedule to
  35266. + * the periodic queued schedule.
  35267. + */
  35268. + DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_queued,
  35269. + &qh->qh_list_entry);
  35270. +
  35271. + /* done queuing high bandwidth */
  35272. + hcd->core_if->queuing_high_bandwidth = 0;
  35273. + }
  35274. + }
  35275. +
  35276. + if (!hcd->core_if->dma_enable) {
  35277. + dwc_otg_core_global_regs_t *global_regs;
  35278. + gintmsk_data_t intr_mask = {.d32 = 0 };
  35279. +
  35280. + global_regs = hcd->core_if->core_global_regs;
  35281. + intr_mask.b.ptxfempty = 1;
  35282. +#ifdef DEBUG
  35283. + tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts);
  35284. + DWC_DEBUGPL(DBG_HCDV,
  35285. + " P Tx Req Queue Space Avail (after queue): %d\n",
  35286. + tx_status.b.ptxqspcavail);
  35287. + DWC_DEBUGPL(DBG_HCDV,
  35288. + " P Tx FIFO Space Avail (after queue): %d\n",
  35289. + tx_status.b.ptxfspcavail);
  35290. +#endif
  35291. + if (!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned) ||
  35292. + no_queue_space || no_fifo_space) {
  35293. + /*
  35294. + * May need to queue more transactions as the request
  35295. + * queue or Tx FIFO empties. Enable the periodic Tx
  35296. + * FIFO empty interrupt. (Always use the half-empty
  35297. + * level to ensure that new requests are loaded as
  35298. + * soon as possible.)
  35299. + */
  35300. + DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
  35301. + intr_mask.d32);
  35302. + } else {
  35303. + /*
  35304. + * Disable the Tx FIFO empty interrupt since there are
  35305. + * no more transactions that need to be queued right
  35306. + * now. This function is called from interrupt
  35307. + * handlers to queue more transactions as transfer
  35308. + * states change.
  35309. + */
  35310. + DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
  35311. + 0);
  35312. + }
  35313. + }
  35314. +}
  35315. +
  35316. +/**
  35317. + * Processes active non-periodic channels and queues transactions for these
  35318. + * channels to the DWC_otg controller. After queueing transactions, the NP Tx
  35319. + * FIFO Empty interrupt is enabled if there are more transactions to queue as
  35320. + * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx
  35321. + * FIFO Empty interrupt is disabled.
  35322. + */
  35323. +static void process_non_periodic_channels(dwc_otg_hcd_t * hcd)
  35324. +{
  35325. + gnptxsts_data_t tx_status;
  35326. + dwc_list_link_t *orig_qh_ptr;
  35327. + dwc_otg_qh_t *qh;
  35328. + int status;
  35329. + int no_queue_space = 0;
  35330. + int no_fifo_space = 0;
  35331. + int more_to_do = 0;
  35332. +
  35333. + dwc_otg_core_global_regs_t *global_regs =
  35334. + hcd->core_if->core_global_regs;
  35335. +
  35336. + DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n");
  35337. +#ifdef DEBUG
  35338. + tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
  35339. + DWC_DEBUGPL(DBG_HCDV,
  35340. + " NP Tx Req Queue Space Avail (before queue): %d\n",
  35341. + tx_status.b.nptxqspcavail);
  35342. + DWC_DEBUGPL(DBG_HCDV, " NP Tx FIFO Space Avail (before queue): %d\n",
  35343. + tx_status.b.nptxfspcavail);
  35344. +#endif
  35345. + /*
  35346. + * Keep track of the starting point. Skip over the start-of-list
  35347. + * entry.
  35348. + */
  35349. + if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
  35350. + hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
  35351. + }
  35352. + orig_qh_ptr = hcd->non_periodic_qh_ptr;
  35353. +
  35354. + /*
  35355. + * Process once through the active list or until no more space is
  35356. + * available in the request queue or the Tx FIFO.
  35357. + */
  35358. + do {
  35359. + tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
  35360. + if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) {
  35361. + no_queue_space = 1;
  35362. + break;
  35363. + }
  35364. +
  35365. + qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
  35366. + qh_list_entry);
  35367. + status =
  35368. + queue_transaction(hcd, qh->channel,
  35369. + tx_status.b.nptxfspcavail);
  35370. +
  35371. + if (status > 0) {
  35372. + more_to_do = 1;
  35373. + } else if (status < 0) {
  35374. + no_fifo_space = 1;
  35375. + break;
  35376. + }
  35377. +
  35378. + /* Advance to next QH, skipping start-of-list entry. */
  35379. + hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
  35380. + if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
  35381. + hcd->non_periodic_qh_ptr =
  35382. + hcd->non_periodic_qh_ptr->next;
  35383. + }
  35384. +
  35385. + } while (hcd->non_periodic_qh_ptr != orig_qh_ptr);
  35386. +
  35387. + if (!hcd->core_if->dma_enable) {
  35388. + gintmsk_data_t intr_mask = {.d32 = 0 };
  35389. + intr_mask.b.nptxfempty = 1;
  35390. +
  35391. +#ifdef DEBUG
  35392. + tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
  35393. + DWC_DEBUGPL(DBG_HCDV,
  35394. + " NP Tx Req Queue Space Avail (after queue): %d\n",
  35395. + tx_status.b.nptxqspcavail);
  35396. + DWC_DEBUGPL(DBG_HCDV,
  35397. + " NP Tx FIFO Space Avail (after queue): %d\n",
  35398. + tx_status.b.nptxfspcavail);
  35399. +#endif
  35400. + if (more_to_do || no_queue_space || no_fifo_space) {
  35401. + /*
  35402. + * May need to queue more transactions as the request
  35403. + * queue or Tx FIFO empties. Enable the non-periodic
  35404. + * Tx FIFO empty interrupt. (Always use the half-empty
  35405. + * level to ensure that new requests are loaded as
  35406. + * soon as possible.)
  35407. + */
  35408. + DWC_MODIFY_REG32(&global_regs->gintmsk, 0,
  35409. + intr_mask.d32);
  35410. + } else {
  35411. + /*
  35412. + * Disable the Tx FIFO empty interrupt since there are
  35413. + * no more transactions that need to be queued right
  35414. + * now. This function is called from interrupt
  35415. + * handlers to queue more transactions as transfer
  35416. + * states change.
  35417. + */
  35418. + DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32,
  35419. + 0);
  35420. + }
  35421. + }
  35422. +}
  35423. +
  35424. +/**
  35425. + * This function processes the currently active host channels and queues
  35426. + * transactions for these channels to the DWC_otg controller. It is called
  35427. + * from HCD interrupt handler functions.
  35428. + *
  35429. + * @param hcd The HCD state structure.
  35430. + * @param tr_type The type(s) of transactions to queue (non-periodic,
  35431. + * periodic, or both).
  35432. + */
  35433. +void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
  35434. + dwc_otg_transaction_type_e tr_type)
  35435. +{
  35436. +#ifdef DEBUG_SOF
  35437. + DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n");
  35438. +#endif
  35439. + /* Process host channels associated with periodic transfers. */
  35440. + if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC ||
  35441. + tr_type == DWC_OTG_TRANSACTION_ALL) &&
  35442. + !DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) {
  35443. +
  35444. + process_periodic_channels(hcd);
  35445. + }
  35446. +
  35447. + /* Process host channels associated with non-periodic transfers. */
  35448. + if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC ||
  35449. + tr_type == DWC_OTG_TRANSACTION_ALL) {
  35450. + if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) {
  35451. + process_non_periodic_channels(hcd);
  35452. + } else {
  35453. + /*
  35454. + * Ensure NP Tx FIFO empty interrupt is disabled when
  35455. + * there are no non-periodic transfers to process.
  35456. + */
  35457. + gintmsk_data_t gintmsk = {.d32 = 0 };
  35458. + gintmsk.b.nptxfempty = 1;
  35459. + DWC_MODIFY_REG32(&hcd->core_if->
  35460. + core_global_regs->gintmsk, gintmsk.d32,
  35461. + 0);
  35462. + }
  35463. + }
  35464. +}
  35465. +
  35466. +#ifdef DWC_HS_ELECT_TST
  35467. +/*
  35468. + * Quick and dirty hack to implement the HS Electrical Test
  35469. + * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature.
  35470. + *
  35471. + * This code was copied from our userspace app "hset". It sends a
  35472. + * Get Device Descriptor control sequence in two parts, first the
  35473. + * Setup packet by itself, followed some time later by the In and
  35474. + * Ack packets. Rather than trying to figure out how to add this
  35475. + * functionality to the normal driver code, we just hijack the
  35476. + * hardware, using these two function to drive the hardware
  35477. + * directly.
  35478. + */
  35479. +
  35480. +static dwc_otg_core_global_regs_t *global_regs;
  35481. +static dwc_otg_host_global_regs_t *hc_global_regs;
  35482. +static dwc_otg_hc_regs_t *hc_regs;
  35483. +static uint32_t *data_fifo;
  35484. +
  35485. +static void do_setup(void)
  35486. +{
  35487. + gintsts_data_t gintsts;
  35488. + hctsiz_data_t hctsiz;
  35489. + hcchar_data_t hcchar;
  35490. + haint_data_t haint;
  35491. + hcint_data_t hcint;
  35492. +
  35493. + /* Enable HAINTs */
  35494. + DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
  35495. +
  35496. + /* Enable HCINTs */
  35497. + DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
  35498. +
  35499. + /* Read GINTSTS */
  35500. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35501. +
  35502. + /* Read HAINT */
  35503. + haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
  35504. +
  35505. + /* Read HCINT */
  35506. + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
  35507. +
  35508. + /* Read HCCHAR */
  35509. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  35510. +
  35511. + /* Clear HCINT */
  35512. + DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
  35513. +
  35514. + /* Clear HAINT */
  35515. + DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
  35516. +
  35517. + /* Clear GINTSTS */
  35518. + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
  35519. +
  35520. + /* Read GINTSTS */
  35521. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35522. +
  35523. + /*
  35524. + * Send Setup packet (Get Device Descriptor)
  35525. + */
  35526. +
  35527. + /* Make sure channel is disabled */
  35528. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  35529. + if (hcchar.b.chen) {
  35530. + hcchar.b.chdis = 1;
  35531. +// hcchar.b.chen = 1;
  35532. + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
  35533. + //sleep(1);
  35534. + dwc_mdelay(1000);
  35535. +
  35536. + /* Read GINTSTS */
  35537. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35538. +
  35539. + /* Read HAINT */
  35540. + haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
  35541. +
  35542. + /* Read HCINT */
  35543. + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
  35544. +
  35545. + /* Read HCCHAR */
  35546. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  35547. +
  35548. + /* Clear HCINT */
  35549. + DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
  35550. +
  35551. + /* Clear HAINT */
  35552. + DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
  35553. +
  35554. + /* Clear GINTSTS */
  35555. + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
  35556. +
  35557. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  35558. + }
  35559. +
  35560. + /* Set HCTSIZ */
  35561. + hctsiz.d32 = 0;
  35562. + hctsiz.b.xfersize = 8;
  35563. + hctsiz.b.pktcnt = 1;
  35564. + hctsiz.b.pid = DWC_OTG_HC_PID_SETUP;
  35565. + DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
  35566. +
  35567. + /* Set HCCHAR */
  35568. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  35569. + hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
  35570. + hcchar.b.epdir = 0;
  35571. + hcchar.b.epnum = 0;
  35572. + hcchar.b.mps = 8;
  35573. + hcchar.b.chen = 1;
  35574. + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
  35575. +
  35576. + /* Fill FIFO with Setup data for Get Device Descriptor */
  35577. + data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
  35578. + DWC_WRITE_REG32(data_fifo++, 0x01000680);
  35579. + DWC_WRITE_REG32(data_fifo++, 0x00080000);
  35580. +
  35581. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35582. +
  35583. + /* Wait for host channel interrupt */
  35584. + do {
  35585. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35586. + } while (gintsts.b.hcintr == 0);
  35587. +
  35588. + /* Disable HCINTs */
  35589. + DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
  35590. +
  35591. + /* Disable HAINTs */
  35592. + DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
  35593. +
  35594. + /* Read HAINT */
  35595. + haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
  35596. +
  35597. + /* Read HCINT */
  35598. + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
  35599. +
  35600. + /* Read HCCHAR */
  35601. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  35602. +
  35603. + /* Clear HCINT */
  35604. + DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
  35605. +
  35606. + /* Clear HAINT */
  35607. + DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
  35608. +
  35609. + /* Clear GINTSTS */
  35610. + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
  35611. +
  35612. + /* Read GINTSTS */
  35613. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35614. +}
  35615. +
  35616. +static void do_in_ack(void)
  35617. +{
  35618. + gintsts_data_t gintsts;
  35619. + hctsiz_data_t hctsiz;
  35620. + hcchar_data_t hcchar;
  35621. + haint_data_t haint;
  35622. + hcint_data_t hcint;
  35623. + host_grxsts_data_t grxsts;
  35624. +
  35625. + /* Enable HAINTs */
  35626. + DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001);
  35627. +
  35628. + /* Enable HCINTs */
  35629. + DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3);
  35630. +
  35631. + /* Read GINTSTS */
  35632. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35633. +
  35634. + /* Read HAINT */
  35635. + haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
  35636. +
  35637. + /* Read HCINT */
  35638. + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
  35639. +
  35640. + /* Read HCCHAR */
  35641. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  35642. +
  35643. + /* Clear HCINT */
  35644. + DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
  35645. +
  35646. + /* Clear HAINT */
  35647. + DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
  35648. +
  35649. + /* Clear GINTSTS */
  35650. + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
  35651. +
  35652. + /* Read GINTSTS */
  35653. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35654. +
  35655. + /*
  35656. + * Receive Control In packet
  35657. + */
  35658. +
  35659. + /* Make sure channel is disabled */
  35660. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  35661. + if (hcchar.b.chen) {
  35662. + hcchar.b.chdis = 1;
  35663. + hcchar.b.chen = 1;
  35664. + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
  35665. + //sleep(1);
  35666. + dwc_mdelay(1000);
  35667. +
  35668. + /* Read GINTSTS */
  35669. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35670. +
  35671. + /* Read HAINT */
  35672. + haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
  35673. +
  35674. + /* Read HCINT */
  35675. + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
  35676. +
  35677. + /* Read HCCHAR */
  35678. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  35679. +
  35680. + /* Clear HCINT */
  35681. + DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
  35682. +
  35683. + /* Clear HAINT */
  35684. + DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
  35685. +
  35686. + /* Clear GINTSTS */
  35687. + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
  35688. +
  35689. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  35690. + }
  35691. +
  35692. + /* Set HCTSIZ */
  35693. + hctsiz.d32 = 0;
  35694. + hctsiz.b.xfersize = 8;
  35695. + hctsiz.b.pktcnt = 1;
  35696. + hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
  35697. + DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
  35698. +
  35699. + /* Set HCCHAR */
  35700. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  35701. + hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
  35702. + hcchar.b.epdir = 1;
  35703. + hcchar.b.epnum = 0;
  35704. + hcchar.b.mps = 8;
  35705. + hcchar.b.chen = 1;
  35706. + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
  35707. +
  35708. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35709. +
  35710. + /* Wait for receive status queue interrupt */
  35711. + do {
  35712. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35713. + } while (gintsts.b.rxstsqlvl == 0);
  35714. +
  35715. + /* Read RXSTS */
  35716. + grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
  35717. +
  35718. + /* Clear RXSTSQLVL in GINTSTS */
  35719. + gintsts.d32 = 0;
  35720. + gintsts.b.rxstsqlvl = 1;
  35721. + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
  35722. +
  35723. + switch (grxsts.b.pktsts) {
  35724. + case DWC_GRXSTS_PKTSTS_IN:
  35725. + /* Read the data into the host buffer */
  35726. + if (grxsts.b.bcnt > 0) {
  35727. + int i;
  35728. + int word_count = (grxsts.b.bcnt + 3) / 4;
  35729. +
  35730. + data_fifo = (uint32_t *) ((char *)global_regs + 0x1000);
  35731. +
  35732. + for (i = 0; i < word_count; i++) {
  35733. + (void)DWC_READ_REG32(data_fifo++);
  35734. + }
  35735. + }
  35736. + break;
  35737. +
  35738. + default:
  35739. + break;
  35740. + }
  35741. +
  35742. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35743. +
  35744. + /* Wait for receive status queue interrupt */
  35745. + do {
  35746. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35747. + } while (gintsts.b.rxstsqlvl == 0);
  35748. +
  35749. + /* Read RXSTS */
  35750. + grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp);
  35751. +
  35752. + /* Clear RXSTSQLVL in GINTSTS */
  35753. + gintsts.d32 = 0;
  35754. + gintsts.b.rxstsqlvl = 1;
  35755. + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
  35756. +
  35757. + switch (grxsts.b.pktsts) {
  35758. + case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
  35759. + break;
  35760. +
  35761. + default:
  35762. + break;
  35763. + }
  35764. +
  35765. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35766. +
  35767. + /* Wait for host channel interrupt */
  35768. + do {
  35769. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35770. + } while (gintsts.b.hcintr == 0);
  35771. +
  35772. + /* Read HAINT */
  35773. + haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
  35774. +
  35775. + /* Read HCINT */
  35776. + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
  35777. +
  35778. + /* Read HCCHAR */
  35779. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  35780. +
  35781. + /* Clear HCINT */
  35782. + DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
  35783. +
  35784. + /* Clear HAINT */
  35785. + DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
  35786. +
  35787. + /* Clear GINTSTS */
  35788. + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
  35789. +
  35790. + /* Read GINTSTS */
  35791. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35792. +
  35793. +// usleep(100000);
  35794. +// mdelay(100);
  35795. + dwc_mdelay(1);
  35796. +
  35797. + /*
  35798. + * Send handshake packet
  35799. + */
  35800. +
  35801. + /* Read HAINT */
  35802. + haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
  35803. +
  35804. + /* Read HCINT */
  35805. + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
  35806. +
  35807. + /* Read HCCHAR */
  35808. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  35809. +
  35810. + /* Clear HCINT */
  35811. + DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
  35812. +
  35813. + /* Clear HAINT */
  35814. + DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
  35815. +
  35816. + /* Clear GINTSTS */
  35817. + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
  35818. +
  35819. + /* Read GINTSTS */
  35820. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35821. +
  35822. + /* Make sure channel is disabled */
  35823. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  35824. + if (hcchar.b.chen) {
  35825. + hcchar.b.chdis = 1;
  35826. + hcchar.b.chen = 1;
  35827. + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
  35828. + //sleep(1);
  35829. + dwc_mdelay(1000);
  35830. +
  35831. + /* Read GINTSTS */
  35832. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35833. +
  35834. + /* Read HAINT */
  35835. + haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
  35836. +
  35837. + /* Read HCINT */
  35838. + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
  35839. +
  35840. + /* Read HCCHAR */
  35841. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  35842. +
  35843. + /* Clear HCINT */
  35844. + DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
  35845. +
  35846. + /* Clear HAINT */
  35847. + DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
  35848. +
  35849. + /* Clear GINTSTS */
  35850. + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
  35851. +
  35852. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  35853. + }
  35854. +
  35855. + /* Set HCTSIZ */
  35856. + hctsiz.d32 = 0;
  35857. + hctsiz.b.xfersize = 0;
  35858. + hctsiz.b.pktcnt = 1;
  35859. + hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
  35860. + DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32);
  35861. +
  35862. + /* Set HCCHAR */
  35863. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  35864. + hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
  35865. + hcchar.b.epdir = 0;
  35866. + hcchar.b.epnum = 0;
  35867. + hcchar.b.mps = 8;
  35868. + hcchar.b.chen = 1;
  35869. + DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32);
  35870. +
  35871. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35872. +
  35873. + /* Wait for host channel interrupt */
  35874. + do {
  35875. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35876. + } while (gintsts.b.hcintr == 0);
  35877. +
  35878. + /* Disable HCINTs */
  35879. + DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000);
  35880. +
  35881. + /* Disable HAINTs */
  35882. + DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000);
  35883. +
  35884. + /* Read HAINT */
  35885. + haint.d32 = DWC_READ_REG32(&hc_global_regs->haint);
  35886. +
  35887. + /* Read HCINT */
  35888. + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
  35889. +
  35890. + /* Read HCCHAR */
  35891. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  35892. +
  35893. + /* Clear HCINT */
  35894. + DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32);
  35895. +
  35896. + /* Clear HAINT */
  35897. + DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32);
  35898. +
  35899. + /* Clear GINTSTS */
  35900. + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
  35901. +
  35902. + /* Read GINTSTS */
  35903. + gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts);
  35904. +}
  35905. +#endif
  35906. +
  35907. +/** Handles hub class-specific requests. */
  35908. +int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,
  35909. + uint16_t typeReq,
  35910. + uint16_t wValue,
  35911. + uint16_t wIndex, uint8_t * buf, uint16_t wLength)
  35912. +{
  35913. + int retval = 0;
  35914. +
  35915. + dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
  35916. + usb_hub_descriptor_t *hub_desc;
  35917. + hprt0_data_t hprt0 = {.d32 = 0 };
  35918. +
  35919. + uint32_t port_status;
  35920. +
  35921. + switch (typeReq) {
  35922. + case UCR_CLEAR_HUB_FEATURE:
  35923. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
  35924. + "ClearHubFeature 0x%x\n", wValue);
  35925. + switch (wValue) {
  35926. + case UHF_C_HUB_LOCAL_POWER:
  35927. + case UHF_C_HUB_OVER_CURRENT:
  35928. + /* Nothing required here */
  35929. + break;
  35930. + default:
  35931. + retval = -DWC_E_INVALID;
  35932. + DWC_ERROR("DWC OTG HCD - "
  35933. + "ClearHubFeature request %xh unknown\n",
  35934. + wValue);
  35935. + }
  35936. + break;
  35937. + case UCR_CLEAR_PORT_FEATURE:
  35938. +#ifdef CONFIG_USB_DWC_OTG_LPM
  35939. + if (wValue != UHF_PORT_L1)
  35940. +#endif
  35941. + if (!wIndex || wIndex > 1)
  35942. + goto error;
  35943. +
  35944. + switch (wValue) {
  35945. + case UHF_PORT_ENABLE:
  35946. + DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - "
  35947. + "ClearPortFeature USB_PORT_FEAT_ENABLE\n");
  35948. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  35949. + hprt0.b.prtena = 1;
  35950. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  35951. + break;
  35952. + case UHF_PORT_SUSPEND:
  35953. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
  35954. + "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
  35955. +
  35956. + if (core_if->power_down == 2) {
  35957. + dwc_otg_host_hibernation_restore(core_if, 0, 0);
  35958. + } else {
  35959. + DWC_WRITE_REG32(core_if->pcgcctl, 0);
  35960. + dwc_mdelay(5);
  35961. +
  35962. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  35963. + hprt0.b.prtres = 1;
  35964. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  35965. + hprt0.b.prtsusp = 0;
  35966. + /* Clear Resume bit */
  35967. + dwc_mdelay(100);
  35968. + hprt0.b.prtres = 0;
  35969. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  35970. + }
  35971. + break;
  35972. +#ifdef CONFIG_USB_DWC_OTG_LPM
  35973. + case UHF_PORT_L1:
  35974. + {
  35975. + pcgcctl_data_t pcgcctl = {.d32 = 0 };
  35976. + glpmcfg_data_t lpmcfg = {.d32 = 0 };
  35977. +
  35978. + lpmcfg.d32 =
  35979. + DWC_READ_REG32(&core_if->
  35980. + core_global_regs->glpmcfg);
  35981. + lpmcfg.b.en_utmi_sleep = 0;
  35982. + lpmcfg.b.hird_thres &= (~(1 << 4));
  35983. + lpmcfg.b.prt_sleep_sts = 1;
  35984. + DWC_WRITE_REG32(&core_if->
  35985. + core_global_regs->glpmcfg,
  35986. + lpmcfg.d32);
  35987. +
  35988. + /* Clear Enbl_L1Gating bit. */
  35989. + pcgcctl.b.enbl_sleep_gating = 1;
  35990. + DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32,
  35991. + 0);
  35992. +
  35993. + dwc_mdelay(5);
  35994. +
  35995. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  35996. + hprt0.b.prtres = 1;
  35997. + DWC_WRITE_REG32(core_if->host_if->hprt0,
  35998. + hprt0.d32);
  35999. + /* This bit will be cleared in wakeup interrupt handle */
  36000. + break;
  36001. + }
  36002. +#endif
  36003. + case UHF_PORT_POWER:
  36004. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
  36005. + "ClearPortFeature USB_PORT_FEAT_POWER\n");
  36006. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  36007. + hprt0.b.prtpwr = 0;
  36008. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  36009. + break;
  36010. + case UHF_PORT_INDICATOR:
  36011. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
  36012. + "ClearPortFeature USB_PORT_FEAT_INDICATOR\n");
  36013. + /* Port inidicator not supported */
  36014. + break;
  36015. + case UHF_C_PORT_CONNECTION:
  36016. + /* Clears drivers internal connect status change
  36017. + * flag */
  36018. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
  36019. + "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n");
  36020. + dwc_otg_hcd->flags.b.port_connect_status_change = 0;
  36021. + break;
  36022. + case UHF_C_PORT_RESET:
  36023. + /* Clears the driver's internal Port Reset Change
  36024. + * flag */
  36025. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
  36026. + "ClearPortFeature USB_PORT_FEAT_C_RESET\n");
  36027. + dwc_otg_hcd->flags.b.port_reset_change = 0;
  36028. + break;
  36029. + case UHF_C_PORT_ENABLE:
  36030. + /* Clears the driver's internal Port
  36031. + * Enable/Disable Change flag */
  36032. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
  36033. + "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n");
  36034. + dwc_otg_hcd->flags.b.port_enable_change = 0;
  36035. + break;
  36036. + case UHF_C_PORT_SUSPEND:
  36037. + /* Clears the driver's internal Port Suspend
  36038. + * Change flag, which is set when resume signaling on
  36039. + * the host port is complete */
  36040. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
  36041. + "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n");
  36042. + dwc_otg_hcd->flags.b.port_suspend_change = 0;
  36043. + break;
  36044. +#ifdef CONFIG_USB_DWC_OTG_LPM
  36045. + case UHF_C_PORT_L1:
  36046. + dwc_otg_hcd->flags.b.port_l1_change = 0;
  36047. + break;
  36048. +#endif
  36049. + case UHF_C_PORT_OVER_CURRENT:
  36050. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
  36051. + "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n");
  36052. + dwc_otg_hcd->flags.b.port_over_current_change = 0;
  36053. + break;
  36054. + default:
  36055. + retval = -DWC_E_INVALID;
  36056. + DWC_ERROR("DWC OTG HCD - "
  36057. + "ClearPortFeature request %xh "
  36058. + "unknown or unsupported\n", wValue);
  36059. + }
  36060. + break;
  36061. + case UCR_GET_HUB_DESCRIPTOR:
  36062. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
  36063. + "GetHubDescriptor\n");
  36064. + hub_desc = (usb_hub_descriptor_t *) buf;
  36065. + hub_desc->bDescLength = 9;
  36066. + hub_desc->bDescriptorType = 0x29;
  36067. + hub_desc->bNbrPorts = 1;
  36068. + USETW(hub_desc->wHubCharacteristics, 0x08);
  36069. + hub_desc->bPwrOn2PwrGood = 1;
  36070. + hub_desc->bHubContrCurrent = 0;
  36071. + hub_desc->DeviceRemovable[0] = 0;
  36072. + hub_desc->DeviceRemovable[1] = 0xff;
  36073. + break;
  36074. + case UCR_GET_HUB_STATUS:
  36075. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
  36076. + "GetHubStatus\n");
  36077. + DWC_MEMSET(buf, 0, 4);
  36078. + break;
  36079. + case UCR_GET_PORT_STATUS:
  36080. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
  36081. + "GetPortStatus wIndex = 0x%04x FLAGS=0x%08x\n",
  36082. + wIndex, dwc_otg_hcd->flags.d32);
  36083. + if (!wIndex || wIndex > 1)
  36084. + goto error;
  36085. +
  36086. + port_status = 0;
  36087. +
  36088. + if (dwc_otg_hcd->flags.b.port_connect_status_change)
  36089. + port_status |= (1 << UHF_C_PORT_CONNECTION);
  36090. +
  36091. + if (dwc_otg_hcd->flags.b.port_enable_change)
  36092. + port_status |= (1 << UHF_C_PORT_ENABLE);
  36093. +
  36094. + if (dwc_otg_hcd->flags.b.port_suspend_change)
  36095. + port_status |= (1 << UHF_C_PORT_SUSPEND);
  36096. +
  36097. + if (dwc_otg_hcd->flags.b.port_l1_change)
  36098. + port_status |= (1 << UHF_C_PORT_L1);
  36099. +
  36100. + if (dwc_otg_hcd->flags.b.port_reset_change) {
  36101. + port_status |= (1 << UHF_C_PORT_RESET);
  36102. + }
  36103. +
  36104. + if (dwc_otg_hcd->flags.b.port_over_current_change) {
  36105. + DWC_WARN("Overcurrent change detected\n");
  36106. + port_status |= (1 << UHF_C_PORT_OVER_CURRENT);
  36107. + }
  36108. +
  36109. + if (!dwc_otg_hcd->flags.b.port_connect_status) {
  36110. + /*
  36111. + * The port is disconnected, which means the core is
  36112. + * either in device mode or it soon will be. Just
  36113. + * return 0's for the remainder of the port status
  36114. + * since the port register can't be read if the core
  36115. + * is in device mode.
  36116. + */
  36117. + *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
  36118. + break;
  36119. + }
  36120. +
  36121. + hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0);
  36122. + DWC_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32);
  36123. +
  36124. + if (hprt0.b.prtconnsts)
  36125. + port_status |= (1 << UHF_PORT_CONNECTION);
  36126. +
  36127. + if (hprt0.b.prtena)
  36128. + port_status |= (1 << UHF_PORT_ENABLE);
  36129. +
  36130. + if (hprt0.b.prtsusp)
  36131. + port_status |= (1 << UHF_PORT_SUSPEND);
  36132. +
  36133. + if (hprt0.b.prtovrcurract)
  36134. + port_status |= (1 << UHF_PORT_OVER_CURRENT);
  36135. +
  36136. + if (hprt0.b.prtrst)
  36137. + port_status |= (1 << UHF_PORT_RESET);
  36138. +
  36139. + if (hprt0.b.prtpwr)
  36140. + port_status |= (1 << UHF_PORT_POWER);
  36141. +
  36142. + if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED)
  36143. + port_status |= (1 << UHF_PORT_HIGH_SPEED);
  36144. + else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED)
  36145. + port_status |= (1 << UHF_PORT_LOW_SPEED);
  36146. +
  36147. + if (hprt0.b.prttstctl)
  36148. + port_status |= (1 << UHF_PORT_TEST);
  36149. + if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) {
  36150. + port_status |= (1 << UHF_PORT_L1);
  36151. + }
  36152. + /*
  36153. + For Synopsys HW emulation of Power down wkup_control asserts the
  36154. + hreset_n and prst_n on suspned. This causes the HPRT0 to be zero.
  36155. + We intentionally tell the software that port is in L2Suspend state.
  36156. + Only for STE.
  36157. + */
  36158. + if ((core_if->power_down == 2)
  36159. + && (core_if->hibernation_suspend == 1)) {
  36160. + port_status |= (1 << UHF_PORT_SUSPEND);
  36161. + }
  36162. + /* USB_PORT_FEAT_INDICATOR unsupported always 0 */
  36163. +
  36164. + *((__le32 *) buf) = dwc_cpu_to_le32(&port_status);
  36165. +
  36166. + break;
  36167. + case UCR_SET_HUB_FEATURE:
  36168. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
  36169. + "SetHubFeature\n");
  36170. + /* No HUB features supported */
  36171. + break;
  36172. + case UCR_SET_PORT_FEATURE:
  36173. + if (wValue != UHF_PORT_TEST && (!wIndex || wIndex > 1))
  36174. + goto error;
  36175. +
  36176. + if (!dwc_otg_hcd->flags.b.port_connect_status) {
  36177. + /*
  36178. + * The port is disconnected, which means the core is
  36179. + * either in device mode or it soon will be. Just
  36180. + * return without doing anything since the port
  36181. + * register can't be written if the core is in device
  36182. + * mode.
  36183. + */
  36184. + break;
  36185. + }
  36186. +
  36187. + switch (wValue) {
  36188. + case UHF_PORT_SUSPEND:
  36189. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
  36190. + "SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
  36191. + if (dwc_otg_hcd_otg_port(dwc_otg_hcd) != wIndex) {
  36192. + goto error;
  36193. + }
  36194. + if (core_if->power_down == 2) {
  36195. + int timeout = 300;
  36196. + dwc_irqflags_t flags;
  36197. + pcgcctl_data_t pcgcctl = {.d32 = 0 };
  36198. + gpwrdn_data_t gpwrdn = {.d32 = 0 };
  36199. + gusbcfg_data_t gusbcfg = {.d32 = 0 };
  36200. +#ifdef DWC_DEV_SRPCAP
  36201. + int32_t otg_cap_param = core_if->core_params->otg_cap;
  36202. +#endif
  36203. + DWC_PRINTF("Preparing for complete power-off\n");
  36204. +
  36205. + /* Save registers before hibernation */
  36206. + dwc_otg_save_global_regs(core_if);
  36207. + dwc_otg_save_host_regs(core_if);
  36208. +
  36209. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  36210. + hprt0.b.prtsusp = 1;
  36211. + hprt0.b.prtena = 0;
  36212. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  36213. + /* Spin hprt0.b.prtsusp to became 1 */
  36214. + do {
  36215. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  36216. + if (hprt0.b.prtsusp) {
  36217. + break;
  36218. + }
  36219. + dwc_mdelay(1);
  36220. + } while (--timeout);
  36221. + if (!timeout) {
  36222. + DWC_WARN("Suspend wasn't genereted\n");
  36223. + }
  36224. + dwc_udelay(10);
  36225. +
  36226. + /*
  36227. + * We need to disable interrupts to prevent servicing of any IRQ
  36228. + * during going to hibernation
  36229. + */
  36230. + DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
  36231. + core_if->lx_state = DWC_OTG_L2;
  36232. +#ifdef DWC_DEV_SRPCAP
  36233. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  36234. + hprt0.b.prtpwr = 0;
  36235. + hprt0.b.prtena = 0;
  36236. + DWC_WRITE_REG32(core_if->host_if->hprt0,
  36237. + hprt0.d32);
  36238. +#endif
  36239. + gusbcfg.d32 =
  36240. + DWC_READ_REG32(&core_if->core_global_regs->
  36241. + gusbcfg);
  36242. + if (gusbcfg.b.ulpi_utmi_sel == 1) {
  36243. + /* ULPI interface */
  36244. + /* Suspend the Phy Clock */
  36245. + pcgcctl.d32 = 0;
  36246. + pcgcctl.b.stoppclk = 1;
  36247. + DWC_MODIFY_REG32(core_if->pcgcctl, 0,
  36248. + pcgcctl.d32);
  36249. + dwc_udelay(10);
  36250. + gpwrdn.b.pmuactv = 1;
  36251. + DWC_MODIFY_REG32(&core_if->
  36252. + core_global_regs->
  36253. + gpwrdn, 0, gpwrdn.d32);
  36254. + } else {
  36255. + /* UTMI+ Interface */
  36256. + gpwrdn.b.pmuactv = 1;
  36257. + DWC_MODIFY_REG32(&core_if->
  36258. + core_global_regs->
  36259. + gpwrdn, 0, gpwrdn.d32);
  36260. + dwc_udelay(10);
  36261. + pcgcctl.b.stoppclk = 1;
  36262. + DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32);
  36263. + dwc_udelay(10);
  36264. + }
  36265. +#ifdef DWC_DEV_SRPCAP
  36266. + gpwrdn.d32 = 0;
  36267. + gpwrdn.b.dis_vbus = 1;
  36268. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  36269. + gpwrdn, 0, gpwrdn.d32);
  36270. +#endif
  36271. + gpwrdn.d32 = 0;
  36272. + gpwrdn.b.pmuintsel = 1;
  36273. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  36274. + gpwrdn, 0, gpwrdn.d32);
  36275. + dwc_udelay(10);
  36276. +
  36277. + gpwrdn.d32 = 0;
  36278. +#ifdef DWC_DEV_SRPCAP
  36279. + gpwrdn.b.srp_det_msk = 1;
  36280. +#endif
  36281. + gpwrdn.b.disconn_det_msk = 1;
  36282. + gpwrdn.b.lnstchng_msk = 1;
  36283. + gpwrdn.b.sts_chngint_msk = 1;
  36284. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  36285. + gpwrdn, 0, gpwrdn.d32);
  36286. + dwc_udelay(10);
  36287. +
  36288. + /* Enable Power Down Clamp and all interrupts in GPWRDN */
  36289. + gpwrdn.d32 = 0;
  36290. + gpwrdn.b.pwrdnclmp = 1;
  36291. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  36292. + gpwrdn, 0, gpwrdn.d32);
  36293. + dwc_udelay(10);
  36294. +
  36295. + /* Switch off VDD */
  36296. + gpwrdn.d32 = 0;
  36297. + gpwrdn.b.pwrdnswtch = 1;
  36298. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  36299. + gpwrdn, 0, gpwrdn.d32);
  36300. +
  36301. +#ifdef DWC_DEV_SRPCAP
  36302. + if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE)
  36303. + {
  36304. + core_if->pwron_timer_started = 1;
  36305. + DWC_TIMER_SCHEDULE(core_if->pwron_timer, 6000 /* 6 secs */ );
  36306. + }
  36307. +#endif
  36308. + /* Save gpwrdn register for further usage if stschng interrupt */
  36309. + core_if->gr_backup->gpwrdn_local =
  36310. + DWC_READ_REG32(&core_if->core_global_regs->gpwrdn);
  36311. +
  36312. + /* Set flag to indicate that we are in hibernation */
  36313. + core_if->hibernation_suspend = 1;
  36314. + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock,flags);
  36315. +
  36316. + DWC_PRINTF("Host hibernation completed\n");
  36317. + // Exit from case statement
  36318. + break;
  36319. +
  36320. + }
  36321. + if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex &&
  36322. + dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
  36323. + gotgctl_data_t gotgctl = {.d32 = 0 };
  36324. + gotgctl.b.hstsethnpen = 1;
  36325. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  36326. + gotgctl, 0, gotgctl.d32);
  36327. + core_if->op_state = A_SUSPEND;
  36328. + }
  36329. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  36330. + hprt0.b.prtsusp = 1;
  36331. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  36332. + {
  36333. + dwc_irqflags_t flags;
  36334. + /* Update lx_state */
  36335. + DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
  36336. + core_if->lx_state = DWC_OTG_L2;
  36337. + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
  36338. + }
  36339. + /* Suspend the Phy Clock */
  36340. + {
  36341. + pcgcctl_data_t pcgcctl = {.d32 = 0 };
  36342. + pcgcctl.b.stoppclk = 1;
  36343. + DWC_MODIFY_REG32(core_if->pcgcctl, 0,
  36344. + pcgcctl.d32);
  36345. + dwc_udelay(10);
  36346. + }
  36347. +
  36348. + /* For HNP the bus must be suspended for at least 200ms. */
  36349. + if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) {
  36350. + pcgcctl_data_t pcgcctl = {.d32 = 0 };
  36351. + pcgcctl.b.stoppclk = 1;
  36352. + DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
  36353. + dwc_mdelay(200);
  36354. + }
  36355. +
  36356. + /** @todo - check how sw can wait for 1 sec to check asesvld??? */
  36357. +#if 0 //vahrama !!!!!!!!!!!!!!!!!!
  36358. + if (core_if->adp_enable) {
  36359. + gotgctl_data_t gotgctl = {.d32 = 0 };
  36360. + gpwrdn_data_t gpwrdn;
  36361. +
  36362. + while (gotgctl.b.asesvld == 1) {
  36363. + gotgctl.d32 =
  36364. + DWC_READ_REG32(&core_if->
  36365. + core_global_regs->
  36366. + gotgctl);
  36367. + dwc_mdelay(100);
  36368. + }
  36369. +
  36370. + /* Enable Power Down Logic */
  36371. + gpwrdn.d32 = 0;
  36372. + gpwrdn.b.pmuactv = 1;
  36373. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  36374. + gpwrdn, 0, gpwrdn.d32);
  36375. +
  36376. + /* Unmask SRP detected interrupt from Power Down Logic */
  36377. + gpwrdn.d32 = 0;
  36378. + gpwrdn.b.srp_det_msk = 1;
  36379. + DWC_MODIFY_REG32(&core_if->core_global_regs->
  36380. + gpwrdn, 0, gpwrdn.d32);
  36381. +
  36382. + dwc_otg_adp_probe_start(core_if);
  36383. + }
  36384. +#endif
  36385. + break;
  36386. + case UHF_PORT_POWER:
  36387. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
  36388. + "SetPortFeature - USB_PORT_FEAT_POWER\n");
  36389. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  36390. + hprt0.b.prtpwr = 1;
  36391. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  36392. + break;
  36393. + case UHF_PORT_RESET:
  36394. + if ((core_if->power_down == 2)
  36395. + && (core_if->hibernation_suspend == 1)) {
  36396. + /* If we are going to exit from Hibernated
  36397. + * state via USB RESET.
  36398. + */
  36399. + dwc_otg_host_hibernation_restore(core_if, 0, 1);
  36400. + } else {
  36401. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  36402. +
  36403. + DWC_DEBUGPL(DBG_HCD,
  36404. + "DWC OTG HCD HUB CONTROL - "
  36405. + "SetPortFeature - USB_PORT_FEAT_RESET\n");
  36406. + {
  36407. + pcgcctl_data_t pcgcctl = {.d32 = 0 };
  36408. + pcgcctl.b.enbl_sleep_gating = 1;
  36409. + pcgcctl.b.stoppclk = 1;
  36410. + DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0);
  36411. + DWC_WRITE_REG32(core_if->pcgcctl, 0);
  36412. + }
  36413. +#ifdef CONFIG_USB_DWC_OTG_LPM
  36414. + {
  36415. + glpmcfg_data_t lpmcfg;
  36416. + lpmcfg.d32 =
  36417. + DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
  36418. + if (lpmcfg.b.prt_sleep_sts) {
  36419. + lpmcfg.b.en_utmi_sleep = 0;
  36420. + lpmcfg.b.hird_thres &= (~(1 << 4));
  36421. + DWC_WRITE_REG32
  36422. + (&core_if->core_global_regs->glpmcfg,
  36423. + lpmcfg.d32);
  36424. + dwc_mdelay(1);
  36425. + }
  36426. + }
  36427. +#endif
  36428. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  36429. + /* Clear suspend bit if resetting from suspended state. */
  36430. + hprt0.b.prtsusp = 0;
  36431. + /* When B-Host the Port reset bit is set in
  36432. + * the Start HCD Callback function, so that
  36433. + * the reset is started within 1ms of the HNP
  36434. + * success interrupt. */
  36435. + if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) {
  36436. + hprt0.b.prtpwr = 1;
  36437. + hprt0.b.prtrst = 1;
  36438. + DWC_PRINTF("Indeed it is in host mode hprt0 = %08x\n",hprt0.d32);
  36439. + DWC_WRITE_REG32(core_if->host_if->hprt0,
  36440. + hprt0.d32);
  36441. + }
  36442. + /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
  36443. + dwc_mdelay(60);
  36444. + hprt0.b.prtrst = 0;
  36445. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  36446. + core_if->lx_state = DWC_OTG_L0; /* Now back to the on state */
  36447. + }
  36448. + break;
  36449. +#ifdef DWC_HS_ELECT_TST
  36450. + case UHF_PORT_TEST:
  36451. + {
  36452. + uint32_t t;
  36453. + gintmsk_data_t gintmsk;
  36454. +
  36455. + t = (wIndex >> 8); /* MSB wIndex USB */
  36456. + DWC_DEBUGPL(DBG_HCD,
  36457. + "DWC OTG HCD HUB CONTROL - "
  36458. + "SetPortFeature - USB_PORT_FEAT_TEST %d\n",
  36459. + t);
  36460. + DWC_WARN("USB_PORT_FEAT_TEST %d\n", t);
  36461. + if (t < 6) {
  36462. + hprt0.d32 = dwc_otg_read_hprt0(core_if);
  36463. + hprt0.b.prttstctl = t;
  36464. + DWC_WRITE_REG32(core_if->host_if->hprt0,
  36465. + hprt0.d32);
  36466. + } else {
  36467. + /* Setup global vars with reg addresses (quick and
  36468. + * dirty hack, should be cleaned up)
  36469. + */
  36470. + global_regs = core_if->core_global_regs;
  36471. + hc_global_regs =
  36472. + core_if->host_if->host_global_regs;
  36473. + hc_regs =
  36474. + (dwc_otg_hc_regs_t *) ((char *)
  36475. + global_regs +
  36476. + 0x500);
  36477. + data_fifo =
  36478. + (uint32_t *) ((char *)global_regs +
  36479. + 0x1000);
  36480. +
  36481. + if (t == 6) { /* HS_HOST_PORT_SUSPEND_RESUME */
  36482. + /* Save current interrupt mask */
  36483. + gintmsk.d32 =
  36484. + DWC_READ_REG32
  36485. + (&global_regs->gintmsk);
  36486. +
  36487. + /* Disable all interrupts while we muck with
  36488. + * the hardware directly
  36489. + */
  36490. + DWC_WRITE_REG32(&global_regs->gintmsk, 0);
  36491. +
  36492. + /* 15 second delay per the test spec */
  36493. + dwc_mdelay(15000);
  36494. +
  36495. + /* Drive suspend on the root port */
  36496. + hprt0.d32 =
  36497. + dwc_otg_read_hprt0(core_if);
  36498. + hprt0.b.prtsusp = 1;
  36499. + hprt0.b.prtres = 0;
  36500. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  36501. +
  36502. + /* 15 second delay per the test spec */
  36503. + dwc_mdelay(15000);
  36504. +
  36505. + /* Drive resume on the root port */
  36506. + hprt0.d32 =
  36507. + dwc_otg_read_hprt0(core_if);
  36508. + hprt0.b.prtsusp = 0;
  36509. + hprt0.b.prtres = 1;
  36510. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  36511. + dwc_mdelay(100);
  36512. +
  36513. + /* Clear the resume bit */
  36514. + hprt0.b.prtres = 0;
  36515. + DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32);
  36516. +
  36517. + /* Restore interrupts */
  36518. + DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
  36519. + } else if (t == 7) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
  36520. + /* Save current interrupt mask */
  36521. + gintmsk.d32 =
  36522. + DWC_READ_REG32
  36523. + (&global_regs->gintmsk);
  36524. +
  36525. + /* Disable all interrupts while we muck with
  36526. + * the hardware directly
  36527. + */
  36528. + DWC_WRITE_REG32(&global_regs->gintmsk, 0);
  36529. +
  36530. + /* 15 second delay per the test spec */
  36531. + dwc_mdelay(15000);
  36532. +
  36533. + /* Send the Setup packet */
  36534. + do_setup();
  36535. +
  36536. + /* 15 second delay so nothing else happens for awhile */
  36537. + dwc_mdelay(15000);
  36538. +
  36539. + /* Restore interrupts */
  36540. + DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
  36541. + } else if (t == 8) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
  36542. + /* Save current interrupt mask */
  36543. + gintmsk.d32 =
  36544. + DWC_READ_REG32
  36545. + (&global_regs->gintmsk);
  36546. +
  36547. + /* Disable all interrupts while we muck with
  36548. + * the hardware directly
  36549. + */
  36550. + DWC_WRITE_REG32(&global_regs->gintmsk, 0);
  36551. +
  36552. + /* Send the Setup packet */
  36553. + do_setup();
  36554. +
  36555. + /* 15 second delay so nothing else happens for awhile */
  36556. + dwc_mdelay(15000);
  36557. +
  36558. + /* Send the In and Ack packets */
  36559. + do_in_ack();
  36560. +
  36561. + /* 15 second delay so nothing else happens for awhile */
  36562. + dwc_mdelay(15000);
  36563. +
  36564. + /* Restore interrupts */
  36565. + DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32);
  36566. + }
  36567. + }
  36568. + break;
  36569. + }
  36570. +#endif /* DWC_HS_ELECT_TST */
  36571. +
  36572. + case UHF_PORT_INDICATOR:
  36573. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - "
  36574. + "SetPortFeature - USB_PORT_FEAT_INDICATOR\n");
  36575. + /* Not supported */
  36576. + break;
  36577. + default:
  36578. + retval = -DWC_E_INVALID;
  36579. + DWC_ERROR("DWC OTG HCD - "
  36580. + "SetPortFeature request %xh "
  36581. + "unknown or unsupported\n", wValue);
  36582. + break;
  36583. + }
  36584. + break;
  36585. +#ifdef CONFIG_USB_DWC_OTG_LPM
  36586. + case UCR_SET_AND_TEST_PORT_FEATURE:
  36587. + if (wValue != UHF_PORT_L1) {
  36588. + goto error;
  36589. + }
  36590. + {
  36591. + int portnum, hird, devaddr, remwake;
  36592. + glpmcfg_data_t lpmcfg;
  36593. + uint32_t time_usecs;
  36594. + gintsts_data_t gintsts;
  36595. + gintmsk_data_t gintmsk;
  36596. +
  36597. + if (!dwc_otg_get_param_lpm_enable(core_if)) {
  36598. + goto error;
  36599. + }
  36600. + if (wValue != UHF_PORT_L1 || wLength != 1) {
  36601. + goto error;
  36602. + }
  36603. + /* Check if the port currently is in SLEEP state */
  36604. + lpmcfg.d32 =
  36605. + DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
  36606. + if (lpmcfg.b.prt_sleep_sts) {
  36607. + DWC_INFO("Port is already in sleep mode\n");
  36608. + buf[0] = 0; /* Return success */
  36609. + break;
  36610. + }
  36611. +
  36612. + portnum = wIndex & 0xf;
  36613. + hird = (wIndex >> 4) & 0xf;
  36614. + devaddr = (wIndex >> 8) & 0x7f;
  36615. + remwake = (wIndex >> 15);
  36616. +
  36617. + if (portnum != 1) {
  36618. + retval = -DWC_E_INVALID;
  36619. + DWC_WARN
  36620. + ("Wrong port number(%d) in SetandTestPortFeature request\n",
  36621. + portnum);
  36622. + break;
  36623. + }
  36624. +
  36625. + DWC_PRINTF
  36626. + ("SetandTestPortFeature request: portnum = %d, hird = %d, devaddr = %d, rewake = %d\n",
  36627. + portnum, hird, devaddr, remwake);
  36628. + /* Disable LPM interrupt */
  36629. + gintmsk.d32 = 0;
  36630. + gintmsk.b.lpmtranrcvd = 1;
  36631. + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
  36632. + gintmsk.d32, 0);
  36633. +
  36634. + if (dwc_otg_hcd_send_lpm
  36635. + (dwc_otg_hcd, devaddr, hird, remwake)) {
  36636. + retval = -DWC_E_INVALID;
  36637. + break;
  36638. + }
  36639. +
  36640. + time_usecs = 10 * (lpmcfg.b.retry_count + 1);
  36641. + /* We will consider timeout if time_usecs microseconds pass,
  36642. + * and we don't receive LPM transaction status.
  36643. + * After receiving non-error responce(ACK/NYET/STALL) from device,
  36644. + * core will set lpmtranrcvd bit.
  36645. + */
  36646. + do {
  36647. + gintsts.d32 =
  36648. + DWC_READ_REG32(&core_if->core_global_regs->gintsts);
  36649. + if (gintsts.b.lpmtranrcvd) {
  36650. + break;
  36651. + }
  36652. + dwc_udelay(1);
  36653. + } while (--time_usecs);
  36654. + /* lpm_int bit will be cleared in LPM interrupt handler */
  36655. +
  36656. + /* Now fill status
  36657. + * 0x00 - Success
  36658. + * 0x10 - NYET
  36659. + * 0x11 - Timeout
  36660. + */
  36661. + if (!gintsts.b.lpmtranrcvd) {
  36662. + buf[0] = 0x3; /* Completion code is Timeout */
  36663. + dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd);
  36664. + } else {
  36665. + lpmcfg.d32 =
  36666. + DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
  36667. + if (lpmcfg.b.lpm_resp == 0x3) {
  36668. + /* ACK responce from the device */
  36669. + buf[0] = 0x00; /* Success */
  36670. + } else if (lpmcfg.b.lpm_resp == 0x2) {
  36671. + /* NYET responce from the device */
  36672. + buf[0] = 0x2;
  36673. + } else {
  36674. + /* Otherwise responce with Timeout */
  36675. + buf[0] = 0x3;
  36676. + }
  36677. + }
  36678. + DWC_PRINTF("Device responce to LPM trans is %x\n",
  36679. + lpmcfg.b.lpm_resp);
  36680. + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0,
  36681. + gintmsk.d32);
  36682. +
  36683. + break;
  36684. + }
  36685. +#endif /* CONFIG_USB_DWC_OTG_LPM */
  36686. + default:
  36687. +error:
  36688. + retval = -DWC_E_INVALID;
  36689. + DWC_WARN("DWC OTG HCD - "
  36690. + "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n",
  36691. + typeReq, wIndex, wValue);
  36692. + break;
  36693. + }
  36694. +
  36695. + return retval;
  36696. +}
  36697. +
  36698. +#ifdef CONFIG_USB_DWC_OTG_LPM
  36699. +/** Returns index of host channel to perform LPM transaction. */
  36700. +int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, uint8_t devaddr)
  36701. +{
  36702. + dwc_otg_core_if_t *core_if = hcd->core_if;
  36703. + dwc_hc_t *hc;
  36704. + hcchar_data_t hcchar;
  36705. + gintmsk_data_t gintmsk = {.d32 = 0 };
  36706. +
  36707. + if (DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
  36708. + DWC_PRINTF("No free channel to select for LPM transaction\n");
  36709. + return -1;
  36710. + }
  36711. +
  36712. + hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
  36713. +
  36714. + /* Mask host channel interrupts. */
  36715. + gintmsk.b.hcintr = 1;
  36716. + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
  36717. +
  36718. + /* Fill fields that core needs for LPM transaction */
  36719. + hcchar.b.devaddr = devaddr;
  36720. + hcchar.b.epnum = 0;
  36721. + hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL;
  36722. + hcchar.b.mps = 64;
  36723. + hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW);
  36724. + hcchar.b.epdir = 0; /* OUT */
  36725. + DWC_WRITE_REG32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar,
  36726. + hcchar.d32);
  36727. +
  36728. + /* Remove the host channel from the free list. */
  36729. + DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry);
  36730. +
  36731. + DWC_PRINTF("hcnum = %d devaddr = %d\n", hc->hc_num, devaddr);
  36732. +
  36733. + return hc->hc_num;
  36734. +}
  36735. +
  36736. +/** Release hc after performing LPM transaction */
  36737. +void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd)
  36738. +{
  36739. + dwc_hc_t *hc;
  36740. + glpmcfg_data_t lpmcfg;
  36741. + uint8_t hc_num;
  36742. +
  36743. + lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
  36744. + hc_num = lpmcfg.b.lpm_chan_index;
  36745. +
  36746. + hc = hcd->hc_ptr_array[hc_num];
  36747. +
  36748. + DWC_PRINTF("Freeing channel %d after LPM\n", hc_num);
  36749. + /* Return host channel to free list */
  36750. + DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
  36751. +}
  36752. +
  36753. +int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, uint8_t hird,
  36754. + uint8_t bRemoteWake)
  36755. +{
  36756. + glpmcfg_data_t lpmcfg;
  36757. + pcgcctl_data_t pcgcctl = {.d32 = 0 };
  36758. + int channel;
  36759. +
  36760. + channel = dwc_otg_hcd_get_hc_for_lpm_tran(hcd, devaddr);
  36761. + if (channel < 0) {
  36762. + return channel;
  36763. + }
  36764. +
  36765. + pcgcctl.b.enbl_sleep_gating = 1;
  36766. + DWC_MODIFY_REG32(hcd->core_if->pcgcctl, 0, pcgcctl.d32);
  36767. +
  36768. + /* Read LPM config register */
  36769. + lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg);
  36770. +
  36771. + /* Program LPM transaction fields */
  36772. + lpmcfg.b.rem_wkup_en = bRemoteWake;
  36773. + lpmcfg.b.hird = hird;
  36774. + lpmcfg.b.hird_thres = 0x1c;
  36775. + lpmcfg.b.lpm_chan_index = channel;
  36776. + lpmcfg.b.en_utmi_sleep = 1;
  36777. + /* Program LPM config register */
  36778. + DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
  36779. +
  36780. + /* Send LPM transaction */
  36781. + lpmcfg.b.send_lpm = 1;
  36782. + DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32);
  36783. +
  36784. + return 0;
  36785. +}
  36786. +
  36787. +#endif /* CONFIG_USB_DWC_OTG_LPM */
  36788. +
  36789. +int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port)
  36790. +{
  36791. + int retval;
  36792. +
  36793. + if (port != 1) {
  36794. + return -DWC_E_INVALID;
  36795. + }
  36796. +
  36797. + retval = (hcd->flags.b.port_connect_status_change ||
  36798. + hcd->flags.b.port_reset_change ||
  36799. + hcd->flags.b.port_enable_change ||
  36800. + hcd->flags.b.port_suspend_change ||
  36801. + hcd->flags.b.port_over_current_change);
  36802. +#ifdef DEBUG
  36803. + if (retval) {
  36804. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:"
  36805. + " Root port status changed\n");
  36806. + DWC_DEBUGPL(DBG_HCDV, " port_connect_status_change: %d\n",
  36807. + hcd->flags.b.port_connect_status_change);
  36808. + DWC_DEBUGPL(DBG_HCDV, " port_reset_change: %d\n",
  36809. + hcd->flags.b.port_reset_change);
  36810. + DWC_DEBUGPL(DBG_HCDV, " port_enable_change: %d\n",
  36811. + hcd->flags.b.port_enable_change);
  36812. + DWC_DEBUGPL(DBG_HCDV, " port_suspend_change: %d\n",
  36813. + hcd->flags.b.port_suspend_change);
  36814. + DWC_DEBUGPL(DBG_HCDV, " port_over_current_change: %d\n",
  36815. + hcd->flags.b.port_over_current_change);
  36816. + }
  36817. +#endif
  36818. + return retval;
  36819. +}
  36820. +
  36821. +int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * dwc_otg_hcd)
  36822. +{
  36823. + hfnum_data_t hfnum;
  36824. + hfnum.d32 =
  36825. + DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->
  36826. + hfnum);
  36827. +
  36828. +#ifdef DEBUG_SOF
  36829. + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n",
  36830. + hfnum.b.frnum);
  36831. +#endif
  36832. + return hfnum.b.frnum;
  36833. +}
  36834. +
  36835. +int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,
  36836. + struct dwc_otg_hcd_function_ops *fops)
  36837. +{
  36838. + int retval = 0;
  36839. +
  36840. + hcd->fops = fops;
  36841. + if (!dwc_otg_is_device_mode(hcd->core_if) &&
  36842. + (!hcd->core_if->adp_enable || hcd->core_if->adp.adp_started)) {
  36843. + dwc_otg_hcd_reinit(hcd);
  36844. + } else {
  36845. + retval = -DWC_E_NO_DEVICE;
  36846. + }
  36847. +
  36848. + return retval;
  36849. +}
  36850. +
  36851. +void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd)
  36852. +{
  36853. + return hcd->priv;
  36854. +}
  36855. +
  36856. +void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data)
  36857. +{
  36858. + hcd->priv = priv_data;
  36859. +}
  36860. +
  36861. +uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd)
  36862. +{
  36863. + return hcd->otg_port;
  36864. +}
  36865. +
  36866. +uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd)
  36867. +{
  36868. + uint32_t is_b_host;
  36869. + if (hcd->core_if->op_state == B_HOST) {
  36870. + is_b_host = 1;
  36871. + } else {
  36872. + is_b_host = 0;
  36873. + }
  36874. +
  36875. + return is_b_host;
  36876. +}
  36877. +
  36878. +dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,
  36879. + int iso_desc_count, int atomic_alloc)
  36880. +{
  36881. + dwc_otg_hcd_urb_t *dwc_otg_urb;
  36882. + uint32_t size;
  36883. +
  36884. + size =
  36885. + sizeof(*dwc_otg_urb) +
  36886. + iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc);
  36887. + if (atomic_alloc)
  36888. + dwc_otg_urb = DWC_ALLOC_ATOMIC(size);
  36889. + else
  36890. + dwc_otg_urb = DWC_ALLOC(size);
  36891. +
  36892. + if (NULL != dwc_otg_urb)
  36893. + dwc_otg_urb->packet_count = iso_desc_count;
  36894. + else {
  36895. + dwc_otg_urb->packet_count = 0;
  36896. + if (size != 0) {
  36897. + DWC_ERROR("**** DWC OTG HCD URB alloc - "
  36898. + "%salloc of %db failed\n",
  36899. + atomic_alloc?"atomic ":"", size);
  36900. + }
  36901. + }
  36902. +
  36903. + return dwc_otg_urb;
  36904. +}
  36905. +
  36906. +void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * dwc_otg_urb,
  36907. + uint8_t dev_addr, uint8_t ep_num,
  36908. + uint8_t ep_type, uint8_t ep_dir, uint16_t mps)
  36909. +{
  36910. + dwc_otg_hcd_fill_pipe(&dwc_otg_urb->pipe_info, dev_addr, ep_num,
  36911. + ep_type, ep_dir, mps);
  36912. +#if 0
  36913. + DWC_PRINTF
  36914. + ("addr = %d, ep_num = %d, ep_dir = 0x%x, ep_type = 0x%x, mps = %d\n",
  36915. + dev_addr, ep_num, ep_dir, ep_type, mps);
  36916. +#endif
  36917. +}
  36918. +
  36919. +void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
  36920. + void *urb_handle, void *buf, dwc_dma_t dma,
  36921. + uint32_t buflen, void *setup_packet,
  36922. + dwc_dma_t setup_dma, uint32_t flags,
  36923. + uint16_t interval)
  36924. +{
  36925. + dwc_otg_urb->priv = urb_handle;
  36926. + dwc_otg_urb->buf = buf;
  36927. + dwc_otg_urb->dma = dma;
  36928. + dwc_otg_urb->length = buflen;
  36929. + dwc_otg_urb->setup_packet = setup_packet;
  36930. + dwc_otg_urb->setup_dma = setup_dma;
  36931. + dwc_otg_urb->flags = flags;
  36932. + dwc_otg_urb->interval = interval;
  36933. + dwc_otg_urb->status = -DWC_E_IN_PROGRESS;
  36934. +}
  36935. +
  36936. +uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb)
  36937. +{
  36938. + return dwc_otg_urb->status;
  36939. +}
  36940. +
  36941. +uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * dwc_otg_urb)
  36942. +{
  36943. + return dwc_otg_urb->actual_length;
  36944. +}
  36945. +
  36946. +uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * dwc_otg_urb)
  36947. +{
  36948. + return dwc_otg_urb->error_count;
  36949. +}
  36950. +
  36951. +void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
  36952. + int desc_num, uint32_t offset,
  36953. + uint32_t length)
  36954. +{
  36955. + dwc_otg_urb->iso_descs[desc_num].offset = offset;
  36956. + dwc_otg_urb->iso_descs[desc_num].length = length;
  36957. +}
  36958. +
  36959. +uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * dwc_otg_urb,
  36960. + int desc_num)
  36961. +{
  36962. + return dwc_otg_urb->iso_descs[desc_num].status;
  36963. +}
  36964. +
  36965. +uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
  36966. + dwc_otg_urb, int desc_num)
  36967. +{
  36968. + return dwc_otg_urb->iso_descs[desc_num].actual_length;
  36969. +}
  36970. +
  36971. +int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, void *ep_handle)
  36972. +{
  36973. + int allocated = 0;
  36974. + dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
  36975. +
  36976. + if (qh) {
  36977. + if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
  36978. + allocated = 1;
  36979. + }
  36980. + }
  36981. + return allocated;
  36982. +}
  36983. +
  36984. +int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle)
  36985. +{
  36986. + dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
  36987. + int freed = 0;
  36988. + DWC_ASSERT(qh, "qh is not allocated\n");
  36989. +
  36990. + if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
  36991. + freed = 1;
  36992. + }
  36993. +
  36994. + return freed;
  36995. +}
  36996. +
  36997. +uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, void *ep_handle)
  36998. +{
  36999. + dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle;
  37000. + DWC_ASSERT(qh, "qh is not allocated\n");
  37001. + return qh->usecs;
  37002. +}
  37003. +
  37004. +void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd)
  37005. +{
  37006. +#ifdef DEBUG
  37007. + int num_channels;
  37008. + int i;
  37009. + gnptxsts_data_t np_tx_status;
  37010. + hptxsts_data_t p_tx_status;
  37011. +
  37012. + num_channels = hcd->core_if->core_params->host_channels;
  37013. + DWC_PRINTF("\n");
  37014. + DWC_PRINTF
  37015. + ("************************************************************\n");
  37016. + DWC_PRINTF("HCD State:\n");
  37017. + DWC_PRINTF(" Num channels: %d\n", num_channels);
  37018. + for (i = 0; i < num_channels; i++) {
  37019. + dwc_hc_t *hc = hcd->hc_ptr_array[i];
  37020. + DWC_PRINTF(" Channel %d:\n", i);
  37021. + DWC_PRINTF(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
  37022. + hc->dev_addr, hc->ep_num, hc->ep_is_in);
  37023. + DWC_PRINTF(" speed: %d\n", hc->speed);
  37024. + DWC_PRINTF(" ep_type: %d\n", hc->ep_type);
  37025. + DWC_PRINTF(" max_packet: %d\n", hc->max_packet);
  37026. + DWC_PRINTF(" data_pid_start: %d\n", hc->data_pid_start);
  37027. + DWC_PRINTF(" multi_count: %d\n", hc->multi_count);
  37028. + DWC_PRINTF(" xfer_started: %d\n", hc->xfer_started);
  37029. + DWC_PRINTF(" xfer_buff: %p\n", hc->xfer_buff);
  37030. + DWC_PRINTF(" xfer_len: %d\n", hc->xfer_len);
  37031. + DWC_PRINTF(" xfer_count: %d\n", hc->xfer_count);
  37032. + DWC_PRINTF(" halt_on_queue: %d\n", hc->halt_on_queue);
  37033. + DWC_PRINTF(" halt_pending: %d\n", hc->halt_pending);
  37034. + DWC_PRINTF(" halt_status: %d\n", hc->halt_status);
  37035. + DWC_PRINTF(" do_split: %d\n", hc->do_split);
  37036. + DWC_PRINTF(" complete_split: %d\n", hc->complete_split);
  37037. + DWC_PRINTF(" hub_addr: %d\n", hc->hub_addr);
  37038. + DWC_PRINTF(" port_addr: %d\n", hc->port_addr);
  37039. + DWC_PRINTF(" xact_pos: %d\n", hc->xact_pos);
  37040. + DWC_PRINTF(" requests: %d\n", hc->requests);
  37041. + DWC_PRINTF(" qh: %p\n", hc->qh);
  37042. + if (hc->xfer_started) {
  37043. + hfnum_data_t hfnum;
  37044. + hcchar_data_t hcchar;
  37045. + hctsiz_data_t hctsiz;
  37046. + hcint_data_t hcint;
  37047. + hcintmsk_data_t hcintmsk;
  37048. + hfnum.d32 =
  37049. + DWC_READ_REG32(&hcd->core_if->
  37050. + host_if->host_global_regs->hfnum);
  37051. + hcchar.d32 =
  37052. + DWC_READ_REG32(&hcd->core_if->host_if->
  37053. + hc_regs[i]->hcchar);
  37054. + hctsiz.d32 =
  37055. + DWC_READ_REG32(&hcd->core_if->host_if->
  37056. + hc_regs[i]->hctsiz);
  37057. + hcint.d32 =
  37058. + DWC_READ_REG32(&hcd->core_if->host_if->
  37059. + hc_regs[i]->hcint);
  37060. + hcintmsk.d32 =
  37061. + DWC_READ_REG32(&hcd->core_if->host_if->
  37062. + hc_regs[i]->hcintmsk);
  37063. + DWC_PRINTF(" hfnum: 0x%08x\n", hfnum.d32);
  37064. + DWC_PRINTF(" hcchar: 0x%08x\n", hcchar.d32);
  37065. + DWC_PRINTF(" hctsiz: 0x%08x\n", hctsiz.d32);
  37066. + DWC_PRINTF(" hcint: 0x%08x\n", hcint.d32);
  37067. + DWC_PRINTF(" hcintmsk: 0x%08x\n", hcintmsk.d32);
  37068. + }
  37069. + if (hc->xfer_started && hc->qh) {
  37070. + dwc_otg_qtd_t *qtd;
  37071. + dwc_otg_hcd_urb_t *urb;
  37072. +
  37073. + DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list, qtd_list_entry) {
  37074. + if (!qtd->in_process)
  37075. + break;
  37076. +
  37077. + urb = qtd->urb;
  37078. + DWC_PRINTF(" URB Info:\n");
  37079. + DWC_PRINTF(" qtd: %p, urb: %p\n", qtd, urb);
  37080. + if (urb) {
  37081. + DWC_PRINTF(" Dev: %d, EP: %d %s\n",
  37082. + dwc_otg_hcd_get_dev_addr(&urb->
  37083. + pipe_info),
  37084. + dwc_otg_hcd_get_ep_num(&urb->
  37085. + pipe_info),
  37086. + dwc_otg_hcd_is_pipe_in(&urb->
  37087. + pipe_info) ?
  37088. + "IN" : "OUT");
  37089. + DWC_PRINTF(" Max packet size: %d\n",
  37090. + dwc_otg_hcd_get_mps(&urb->
  37091. + pipe_info));
  37092. + DWC_PRINTF(" transfer_buffer: %p\n",
  37093. + urb->buf);
  37094. + DWC_PRINTF(" transfer_dma: %p\n",
  37095. + (void *)urb->dma);
  37096. + DWC_PRINTF(" transfer_buffer_length: %d\n",
  37097. + urb->length);
  37098. + DWC_PRINTF(" actual_length: %d\n",
  37099. + urb->actual_length);
  37100. + }
  37101. + }
  37102. + }
  37103. + }
  37104. + DWC_PRINTF(" non_periodic_channels: %d\n", hcd->non_periodic_channels);
  37105. + DWC_PRINTF(" periodic_channels: %d\n", hcd->periodic_channels);
  37106. + DWC_PRINTF(" periodic_usecs: %d\n", hcd->periodic_usecs);
  37107. + np_tx_status.d32 =
  37108. + DWC_READ_REG32(&hcd->core_if->core_global_regs->gnptxsts);
  37109. + DWC_PRINTF(" NP Tx Req Queue Space Avail: %d\n",
  37110. + np_tx_status.b.nptxqspcavail);
  37111. + DWC_PRINTF(" NP Tx FIFO Space Avail: %d\n",
  37112. + np_tx_status.b.nptxfspcavail);
  37113. + p_tx_status.d32 =
  37114. + DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hptxsts);
  37115. + DWC_PRINTF(" P Tx Req Queue Space Avail: %d\n",
  37116. + p_tx_status.b.ptxqspcavail);
  37117. + DWC_PRINTF(" P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail);
  37118. + dwc_otg_hcd_dump_frrem(hcd);
  37119. + dwc_otg_dump_global_registers(hcd->core_if);
  37120. + dwc_otg_dump_host_registers(hcd->core_if);
  37121. + DWC_PRINTF
  37122. + ("************************************************************\n");
  37123. + DWC_PRINTF("\n");
  37124. +#endif
  37125. +}
  37126. +
  37127. +#ifdef DEBUG
  37128. +void dwc_print_setup_data(uint8_t * setup)
  37129. +{
  37130. + int i;
  37131. + if (CHK_DEBUG_LEVEL(DBG_HCD)) {
  37132. + DWC_PRINTF("Setup Data = MSB ");
  37133. + for (i = 7; i >= 0; i--)
  37134. + DWC_PRINTF("%02x ", setup[i]);
  37135. + DWC_PRINTF("\n");
  37136. + DWC_PRINTF(" bmRequestType Tranfer = %s\n",
  37137. + (setup[0] & 0x80) ? "Device-to-Host" :
  37138. + "Host-to-Device");
  37139. + DWC_PRINTF(" bmRequestType Type = ");
  37140. + switch ((setup[0] & 0x60) >> 5) {
  37141. + case 0:
  37142. + DWC_PRINTF("Standard\n");
  37143. + break;
  37144. + case 1:
  37145. + DWC_PRINTF("Class\n");
  37146. + break;
  37147. + case 2:
  37148. + DWC_PRINTF("Vendor\n");
  37149. + break;
  37150. + case 3:
  37151. + DWC_PRINTF("Reserved\n");
  37152. + break;
  37153. + }
  37154. + DWC_PRINTF(" bmRequestType Recipient = ");
  37155. + switch (setup[0] & 0x1f) {
  37156. + case 0:
  37157. + DWC_PRINTF("Device\n");
  37158. + break;
  37159. + case 1:
  37160. + DWC_PRINTF("Interface\n");
  37161. + break;
  37162. + case 2:
  37163. + DWC_PRINTF("Endpoint\n");
  37164. + break;
  37165. + case 3:
  37166. + DWC_PRINTF("Other\n");
  37167. + break;
  37168. + default:
  37169. + DWC_PRINTF("Reserved\n");
  37170. + break;
  37171. + }
  37172. + DWC_PRINTF(" bRequest = 0x%0x\n", setup[1]);
  37173. + DWC_PRINTF(" wValue = 0x%0x\n", *((uint16_t *) & setup[2]));
  37174. + DWC_PRINTF(" wIndex = 0x%0x\n", *((uint16_t *) & setup[4]));
  37175. + DWC_PRINTF(" wLength = 0x%0x\n\n", *((uint16_t *) & setup[6]));
  37176. + }
  37177. +}
  37178. +#endif
  37179. +
  37180. +void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd)
  37181. +{
  37182. +#if 0
  37183. + DWC_PRINTF("Frame remaining at SOF:\n");
  37184. + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
  37185. + hcd->frrem_samples, hcd->frrem_accum,
  37186. + (hcd->frrem_samples > 0) ?
  37187. + hcd->frrem_accum / hcd->frrem_samples : 0);
  37188. +
  37189. + DWC_PRINTF("\n");
  37190. + DWC_PRINTF("Frame remaining at start_transfer (uframe 7):\n");
  37191. + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
  37192. + hcd->core_if->hfnum_7_samples,
  37193. + hcd->core_if->hfnum_7_frrem_accum,
  37194. + (hcd->core_if->hfnum_7_samples >
  37195. + 0) ? hcd->core_if->hfnum_7_frrem_accum /
  37196. + hcd->core_if->hfnum_7_samples : 0);
  37197. + DWC_PRINTF("Frame remaining at start_transfer (uframe 0):\n");
  37198. + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
  37199. + hcd->core_if->hfnum_0_samples,
  37200. + hcd->core_if->hfnum_0_frrem_accum,
  37201. + (hcd->core_if->hfnum_0_samples >
  37202. + 0) ? hcd->core_if->hfnum_0_frrem_accum /
  37203. + hcd->core_if->hfnum_0_samples : 0);
  37204. + DWC_PRINTF("Frame remaining at start_transfer (uframe 1-6):\n");
  37205. + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
  37206. + hcd->core_if->hfnum_other_samples,
  37207. + hcd->core_if->hfnum_other_frrem_accum,
  37208. + (hcd->core_if->hfnum_other_samples >
  37209. + 0) ? hcd->core_if->hfnum_other_frrem_accum /
  37210. + hcd->core_if->hfnum_other_samples : 0);
  37211. +
  37212. + DWC_PRINTF("\n");
  37213. + DWC_PRINTF("Frame remaining at sample point A (uframe 7):\n");
  37214. + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
  37215. + hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a,
  37216. + (hcd->hfnum_7_samples_a > 0) ?
  37217. + hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0);
  37218. + DWC_PRINTF("Frame remaining at sample point A (uframe 0):\n");
  37219. + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
  37220. + hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a,
  37221. + (hcd->hfnum_0_samples_a > 0) ?
  37222. + hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0);
  37223. + DWC_PRINTF("Frame remaining at sample point A (uframe 1-6):\n");
  37224. + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
  37225. + hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a,
  37226. + (hcd->hfnum_other_samples_a > 0) ?
  37227. + hcd->hfnum_other_frrem_accum_a /
  37228. + hcd->hfnum_other_samples_a : 0);
  37229. +
  37230. + DWC_PRINTF("\n");
  37231. + DWC_PRINTF("Frame remaining at sample point B (uframe 7):\n");
  37232. + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
  37233. + hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b,
  37234. + (hcd->hfnum_7_samples_b > 0) ?
  37235. + hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0);
  37236. + DWC_PRINTF("Frame remaining at sample point B (uframe 0):\n");
  37237. + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
  37238. + hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b,
  37239. + (hcd->hfnum_0_samples_b > 0) ?
  37240. + hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0);
  37241. + DWC_PRINTF("Frame remaining at sample point B (uframe 1-6):\n");
  37242. + DWC_PRINTF(" samples %u, accum %llu, avg %llu\n",
  37243. + hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b,
  37244. + (hcd->hfnum_other_samples_b > 0) ?
  37245. + hcd->hfnum_other_frrem_accum_b /
  37246. + hcd->hfnum_other_samples_b : 0);
  37247. +#endif
  37248. +}
  37249. +
  37250. +#endif /* DWC_DEVICE_ONLY */
  37251. --- /dev/null
  37252. +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
  37253. @@ -0,0 +1,824 @@
  37254. +/* ==========================================================================
  37255. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $
  37256. + * $Revision: #58 $
  37257. + * $Date: 2011/09/15 $
  37258. + * $Change: 1846647 $
  37259. + *
  37260. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  37261. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  37262. + * otherwise expressly agreed to in writing between Synopsys and you.
  37263. + *
  37264. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  37265. + * any End User Software License Agreement or Agreement for Licensed Product
  37266. + * with Synopsys or any supplement thereto. You are permitted to use and
  37267. + * redistribute this Software in source and binary forms, with or without
  37268. + * modification, provided that redistributions of source code must retain this
  37269. + * notice. You may not view, use, disclose, copy or distribute this file or
  37270. + * any information contained herein except pursuant to this license grant from
  37271. + * Synopsys. If you do not agree with this notice, including the disclaimer
  37272. + * below, then you are not authorized to use the Software.
  37273. + *
  37274. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  37275. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  37276. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  37277. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  37278. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  37279. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  37280. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  37281. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  37282. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  37283. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  37284. + * DAMAGE.
  37285. + * ========================================================================== */
  37286. +#ifndef DWC_DEVICE_ONLY
  37287. +#ifndef __DWC_HCD_H__
  37288. +#define __DWC_HCD_H__
  37289. +
  37290. +#include "dwc_otg_os_dep.h"
  37291. +#include "usb.h"
  37292. +#include "dwc_otg_hcd_if.h"
  37293. +#include "dwc_otg_core_if.h"
  37294. +#include "dwc_list.h"
  37295. +#include "dwc_otg_cil.h"
  37296. +
  37297. +/**
  37298. + * @file
  37299. + *
  37300. + * This file contains the structures, constants, and interfaces for
  37301. + * the Host Contoller Driver (HCD).
  37302. + *
  37303. + * The Host Controller Driver (HCD) is responsible for translating requests
  37304. + * from the USB Driver into the appropriate actions on the DWC_otg controller.
  37305. + * It isolates the USBD from the specifics of the controller by providing an
  37306. + * API to the USBD.
  37307. + */
  37308. +
  37309. +struct dwc_otg_hcd_pipe_info {
  37310. + uint8_t dev_addr;
  37311. + uint8_t ep_num;
  37312. + uint8_t pipe_type;
  37313. + uint8_t pipe_dir;
  37314. + uint16_t mps;
  37315. +};
  37316. +
  37317. +struct dwc_otg_hcd_iso_packet_desc {
  37318. + uint32_t offset;
  37319. + uint32_t length;
  37320. + uint32_t actual_length;
  37321. + uint32_t status;
  37322. +};
  37323. +
  37324. +struct dwc_otg_qtd;
  37325. +
  37326. +struct dwc_otg_hcd_urb {
  37327. + void *priv;
  37328. + struct dwc_otg_qtd *qtd;
  37329. + void *buf;
  37330. + dwc_dma_t dma;
  37331. + void *setup_packet;
  37332. + dwc_dma_t setup_dma;
  37333. + uint32_t length;
  37334. + uint32_t actual_length;
  37335. + uint32_t status;
  37336. + uint32_t error_count;
  37337. + uint32_t packet_count;
  37338. + uint32_t flags;
  37339. + uint16_t interval;
  37340. + struct dwc_otg_hcd_pipe_info pipe_info;
  37341. + struct dwc_otg_hcd_iso_packet_desc iso_descs[0];
  37342. +};
  37343. +
  37344. +static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe)
  37345. +{
  37346. + return pipe->ep_num;
  37347. +}
  37348. +
  37349. +static inline uint8_t dwc_otg_hcd_get_pipe_type(struct dwc_otg_hcd_pipe_info
  37350. + *pipe)
  37351. +{
  37352. + return pipe->pipe_type;
  37353. +}
  37354. +
  37355. +static inline uint16_t dwc_otg_hcd_get_mps(struct dwc_otg_hcd_pipe_info *pipe)
  37356. +{
  37357. + return pipe->mps;
  37358. +}
  37359. +
  37360. +static inline uint8_t dwc_otg_hcd_get_dev_addr(struct dwc_otg_hcd_pipe_info
  37361. + *pipe)
  37362. +{
  37363. + return pipe->dev_addr;
  37364. +}
  37365. +
  37366. +static inline uint8_t dwc_otg_hcd_is_pipe_isoc(struct dwc_otg_hcd_pipe_info
  37367. + *pipe)
  37368. +{
  37369. + return (pipe->pipe_type == UE_ISOCHRONOUS);
  37370. +}
  37371. +
  37372. +static inline uint8_t dwc_otg_hcd_is_pipe_int(struct dwc_otg_hcd_pipe_info
  37373. + *pipe)
  37374. +{
  37375. + return (pipe->pipe_type == UE_INTERRUPT);
  37376. +}
  37377. +
  37378. +static inline uint8_t dwc_otg_hcd_is_pipe_bulk(struct dwc_otg_hcd_pipe_info
  37379. + *pipe)
  37380. +{
  37381. + return (pipe->pipe_type == UE_BULK);
  37382. +}
  37383. +
  37384. +static inline uint8_t dwc_otg_hcd_is_pipe_control(struct dwc_otg_hcd_pipe_info
  37385. + *pipe)
  37386. +{
  37387. + return (pipe->pipe_type == UE_CONTROL);
  37388. +}
  37389. +
  37390. +static inline uint8_t dwc_otg_hcd_is_pipe_in(struct dwc_otg_hcd_pipe_info *pipe)
  37391. +{
  37392. + return (pipe->pipe_dir == UE_DIR_IN);
  37393. +}
  37394. +
  37395. +static inline uint8_t dwc_otg_hcd_is_pipe_out(struct dwc_otg_hcd_pipe_info
  37396. + *pipe)
  37397. +{
  37398. + return (!dwc_otg_hcd_is_pipe_in(pipe));
  37399. +}
  37400. +
  37401. +static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe,
  37402. + uint8_t devaddr, uint8_t ep_num,
  37403. + uint8_t pipe_type, uint8_t pipe_dir,
  37404. + uint16_t mps)
  37405. +{
  37406. + pipe->dev_addr = devaddr;
  37407. + pipe->ep_num = ep_num;
  37408. + pipe->pipe_type = pipe_type;
  37409. + pipe->pipe_dir = pipe_dir;
  37410. + pipe->mps = mps;
  37411. +}
  37412. +
  37413. +/**
  37414. + * Phases for control transfers.
  37415. + */
  37416. +typedef enum dwc_otg_control_phase {
  37417. + DWC_OTG_CONTROL_SETUP,
  37418. + DWC_OTG_CONTROL_DATA,
  37419. + DWC_OTG_CONTROL_STATUS
  37420. +} dwc_otg_control_phase_e;
  37421. +
  37422. +/** Transaction types. */
  37423. +typedef enum dwc_otg_transaction_type {
  37424. + DWC_OTG_TRANSACTION_NONE,
  37425. + DWC_OTG_TRANSACTION_PERIODIC,
  37426. + DWC_OTG_TRANSACTION_NON_PERIODIC,
  37427. + DWC_OTG_TRANSACTION_ALL
  37428. +} dwc_otg_transaction_type_e;
  37429. +
  37430. +struct dwc_otg_qh;
  37431. +
  37432. +/**
  37433. + * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control,
  37434. + * interrupt, or isochronous transfer. A single QTD is created for each URB
  37435. + * (of one of these types) submitted to the HCD. The transfer associated with
  37436. + * a QTD may require one or multiple transactions.
  37437. + *
  37438. + * A QTD is linked to a Queue Head, which is entered in either the
  37439. + * non-periodic or periodic schedule for execution. When a QTD is chosen for
  37440. + * execution, some or all of its transactions may be executed. After
  37441. + * execution, the state of the QTD is updated. The QTD may be retired if all
  37442. + * its transactions are complete or if an error occurred. Otherwise, it
  37443. + * remains in the schedule so more transactions can be executed later.
  37444. + */
  37445. +typedef struct dwc_otg_qtd {
  37446. + /**
  37447. + * Determines the PID of the next data packet for the data phase of
  37448. + * control transfers. Ignored for other transfer types.<br>
  37449. + * One of the following values:
  37450. + * - DWC_OTG_HC_PID_DATA0
  37451. + * - DWC_OTG_HC_PID_DATA1
  37452. + */
  37453. + uint8_t data_toggle;
  37454. +
  37455. + /** Current phase for control transfers (Setup, Data, or Status). */
  37456. + dwc_otg_control_phase_e control_phase;
  37457. +
  37458. + /** Keep track of the current split type
  37459. + * for FS/LS endpoints on a HS Hub */
  37460. + uint8_t complete_split;
  37461. +
  37462. + /** How many bytes transferred during SSPLIT OUT */
  37463. + uint32_t ssplit_out_xfer_count;
  37464. +
  37465. + /**
  37466. + * Holds the number of bus errors that have occurred for a transaction
  37467. + * within this transfer.
  37468. + */
  37469. + uint8_t error_count;
  37470. +
  37471. + /**
  37472. + * Index of the next frame descriptor for an isochronous transfer. A
  37473. + * frame descriptor describes the buffer position and length of the
  37474. + * data to be transferred in the next scheduled (micro)frame of an
  37475. + * isochronous transfer. It also holds status for that transaction.
  37476. + * The frame index starts at 0.
  37477. + */
  37478. + uint16_t isoc_frame_index;
  37479. +
  37480. + /** Position of the ISOC split on full/low speed */
  37481. + uint8_t isoc_split_pos;
  37482. +
  37483. + /** Position of the ISOC split in the buffer for the current frame */
  37484. + uint16_t isoc_split_offset;
  37485. +
  37486. + /** URB for this transfer */
  37487. + struct dwc_otg_hcd_urb *urb;
  37488. +
  37489. + struct dwc_otg_qh *qh;
  37490. +
  37491. + /** This list of QTDs */
  37492. + DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry;
  37493. +
  37494. + /** Indicates if this QTD is currently processed by HW. */
  37495. + uint8_t in_process;
  37496. +
  37497. + /** Number of DMA descriptors for this QTD */
  37498. + uint8_t n_desc;
  37499. +
  37500. + /**
  37501. + * Last activated frame(packet) index.
  37502. + * Used in Descriptor DMA mode only.
  37503. + */
  37504. + uint16_t isoc_frame_index_last;
  37505. +
  37506. +} dwc_otg_qtd_t;
  37507. +
  37508. +DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd);
  37509. +
  37510. +/**
  37511. + * A Queue Head (QH) holds the static characteristics of an endpoint and
  37512. + * maintains a list of transfers (QTDs) for that endpoint. A QH structure may
  37513. + * be entered in either the non-periodic or periodic schedule.
  37514. + */
  37515. +typedef struct dwc_otg_qh {
  37516. + /**
  37517. + * Endpoint type.
  37518. + * One of the following values:
  37519. + * - UE_CONTROL
  37520. + * - UE_BULK
  37521. + * - UE_INTERRUPT
  37522. + * - UE_ISOCHRONOUS
  37523. + */
  37524. + uint8_t ep_type;
  37525. + uint8_t ep_is_in;
  37526. +
  37527. + /** wMaxPacketSize Field of Endpoint Descriptor. */
  37528. + uint16_t maxp;
  37529. +
  37530. + /**
  37531. + * Device speed.
  37532. + * One of the following values:
  37533. + * - DWC_OTG_EP_SPEED_LOW
  37534. + * - DWC_OTG_EP_SPEED_FULL
  37535. + * - DWC_OTG_EP_SPEED_HIGH
  37536. + */
  37537. + uint8_t dev_speed;
  37538. +
  37539. + /**
  37540. + * Determines the PID of the next data packet for non-control
  37541. + * transfers. Ignored for control transfers.<br>
  37542. + * One of the following values:
  37543. + * - DWC_OTG_HC_PID_DATA0
  37544. + * - DWC_OTG_HC_PID_DATA1
  37545. + */
  37546. + uint8_t data_toggle;
  37547. +
  37548. + /** Ping state if 1. */
  37549. + uint8_t ping_state;
  37550. +
  37551. + /**
  37552. + * List of QTDs for this QH.
  37553. + */
  37554. + struct dwc_otg_qtd_list qtd_list;
  37555. +
  37556. + /** Host channel currently processing transfers for this QH. */
  37557. + struct dwc_hc *channel;
  37558. +
  37559. + /** Full/low speed endpoint on high-speed hub requires split. */
  37560. + uint8_t do_split;
  37561. +
  37562. + /** @name Periodic schedule information */
  37563. + /** @{ */
  37564. +
  37565. + /** Bandwidth in microseconds per (micro)frame. */
  37566. + uint16_t usecs;
  37567. +
  37568. + /** Interval between transfers in (micro)frames. */
  37569. + uint16_t interval;
  37570. +
  37571. + /**
  37572. + * (micro)frame to initialize a periodic transfer. The transfer
  37573. + * executes in the following (micro)frame.
  37574. + */
  37575. + uint16_t sched_frame;
  37576. +
  37577. + /** (micro)frame at which last start split was initialized. */
  37578. + uint16_t start_split_frame;
  37579. +
  37580. + /** @} */
  37581. +
  37582. + /**
  37583. + * Used instead of original buffer if
  37584. + * it(physical address) is not dword-aligned.
  37585. + */
  37586. + uint8_t *dw_align_buf;
  37587. + dwc_dma_t dw_align_buf_dma;
  37588. +
  37589. + /** Entry for QH in either the periodic or non-periodic schedule. */
  37590. + dwc_list_link_t qh_list_entry;
  37591. +
  37592. + /** @name Descriptor DMA support */
  37593. + /** @{ */
  37594. +
  37595. + /** Descriptor List. */
  37596. + dwc_otg_host_dma_desc_t *desc_list;
  37597. +
  37598. + /** Descriptor List physical address. */
  37599. + dwc_dma_t desc_list_dma;
  37600. +
  37601. + /**
  37602. + * Xfer Bytes array.
  37603. + * Each element corresponds to a descriptor and indicates
  37604. + * original XferSize size value for the descriptor.
  37605. + */
  37606. + uint32_t *n_bytes;
  37607. +
  37608. + /** Actual number of transfer descriptors in a list. */
  37609. + uint16_t ntd;
  37610. +
  37611. + /** First activated isochronous transfer descriptor index. */
  37612. + uint8_t td_first;
  37613. + /** Last activated isochronous transfer descriptor index. */
  37614. + uint8_t td_last;
  37615. +
  37616. + /** @} */
  37617. +
  37618. +
  37619. + uint16_t speed;
  37620. + uint16_t frame_usecs[8];
  37621. +} dwc_otg_qh_t;
  37622. +
  37623. +DWC_CIRCLEQ_HEAD(hc_list, dwc_hc);
  37624. +
  37625. +/**
  37626. + * This structure holds the state of the HCD, including the non-periodic and
  37627. + * periodic schedules.
  37628. + */
  37629. +struct dwc_otg_hcd {
  37630. + /** The DWC otg device pointer */
  37631. + struct dwc_otg_device *otg_dev;
  37632. + /** DWC OTG Core Interface Layer */
  37633. + dwc_otg_core_if_t *core_if;
  37634. +
  37635. + /** Function HCD driver callbacks */
  37636. + struct dwc_otg_hcd_function_ops *fops;
  37637. +
  37638. + /** Internal DWC HCD Flags */
  37639. + volatile union dwc_otg_hcd_internal_flags {
  37640. + uint32_t d32;
  37641. + struct {
  37642. + unsigned port_connect_status_change:1;
  37643. + unsigned port_connect_status:1;
  37644. + unsigned port_reset_change:1;
  37645. + unsigned port_enable_change:1;
  37646. + unsigned port_suspend_change:1;
  37647. + unsigned port_over_current_change:1;
  37648. + unsigned port_l1_change:1;
  37649. + unsigned reserved:26;
  37650. + } b;
  37651. + } flags;
  37652. +
  37653. + /**
  37654. + * Inactive items in the non-periodic schedule. This is a list of
  37655. + * Queue Heads. Transfers associated with these Queue Heads are not
  37656. + * currently assigned to a host channel.
  37657. + */
  37658. + dwc_list_link_t non_periodic_sched_inactive;
  37659. +
  37660. + /**
  37661. + * Active items in the non-periodic schedule. This is a list of
  37662. + * Queue Heads. Transfers associated with these Queue Heads are
  37663. + * currently assigned to a host channel.
  37664. + */
  37665. + dwc_list_link_t non_periodic_sched_active;
  37666. +
  37667. + /**
  37668. + * Pointer to the next Queue Head to process in the active
  37669. + * non-periodic schedule.
  37670. + */
  37671. + dwc_list_link_t *non_periodic_qh_ptr;
  37672. +
  37673. + /**
  37674. + * Inactive items in the periodic schedule. This is a list of QHs for
  37675. + * periodic transfers that are _not_ scheduled for the next frame.
  37676. + * Each QH in the list has an interval counter that determines when it
  37677. + * needs to be scheduled for execution. This scheduling mechanism
  37678. + * allows only a simple calculation for periodic bandwidth used (i.e.
  37679. + * must assume that all periodic transfers may need to execute in the
  37680. + * same frame). However, it greatly simplifies scheduling and should
  37681. + * be sufficient for the vast majority of OTG hosts, which need to
  37682. + * connect to a small number of peripherals at one time.
  37683. + *
  37684. + * Items move from this list to periodic_sched_ready when the QH
  37685. + * interval counter is 0 at SOF.
  37686. + */
  37687. + dwc_list_link_t periodic_sched_inactive;
  37688. +
  37689. + /**
  37690. + * List of periodic QHs that are ready for execution in the next
  37691. + * frame, but have not yet been assigned to host channels.
  37692. + *
  37693. + * Items move from this list to periodic_sched_assigned as host
  37694. + * channels become available during the current frame.
  37695. + */
  37696. + dwc_list_link_t periodic_sched_ready;
  37697. +
  37698. + /**
  37699. + * List of periodic QHs to be executed in the next frame that are
  37700. + * assigned to host channels.
  37701. + *
  37702. + * Items move from this list to periodic_sched_queued as the
  37703. + * transactions for the QH are queued to the DWC_otg controller.
  37704. + */
  37705. + dwc_list_link_t periodic_sched_assigned;
  37706. +
  37707. + /**
  37708. + * List of periodic QHs that have been queued for execution.
  37709. + *
  37710. + * Items move from this list to either periodic_sched_inactive or
  37711. + * periodic_sched_ready when the channel associated with the transfer
  37712. + * is released. If the interval for the QH is 1, the item moves to
  37713. + * periodic_sched_ready because it must be rescheduled for the next
  37714. + * frame. Otherwise, the item moves to periodic_sched_inactive.
  37715. + */
  37716. + dwc_list_link_t periodic_sched_queued;
  37717. +
  37718. + /**
  37719. + * Total bandwidth claimed so far for periodic transfers. This value
  37720. + * is in microseconds per (micro)frame. The assumption is that all
  37721. + * periodic transfers may occur in the same (micro)frame.
  37722. + */
  37723. + uint16_t periodic_usecs;
  37724. +
  37725. + /**
  37726. + * Total bandwidth claimed so far for all periodic transfers
  37727. + * in a frame.
  37728. + * This will include a mixture of HS and FS transfers.
  37729. + * Units are microseconds per (micro)frame.
  37730. + * We have a budget per frame and have to schedule
  37731. + * transactions accordingly.
  37732. + * Watch out for the fact that things are actually scheduled for the
  37733. + * "next frame".
  37734. + */
  37735. + uint16_t frame_usecs[8];
  37736. +
  37737. +
  37738. + /**
  37739. + * Frame number read from the core at SOF. The value ranges from 0 to
  37740. + * DWC_HFNUM_MAX_FRNUM.
  37741. + */
  37742. + uint16_t frame_number;
  37743. +
  37744. + /**
  37745. + * Count of periodic QHs, if using several eps. For SOF enable/disable.
  37746. + */
  37747. + uint16_t periodic_qh_count;
  37748. +
  37749. + /**
  37750. + * Free host channels in the controller. This is a list of
  37751. + * dwc_hc_t items.
  37752. + */
  37753. + struct hc_list free_hc_list;
  37754. + /**
  37755. + * Number of host channels assigned to periodic transfers. Currently
  37756. + * assuming that there is a dedicated host channel for each periodic
  37757. + * transaction and at least one host channel available for
  37758. + * non-periodic transactions.
  37759. + */
  37760. + int periodic_channels; /* microframe_schedule==0 */
  37761. +
  37762. + /**
  37763. + * Number of host channels assigned to non-periodic transfers.
  37764. + */
  37765. + int non_periodic_channels; /* microframe_schedule==0 */
  37766. +
  37767. + /**
  37768. + * Number of host channels assigned to non-periodic transfers.
  37769. + */
  37770. + int available_host_channels;
  37771. +
  37772. + /**
  37773. + * Array of pointers to the host channel descriptors. Allows accessing
  37774. + * a host channel descriptor given the host channel number. This is
  37775. + * useful in interrupt handlers.
  37776. + */
  37777. + struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS];
  37778. +
  37779. + /**
  37780. + * Buffer to use for any data received during the status phase of a
  37781. + * control transfer. Normally no data is transferred during the status
  37782. + * phase. This buffer is used as a bit bucket.
  37783. + */
  37784. + uint8_t *status_buf;
  37785. +
  37786. + /**
  37787. + * DMA address for status_buf.
  37788. + */
  37789. + dma_addr_t status_buf_dma;
  37790. +#define DWC_OTG_HCD_STATUS_BUF_SIZE 64
  37791. +
  37792. + /**
  37793. + * Connection timer. An OTG host must display a message if the device
  37794. + * does not connect. Started when the VBus power is turned on via
  37795. + * sysfs attribute "buspower".
  37796. + */
  37797. + dwc_timer_t *conn_timer;
  37798. +
  37799. + /* Tasket to do a reset */
  37800. + dwc_tasklet_t *reset_tasklet;
  37801. +
  37802. + /* */
  37803. + dwc_spinlock_t *lock;
  37804. +
  37805. + /**
  37806. + * Private data that could be used by OS wrapper.
  37807. + */
  37808. + void *priv;
  37809. +
  37810. + uint8_t otg_port;
  37811. +
  37812. + /** Frame List */
  37813. + uint32_t *frame_list;
  37814. +
  37815. + /** Frame List DMA address */
  37816. + dma_addr_t frame_list_dma;
  37817. +
  37818. +#ifdef DEBUG
  37819. + uint32_t frrem_samples;
  37820. + uint64_t frrem_accum;
  37821. +
  37822. + uint32_t hfnum_7_samples_a;
  37823. + uint64_t hfnum_7_frrem_accum_a;
  37824. + uint32_t hfnum_0_samples_a;
  37825. + uint64_t hfnum_0_frrem_accum_a;
  37826. + uint32_t hfnum_other_samples_a;
  37827. + uint64_t hfnum_other_frrem_accum_a;
  37828. +
  37829. + uint32_t hfnum_7_samples_b;
  37830. + uint64_t hfnum_7_frrem_accum_b;
  37831. + uint32_t hfnum_0_samples_b;
  37832. + uint64_t hfnum_0_frrem_accum_b;
  37833. + uint32_t hfnum_other_samples_b;
  37834. + uint64_t hfnum_other_frrem_accum_b;
  37835. +#endif
  37836. +};
  37837. +
  37838. +/** @name Transaction Execution Functions */
  37839. +/** @{ */
  37840. +extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t
  37841. + * hcd);
  37842. +extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
  37843. + dwc_otg_transaction_type_e tr_type);
  37844. +
  37845. +/** @} */
  37846. +
  37847. +/** @name Interrupt Handler Functions */
  37848. +/** @{ */
  37849. +extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
  37850. +extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd);
  37851. +extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t *
  37852. + dwc_otg_hcd);
  37853. +extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t *
  37854. + dwc_otg_hcd);
  37855. +extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t *
  37856. + dwc_otg_hcd);
  37857. +extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t *
  37858. + dwc_otg_hcd);
  37859. +extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd);
  37860. +extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t *
  37861. + dwc_otg_hcd);
  37862. +extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t * dwc_otg_hcd);
  37863. +extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd);
  37864. +extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd,
  37865. + uint32_t num);
  37866. +extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t * dwc_otg_hcd);
  37867. +extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t *
  37868. + dwc_otg_hcd);
  37869. +/** @} */
  37870. +
  37871. +/** @name Schedule Queue Functions */
  37872. +/** @{ */
  37873. +
  37874. +/* Implemented in dwc_otg_hcd_queue.c */
  37875. +extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
  37876. + dwc_otg_hcd_urb_t * urb, int atomic_alloc);
  37877. +extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
  37878. +extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
  37879. +extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
  37880. +extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
  37881. + int sched_csplit);
  37882. +
  37883. +/** Remove and free a QH */
  37884. +static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd,
  37885. + dwc_otg_qh_t * qh)
  37886. +{
  37887. + dwc_irqflags_t flags;
  37888. + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
  37889. + dwc_otg_hcd_qh_remove(hcd, qh);
  37890. + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
  37891. + dwc_otg_hcd_qh_free(hcd, qh);
  37892. +}
  37893. +
  37894. +/** Allocates memory for a QH structure.
  37895. + * @return Returns the memory allocate or NULL on error. */
  37896. +static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(int atomic_alloc)
  37897. +{
  37898. + if (atomic_alloc)
  37899. + return (dwc_otg_qh_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qh_t));
  37900. + else
  37901. + return (dwc_otg_qh_t *) DWC_ALLOC(sizeof(dwc_otg_qh_t));
  37902. +}
  37903. +
  37904. +extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb,
  37905. + int atomic_alloc);
  37906. +extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb);
  37907. +extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd,
  37908. + dwc_otg_qh_t ** qh, int atomic_alloc);
  37909. +
  37910. +/** Allocates memory for a QTD structure.
  37911. + * @return Returns the memory allocate or NULL on error. */
  37912. +static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(int atomic_alloc)
  37913. +{
  37914. + if (atomic_alloc)
  37915. + return (dwc_otg_qtd_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qtd_t));
  37916. + else
  37917. + return (dwc_otg_qtd_t *) DWC_ALLOC(sizeof(dwc_otg_qtd_t));
  37918. +}
  37919. +
  37920. +/** Frees the memory for a QTD structure. QTD should already be removed from
  37921. + * list.
  37922. + * @param qtd QTD to free.*/
  37923. +static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd)
  37924. +{
  37925. + DWC_FREE(qtd);
  37926. +}
  37927. +
  37928. +/** Removes a QTD from list.
  37929. + * @param hcd HCD instance.
  37930. + * @param qtd QTD to remove from list.
  37931. + * @param qh QTD belongs to.
  37932. + */
  37933. +static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t * hcd,
  37934. + dwc_otg_qtd_t * qtd,
  37935. + dwc_otg_qh_t * qh)
  37936. +{
  37937. + DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
  37938. +}
  37939. +
  37940. +/** Remove and free a QTD
  37941. + * Need to disable IRQ and hold hcd lock while calling this function out of
  37942. + * interrupt servicing chain */
  37943. +static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd,
  37944. + dwc_otg_qtd_t * qtd,
  37945. + dwc_otg_qh_t * qh)
  37946. +{
  37947. + dwc_otg_hcd_qtd_remove(hcd, qtd, qh);
  37948. + dwc_otg_hcd_qtd_free(qtd);
  37949. +}
  37950. +
  37951. +/** @} */
  37952. +
  37953. +/** @name Descriptor DMA Supporting Functions */
  37954. +/** @{ */
  37955. +
  37956. +extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
  37957. +extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,
  37958. + dwc_hc_t * hc,
  37959. + dwc_otg_hc_regs_t * hc_regs,
  37960. + dwc_otg_halt_status_e halt_status);
  37961. +
  37962. +extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
  37963. +extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh);
  37964. +
  37965. +/** @} */
  37966. +
  37967. +/** @name Internal Functions */
  37968. +/** @{ */
  37969. +dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb);
  37970. +/** @} */
  37971. +
  37972. +#ifdef CONFIG_USB_DWC_OTG_LPM
  37973. +extern int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd,
  37974. + uint8_t devaddr);
  37975. +extern void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd);
  37976. +#endif
  37977. +
  37978. +/** Gets the QH that contains the list_head */
  37979. +#define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry)
  37980. +
  37981. +/** Gets the QTD that contains the list_head */
  37982. +#define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry)
  37983. +
  37984. +/** Check if QH is non-periodic */
  37985. +#define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \
  37986. + (_qh_ptr_->ep_type == UE_CONTROL))
  37987. +
  37988. +/** High bandwidth multiplier as encoded in highspeed endpoint descriptors */
  37989. +#define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
  37990. +
  37991. +/** Packet size for any kind of endpoint descriptor */
  37992. +#define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
  37993. +
  37994. +/**
  37995. + * Returns true if _frame1 is less than or equal to _frame2. The comparison is
  37996. + * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the
  37997. + * frame number when the max frame number is reached.
  37998. + */
  37999. +static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2)
  38000. +{
  38001. + return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <=
  38002. + (DWC_HFNUM_MAX_FRNUM >> 1);
  38003. +}
  38004. +
  38005. +/**
  38006. + * Returns true if _frame1 is greater than _frame2. The comparison is done
  38007. + * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame
  38008. + * number when the max frame number is reached.
  38009. + */
  38010. +static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2)
  38011. +{
  38012. + return (frame1 != frame2) &&
  38013. + (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) <
  38014. + (DWC_HFNUM_MAX_FRNUM >> 1));
  38015. +}
  38016. +
  38017. +/**
  38018. + * Increments _frame by the amount specified by _inc. The addition is done
  38019. + * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value.
  38020. + */
  38021. +static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc)
  38022. +{
  38023. + return (frame + inc) & DWC_HFNUM_MAX_FRNUM;
  38024. +}
  38025. +
  38026. +static inline uint16_t dwc_full_frame_num(uint16_t frame)
  38027. +{
  38028. + return (frame & DWC_HFNUM_MAX_FRNUM) >> 3;
  38029. +}
  38030. +
  38031. +static inline uint16_t dwc_micro_frame_num(uint16_t frame)
  38032. +{
  38033. + return frame & 0x7;
  38034. +}
  38035. +
  38036. +void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
  38037. + dwc_otg_hc_regs_t * hc_regs,
  38038. + dwc_otg_qtd_t * qtd);
  38039. +
  38040. +#ifdef DEBUG
  38041. +/**
  38042. + * Macro to sample the remaining PHY clocks left in the current frame. This
  38043. + * may be used during debugging to determine the average time it takes to
  38044. + * execute sections of code. There are two possible sample points, "a" and
  38045. + * "b", so the _letter argument must be one of these values.
  38046. + *
  38047. + * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For
  38048. + * example, "cat /sys/devices/lm0/hcd_frrem".
  38049. + */
  38050. +#define dwc_sample_frrem(_hcd, _qh, _letter) \
  38051. +{ \
  38052. + hfnum_data_t hfnum; \
  38053. + dwc_otg_qtd_t *qtd; \
  38054. + qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \
  38055. + if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \
  38056. + hfnum.d32 = DWC_READ_REG32(&_hcd->core_if->host_if->host_global_regs->hfnum); \
  38057. + switch (hfnum.b.frnum & 0x7) { \
  38058. + case 7: \
  38059. + _hcd->hfnum_7_samples_##_letter++; \
  38060. + _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \
  38061. + break; \
  38062. + case 0: \
  38063. + _hcd->hfnum_0_samples_##_letter++; \
  38064. + _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \
  38065. + break; \
  38066. + default: \
  38067. + _hcd->hfnum_other_samples_##_letter++; \
  38068. + _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \
  38069. + break; \
  38070. + } \
  38071. + } \
  38072. +}
  38073. +#else
  38074. +#define dwc_sample_frrem(_hcd, _qh, _letter)
  38075. +#endif
  38076. +#endif
  38077. +#endif /* DWC_DEVICE_ONLY */
  38078. --- /dev/null
  38079. +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
  38080. @@ -0,0 +1,1133 @@
  38081. +/*==========================================================================
  38082. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $
  38083. + * $Revision: #10 $
  38084. + * $Date: 2011/10/20 $
  38085. + * $Change: 1869464 $
  38086. + *
  38087. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  38088. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  38089. + * otherwise expressly agreed to in writing between Synopsys and you.
  38090. + *
  38091. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  38092. + * any End User Software License Agreement or Agreement for Licensed Product
  38093. + * with Synopsys or any supplement thereto. You are permitted to use and
  38094. + * redistribute this Software in source and binary forms, with or without
  38095. + * modification, provided that redistributions of source code must retain this
  38096. + * notice. You may not view, use, disclose, copy or distribute this file or
  38097. + * any information contained herein except pursuant to this license grant from
  38098. + * Synopsys. If you do not agree with this notice, including the disclaimer
  38099. + * below, then you are not authorized to use the Software.
  38100. + *
  38101. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  38102. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  38103. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  38104. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  38105. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  38106. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  38107. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  38108. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  38109. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  38110. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  38111. + * DAMAGE.
  38112. + * ========================================================================== */
  38113. +#ifndef DWC_DEVICE_ONLY
  38114. +
  38115. +/** @file
  38116. + * This file contains Descriptor DMA support implementation for host mode.
  38117. + */
  38118. +
  38119. +#include "dwc_otg_hcd.h"
  38120. +#include "dwc_otg_regs.h"
  38121. +
  38122. +extern bool microframe_schedule;
  38123. +
  38124. +static inline uint8_t frame_list_idx(uint16_t frame)
  38125. +{
  38126. + return (frame & (MAX_FRLIST_EN_NUM - 1));
  38127. +}
  38128. +
  38129. +static inline uint16_t desclist_idx_inc(uint16_t idx, uint16_t inc, uint8_t speed)
  38130. +{
  38131. + return (idx + inc) &
  38132. + (((speed ==
  38133. + DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC :
  38134. + MAX_DMA_DESC_NUM_GENERIC) - 1);
  38135. +}
  38136. +
  38137. +static inline uint16_t desclist_idx_dec(uint16_t idx, uint16_t inc, uint8_t speed)
  38138. +{
  38139. + return (idx - inc) &
  38140. + (((speed ==
  38141. + DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC :
  38142. + MAX_DMA_DESC_NUM_GENERIC) - 1);
  38143. +}
  38144. +
  38145. +static inline uint16_t max_desc_num(dwc_otg_qh_t * qh)
  38146. +{
  38147. + return (((qh->ep_type == UE_ISOCHRONOUS)
  38148. + && (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH))
  38149. + ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC);
  38150. +}
  38151. +static inline uint16_t frame_incr_val(dwc_otg_qh_t * qh)
  38152. +{
  38153. + return ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH)
  38154. + ? ((qh->interval + 8 - 1) / 8)
  38155. + : qh->interval);
  38156. +}
  38157. +
  38158. +static int desc_list_alloc(dwc_otg_qh_t * qh)
  38159. +{
  38160. + int retval = 0;
  38161. +
  38162. + qh->desc_list = (dwc_otg_host_dma_desc_t *)
  38163. + DWC_DMA_ALLOC(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh),
  38164. + &qh->desc_list_dma);
  38165. +
  38166. + if (!qh->desc_list) {
  38167. + retval = -DWC_E_NO_MEMORY;
  38168. + DWC_ERROR("%s: DMA descriptor list allocation failed\n", __func__);
  38169. +
  38170. + }
  38171. +
  38172. + dwc_memset(qh->desc_list, 0x00,
  38173. + sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));
  38174. +
  38175. + qh->n_bytes =
  38176. + (uint32_t *) DWC_ALLOC(sizeof(uint32_t) * max_desc_num(qh));
  38177. +
  38178. + if (!qh->n_bytes) {
  38179. + retval = -DWC_E_NO_MEMORY;
  38180. + DWC_ERROR
  38181. + ("%s: Failed to allocate array for descriptors' size actual values\n",
  38182. + __func__);
  38183. +
  38184. + }
  38185. + return retval;
  38186. +
  38187. +}
  38188. +
  38189. +static void desc_list_free(dwc_otg_qh_t * qh)
  38190. +{
  38191. + if (qh->desc_list) {
  38192. + DWC_DMA_FREE(max_desc_num(qh), qh->desc_list,
  38193. + qh->desc_list_dma);
  38194. + qh->desc_list = NULL;
  38195. + }
  38196. +
  38197. + if (qh->n_bytes) {
  38198. + DWC_FREE(qh->n_bytes);
  38199. + qh->n_bytes = NULL;
  38200. + }
  38201. +}
  38202. +
  38203. +static int frame_list_alloc(dwc_otg_hcd_t * hcd)
  38204. +{
  38205. + int retval = 0;
  38206. + if (hcd->frame_list)
  38207. + return 0;
  38208. +
  38209. + hcd->frame_list = DWC_DMA_ALLOC(4 * MAX_FRLIST_EN_NUM,
  38210. + &hcd->frame_list_dma);
  38211. + if (!hcd->frame_list) {
  38212. + retval = -DWC_E_NO_MEMORY;
  38213. + DWC_ERROR("%s: Frame List allocation failed\n", __func__);
  38214. + }
  38215. +
  38216. + dwc_memset(hcd->frame_list, 0x00, 4 * MAX_FRLIST_EN_NUM);
  38217. +
  38218. + return retval;
  38219. +}
  38220. +
  38221. +static void frame_list_free(dwc_otg_hcd_t * hcd)
  38222. +{
  38223. + if (!hcd->frame_list)
  38224. + return;
  38225. +
  38226. + DWC_DMA_FREE(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma);
  38227. + hcd->frame_list = NULL;
  38228. +}
  38229. +
  38230. +static void per_sched_enable(dwc_otg_hcd_t * hcd, uint16_t fr_list_en)
  38231. +{
  38232. +
  38233. + hcfg_data_t hcfg;
  38234. +
  38235. + hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg);
  38236. +
  38237. + if (hcfg.b.perschedena) {
  38238. + /* already enabled */
  38239. + return;
  38240. + }
  38241. +
  38242. + DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hflbaddr,
  38243. + hcd->frame_list_dma);
  38244. +
  38245. + switch (fr_list_en) {
  38246. + case 64:
  38247. + hcfg.b.frlisten = 3;
  38248. + break;
  38249. + case 32:
  38250. + hcfg.b.frlisten = 2;
  38251. + break;
  38252. + case 16:
  38253. + hcfg.b.frlisten = 1;
  38254. + break;
  38255. + case 8:
  38256. + hcfg.b.frlisten = 0;
  38257. + break;
  38258. + default:
  38259. + break;
  38260. + }
  38261. +
  38262. + hcfg.b.perschedena = 1;
  38263. +
  38264. + DWC_DEBUGPL(DBG_HCD, "Enabling Periodic schedule\n");
  38265. + DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32);
  38266. +
  38267. +}
  38268. +
  38269. +static void per_sched_disable(dwc_otg_hcd_t * hcd)
  38270. +{
  38271. + hcfg_data_t hcfg;
  38272. +
  38273. + hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg);
  38274. +
  38275. + if (!hcfg.b.perschedena) {
  38276. + /* already disabled */
  38277. + return;
  38278. + }
  38279. + hcfg.b.perschedena = 0;
  38280. +
  38281. + DWC_DEBUGPL(DBG_HCD, "Disabling Periodic schedule\n");
  38282. + DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32);
  38283. +}
  38284. +
  38285. +/*
  38286. + * Activates/Deactivates FrameList entries for the channel
  38287. + * based on endpoint servicing period.
  38288. + */
  38289. +void update_frame_list(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t enable)
  38290. +{
  38291. + uint16_t i, j, inc;
  38292. + dwc_hc_t *hc = NULL;
  38293. +
  38294. + if (!qh->channel) {
  38295. + DWC_ERROR("qh->channel = %p", qh->channel);
  38296. + return;
  38297. + }
  38298. +
  38299. + if (!hcd) {
  38300. + DWC_ERROR("------hcd = %p", hcd);
  38301. + return;
  38302. + }
  38303. +
  38304. + if (!hcd->frame_list) {
  38305. + DWC_ERROR("-------hcd->frame_list = %p", hcd->frame_list);
  38306. + return;
  38307. + }
  38308. +
  38309. + hc = qh->channel;
  38310. + inc = frame_incr_val(qh);
  38311. + if (qh->ep_type == UE_ISOCHRONOUS)
  38312. + i = frame_list_idx(qh->sched_frame);
  38313. + else
  38314. + i = 0;
  38315. +
  38316. + j = i;
  38317. + do {
  38318. + if (enable)
  38319. + hcd->frame_list[j] |= (1 << hc->hc_num);
  38320. + else
  38321. + hcd->frame_list[j] &= ~(1 << hc->hc_num);
  38322. + j = (j + inc) & (MAX_FRLIST_EN_NUM - 1);
  38323. + }
  38324. + while (j != i);
  38325. + if (!enable)
  38326. + return;
  38327. + hc->schinfo = 0;
  38328. + if (qh->channel->speed == DWC_OTG_EP_SPEED_HIGH) {
  38329. + j = 1;
  38330. + /* TODO - check this */
  38331. + inc = (8 + qh->interval - 1) / qh->interval;
  38332. + for (i = 0; i < inc; i++) {
  38333. + hc->schinfo |= j;
  38334. + j = j << qh->interval;
  38335. + }
  38336. + } else {
  38337. + hc->schinfo = 0xff;
  38338. + }
  38339. +}
  38340. +
  38341. +#if 1
  38342. +void dump_frame_list(dwc_otg_hcd_t * hcd)
  38343. +{
  38344. + int i = 0;
  38345. + DWC_PRINTF("--FRAME LIST (hex) --\n");
  38346. + for (i = 0; i < MAX_FRLIST_EN_NUM; i++) {
  38347. + DWC_PRINTF("%x\t", hcd->frame_list[i]);
  38348. + if (!(i % 8) && i)
  38349. + DWC_PRINTF("\n");
  38350. + }
  38351. + DWC_PRINTF("\n----\n");
  38352. +
  38353. +}
  38354. +#endif
  38355. +
  38356. +static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
  38357. +{
  38358. + dwc_irqflags_t flags;
  38359. + dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
  38360. +
  38361. + dwc_hc_t *hc = qh->channel;
  38362. + if (dwc_qh_is_non_per(qh)) {
  38363. + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
  38364. + if (!microframe_schedule)
  38365. + hcd->non_periodic_channels--;
  38366. + else
  38367. + hcd->available_host_channels++;
  38368. + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
  38369. + } else
  38370. + update_frame_list(hcd, qh, 0);
  38371. +
  38372. + /*
  38373. + * The condition is added to prevent double cleanup try in case of device
  38374. + * disconnect. See channel cleanup in dwc_otg_hcd_disconnect_cb().
  38375. + */
  38376. + if (hc->qh) {
  38377. + dwc_otg_hc_cleanup(hcd->core_if, hc);
  38378. + DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
  38379. + hc->qh = NULL;
  38380. + }
  38381. +
  38382. + qh->channel = NULL;
  38383. + qh->ntd = 0;
  38384. +
  38385. + if (qh->desc_list) {
  38386. + dwc_memset(qh->desc_list, 0x00,
  38387. + sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh));
  38388. + }
  38389. + DWC_SPINLOCK_FREE(channel_lock);
  38390. +}
  38391. +
  38392. +/**
  38393. + * Initializes a QH structure's Descriptor DMA related members.
  38394. + * Allocates memory for descriptor list.
  38395. + * On first periodic QH, allocates memory for FrameList
  38396. + * and enables periodic scheduling.
  38397. + *
  38398. + * @param hcd The HCD state structure for the DWC OTG controller.
  38399. + * @param qh The QH to init.
  38400. + *
  38401. + * @return 0 if successful, negative error code otherwise.
  38402. + */
  38403. +int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
  38404. +{
  38405. + int retval = 0;
  38406. +
  38407. + if (qh->do_split) {
  38408. + DWC_ERROR("SPLIT Transfers are not supported in Descriptor DMA.\n");
  38409. + return -1;
  38410. + }
  38411. +
  38412. + retval = desc_list_alloc(qh);
  38413. +
  38414. + if ((retval == 0)
  38415. + && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) {
  38416. + if (!hcd->frame_list) {
  38417. + retval = frame_list_alloc(hcd);
  38418. + /* Enable periodic schedule on first periodic QH */
  38419. + if (retval == 0)
  38420. + per_sched_enable(hcd, MAX_FRLIST_EN_NUM);
  38421. + }
  38422. + }
  38423. +
  38424. + qh->ntd = 0;
  38425. +
  38426. + return retval;
  38427. +}
  38428. +
  38429. +/**
  38430. + * Frees descriptor list memory associated with the QH.
  38431. + * If QH is periodic and the last, frees FrameList memory
  38432. + * and disables periodic scheduling.
  38433. + *
  38434. + * @param hcd The HCD state structure for the DWC OTG controller.
  38435. + * @param qh The QH to init.
  38436. + */
  38437. +void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
  38438. +{
  38439. + desc_list_free(qh);
  38440. +
  38441. + /*
  38442. + * Channel still assigned due to some reasons.
  38443. + * Seen on Isoc URB dequeue. Channel halted but no subsequent
  38444. + * ChHalted interrupt to release the channel. Afterwards
  38445. + * when it comes here from endpoint disable routine
  38446. + * channel remains assigned.
  38447. + */
  38448. + if (qh->channel)
  38449. + release_channel_ddma(hcd, qh);
  38450. +
  38451. + if ((qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)
  38452. + && (microframe_schedule || !hcd->periodic_channels) && hcd->frame_list) {
  38453. +
  38454. + per_sched_disable(hcd);
  38455. + frame_list_free(hcd);
  38456. + }
  38457. +}
  38458. +
  38459. +static uint8_t frame_to_desc_idx(dwc_otg_qh_t * qh, uint16_t frame_idx)
  38460. +{
  38461. + if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) {
  38462. + /*
  38463. + * Descriptor set(8 descriptors) index
  38464. + * which is 8-aligned.
  38465. + */
  38466. + return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8;
  38467. + } else {
  38468. + return (frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1));
  38469. + }
  38470. +}
  38471. +
  38472. +/*
  38473. + * Determine starting frame for Isochronous transfer.
  38474. + * Few frames skipped to prevent race condition with HC.
  38475. + */
  38476. +static uint8_t calc_starting_frame(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
  38477. + uint8_t * skip_frames)
  38478. +{
  38479. + uint16_t frame = 0;
  38480. + hcd->frame_number = dwc_otg_hcd_get_frame_number(hcd);
  38481. +
  38482. + /* sched_frame is always frame number(not uFrame) both in FS and HS !! */
  38483. +
  38484. + /*
  38485. + * skip_frames is used to limit activated descriptors number
  38486. + * to avoid the situation when HC services the last activated
  38487. + * descriptor firstly.
  38488. + * Example for FS:
  38489. + * Current frame is 1, scheduled frame is 3. Since HC always fetches the descriptor
  38490. + * corresponding to curr_frame+1, the descriptor corresponding to frame 2
  38491. + * will be fetched. If the number of descriptors is max=64 (or greather) the
  38492. + * list will be fully programmed with Active descriptors and it is possible
  38493. + * case(rare) that the latest descriptor(considering rollback) corresponding
  38494. + * to frame 2 will be serviced first. HS case is more probable because, in fact,
  38495. + * up to 11 uframes(16 in the code) may be skipped.
  38496. + */
  38497. + if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) {
  38498. + /*
  38499. + * Consider uframe counter also, to start xfer asap.
  38500. + * If half of the frame elapsed skip 2 frames otherwise
  38501. + * just 1 frame.
  38502. + * Starting descriptor index must be 8-aligned, so
  38503. + * if the current frame is near to complete the next one
  38504. + * is skipped as well.
  38505. + */
  38506. +
  38507. + if (dwc_micro_frame_num(hcd->frame_number) >= 5) {
  38508. + *skip_frames = 2 * 8;
  38509. + frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames);
  38510. + } else {
  38511. + *skip_frames = 1 * 8;
  38512. + frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames);
  38513. + }
  38514. +
  38515. + frame = dwc_full_frame_num(frame);
  38516. + } else {
  38517. + /*
  38518. + * Two frames are skipped for FS - the current and the next.
  38519. + * But for descriptor programming, 1 frame(descriptor) is enough,
  38520. + * see example above.
  38521. + */
  38522. + *skip_frames = 1;
  38523. + frame = dwc_frame_num_inc(hcd->frame_number, 2);
  38524. + }
  38525. +
  38526. + return frame;
  38527. +}
  38528. +
  38529. +/*
  38530. + * Calculate initial descriptor index for isochronous transfer
  38531. + * based on scheduled frame.
  38532. + */
  38533. +static uint8_t recalc_initial_desc_idx(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
  38534. +{
  38535. + uint16_t frame = 0, fr_idx, fr_idx_tmp;
  38536. + uint8_t skip_frames = 0;
  38537. + /*
  38538. + * With current ISOC processing algorithm the channel is being
  38539. + * released when no more QTDs in the list(qh->ntd == 0).
  38540. + * Thus this function is called only when qh->ntd == 0 and qh->channel == 0.
  38541. + *
  38542. + * So qh->channel != NULL branch is not used and just not removed from the
  38543. + * source file. It is required for another possible approach which is,
  38544. + * do not disable and release the channel when ISOC session completed,
  38545. + * just move QH to inactive schedule until new QTD arrives.
  38546. + * On new QTD, the QH moved back to 'ready' schedule,
  38547. + * starting frame and therefore starting desc_index are recalculated.
  38548. + * In this case channel is released only on ep_disable.
  38549. + */
  38550. +
  38551. + /* Calculate starting descriptor index. For INTERRUPT endpoint it is always 0. */
  38552. + if (qh->channel) {
  38553. + frame = calc_starting_frame(hcd, qh, &skip_frames);
  38554. + /*
  38555. + * Calculate initial descriptor index based on FrameList current bitmap
  38556. + * and servicing period.
  38557. + */
  38558. + fr_idx_tmp = frame_list_idx(frame);
  38559. + fr_idx =
  38560. + (MAX_FRLIST_EN_NUM + frame_list_idx(qh->sched_frame) -
  38561. + fr_idx_tmp)
  38562. + % frame_incr_val(qh);
  38563. + fr_idx = (fr_idx + fr_idx_tmp) % MAX_FRLIST_EN_NUM;
  38564. + } else {
  38565. + qh->sched_frame = calc_starting_frame(hcd, qh, &skip_frames);
  38566. + fr_idx = frame_list_idx(qh->sched_frame);
  38567. + }
  38568. +
  38569. + qh->td_first = qh->td_last = frame_to_desc_idx(qh, fr_idx);
  38570. +
  38571. + return skip_frames;
  38572. +}
  38573. +
  38574. +#define ISOC_URB_GIVEBACK_ASAP
  38575. +
  38576. +#define MAX_ISOC_XFER_SIZE_FS 1023
  38577. +#define MAX_ISOC_XFER_SIZE_HS 3072
  38578. +#define DESCNUM_THRESHOLD 4
  38579. +
  38580. +static void init_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
  38581. + uint8_t skip_frames)
  38582. +{
  38583. + struct dwc_otg_hcd_iso_packet_desc *frame_desc;
  38584. + dwc_otg_qtd_t *qtd;
  38585. + dwc_otg_host_dma_desc_t *dma_desc;
  38586. + uint16_t idx, inc, n_desc, ntd_max, max_xfer_size;
  38587. +
  38588. + idx = qh->td_last;
  38589. + inc = qh->interval;
  38590. + n_desc = 0;
  38591. +
  38592. + ntd_max = (max_desc_num(qh) + qh->interval - 1) / qh->interval;
  38593. + if (skip_frames && !qh->channel)
  38594. + ntd_max = ntd_max - skip_frames / qh->interval;
  38595. +
  38596. + max_xfer_size =
  38597. + (qh->dev_speed ==
  38598. + DWC_OTG_EP_SPEED_HIGH) ? MAX_ISOC_XFER_SIZE_HS :
  38599. + MAX_ISOC_XFER_SIZE_FS;
  38600. +
  38601. + DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) {
  38602. + while ((qh->ntd < ntd_max)
  38603. + && (qtd->isoc_frame_index_last <
  38604. + qtd->urb->packet_count)) {
  38605. +
  38606. + dma_desc = &qh->desc_list[idx];
  38607. + dwc_memset(dma_desc, 0x00, sizeof(dwc_otg_host_dma_desc_t));
  38608. +
  38609. + frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last];
  38610. +
  38611. + if (frame_desc->length > max_xfer_size)
  38612. + qh->n_bytes[idx] = max_xfer_size;
  38613. + else
  38614. + qh->n_bytes[idx] = frame_desc->length;
  38615. + dma_desc->status.b_isoc.n_bytes = qh->n_bytes[idx];
  38616. + dma_desc->status.b_isoc.a = 1;
  38617. + dma_desc->status.b_isoc.sts = 0;
  38618. +
  38619. + dma_desc->buf = qtd->urb->dma + frame_desc->offset;
  38620. +
  38621. + qh->ntd++;
  38622. +
  38623. + qtd->isoc_frame_index_last++;
  38624. +
  38625. +#ifdef ISOC_URB_GIVEBACK_ASAP
  38626. + /*
  38627. + * Set IOC for each descriptor corresponding to the
  38628. + * last frame of the URB.
  38629. + */
  38630. + if (qtd->isoc_frame_index_last ==
  38631. + qtd->urb->packet_count)
  38632. + dma_desc->status.b_isoc.ioc = 1;
  38633. +
  38634. +#endif
  38635. + idx = desclist_idx_inc(idx, inc, qh->dev_speed);
  38636. + n_desc++;
  38637. +
  38638. + }
  38639. + qtd->in_process = 1;
  38640. + }
  38641. +
  38642. + qh->td_last = idx;
  38643. +
  38644. +#ifdef ISOC_URB_GIVEBACK_ASAP
  38645. + /* Set IOC for the last descriptor if descriptor list is full */
  38646. + if (qh->ntd == ntd_max) {
  38647. + idx = desclist_idx_dec(qh->td_last, inc, qh->dev_speed);
  38648. + qh->desc_list[idx].status.b_isoc.ioc = 1;
  38649. + }
  38650. +#else
  38651. + /*
  38652. + * Set IOC bit only for one descriptor.
  38653. + * Always try to be ahead of HW processing,
  38654. + * i.e. on IOC generation driver activates next descriptors but
  38655. + * core continues to process descriptors followed the one with IOC set.
  38656. + */
  38657. +
  38658. + if (n_desc > DESCNUM_THRESHOLD) {
  38659. + /*
  38660. + * Move IOC "up". Required even if there is only one QTD
  38661. + * in the list, cause QTDs migth continue to be queued,
  38662. + * but during the activation it was only one queued.
  38663. + * Actually more than one QTD might be in the list if this function called
  38664. + * from XferCompletion - QTDs was queued during HW processing of the previous
  38665. + * descriptor chunk.
  38666. + */
  38667. + idx = dwc_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2), qh->dev_speed);
  38668. + } else {
  38669. + /*
  38670. + * Set the IOC for the latest descriptor
  38671. + * if either number of descriptor is not greather than threshold
  38672. + * or no more new descriptors activated.
  38673. + */
  38674. + idx = dwc_desclist_idx_dec(qh->td_last, inc, qh->dev_speed);
  38675. + }
  38676. +
  38677. + qh->desc_list[idx].status.b_isoc.ioc = 1;
  38678. +#endif
  38679. +}
  38680. +
  38681. +static void init_non_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
  38682. +{
  38683. +
  38684. + dwc_hc_t *hc;
  38685. + dwc_otg_host_dma_desc_t *dma_desc;
  38686. + dwc_otg_qtd_t *qtd;
  38687. + int num_packets, len, n_desc = 0;
  38688. +
  38689. + hc = qh->channel;
  38690. +
  38691. + /*
  38692. + * Start with hc->xfer_buff initialized in
  38693. + * assign_and_init_hc(), then if SG transfer consists of multiple URBs,
  38694. + * this pointer re-assigned to the buffer of the currently processed QTD.
  38695. + * For non-SG request there is always one QTD active.
  38696. + */
  38697. +
  38698. + DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) {
  38699. +
  38700. + if (n_desc) {
  38701. + /* SG request - more than 1 QTDs */
  38702. + hc->xfer_buff = (uint8_t *)qtd->urb->dma + qtd->urb->actual_length;
  38703. + hc->xfer_len = qtd->urb->length - qtd->urb->actual_length;
  38704. + }
  38705. +
  38706. + qtd->n_desc = 0;
  38707. +
  38708. + do {
  38709. + dma_desc = &qh->desc_list[n_desc];
  38710. + len = hc->xfer_len;
  38711. +
  38712. + if (len > MAX_DMA_DESC_SIZE)
  38713. + len = MAX_DMA_DESC_SIZE - hc->max_packet + 1;
  38714. +
  38715. + if (hc->ep_is_in) {
  38716. + if (len > 0) {
  38717. + num_packets = (len + hc->max_packet - 1) / hc->max_packet;
  38718. + } else {
  38719. + /* Need 1 packet for transfer length of 0. */
  38720. + num_packets = 1;
  38721. + }
  38722. + /* Always program an integral # of max packets for IN transfers. */
  38723. + len = num_packets * hc->max_packet;
  38724. + }
  38725. +
  38726. + dma_desc->status.b.n_bytes = len;
  38727. +
  38728. + qh->n_bytes[n_desc] = len;
  38729. +
  38730. + if ((qh->ep_type == UE_CONTROL)
  38731. + && (qtd->control_phase == DWC_OTG_CONTROL_SETUP))
  38732. + dma_desc->status.b.sup = 1; /* Setup Packet */
  38733. +
  38734. + dma_desc->status.b.a = 1; /* Active descriptor */
  38735. + dma_desc->status.b.sts = 0;
  38736. +
  38737. + dma_desc->buf =
  38738. + ((unsigned long)hc->xfer_buff & 0xffffffff);
  38739. +
  38740. + /*
  38741. + * Last descriptor(or single) of IN transfer
  38742. + * with actual size less than MaxPacket.
  38743. + */
  38744. + if (len > hc->xfer_len) {
  38745. + hc->xfer_len = 0;
  38746. + } else {
  38747. + hc->xfer_buff += len;
  38748. + hc->xfer_len -= len;
  38749. + }
  38750. +
  38751. + qtd->n_desc++;
  38752. + n_desc++;
  38753. + }
  38754. + while ((hc->xfer_len > 0) && (n_desc != MAX_DMA_DESC_NUM_GENERIC));
  38755. +
  38756. +
  38757. + qtd->in_process = 1;
  38758. +
  38759. + if (qh->ep_type == UE_CONTROL)
  38760. + break;
  38761. +
  38762. + if (n_desc == MAX_DMA_DESC_NUM_GENERIC)
  38763. + break;
  38764. + }
  38765. +
  38766. + if (n_desc) {
  38767. + /* Request Transfer Complete interrupt for the last descriptor */
  38768. + qh->desc_list[n_desc - 1].status.b.ioc = 1;
  38769. + /* End of List indicator */
  38770. + qh->desc_list[n_desc - 1].status.b.eol = 1;
  38771. +
  38772. + hc->ntd = n_desc;
  38773. + }
  38774. +}
  38775. +
  38776. +/**
  38777. + * For Control and Bulk endpoints initializes descriptor list
  38778. + * and starts the transfer.
  38779. + *
  38780. + * For Interrupt and Isochronous endpoints initializes descriptor list
  38781. + * then updates FrameList, marking appropriate entries as active.
  38782. + * In case of Isochronous, the starting descriptor index is calculated based
  38783. + * on the scheduled frame, but only on the first transfer descriptor within a session.
  38784. + * Then starts the transfer via enabling the channel.
  38785. + * For Isochronous endpoint the channel is not halted on XferComplete
  38786. + * interrupt so remains assigned to the endpoint(QH) until session is done.
  38787. + *
  38788. + * @param hcd The HCD state structure for the DWC OTG controller.
  38789. + * @param qh The QH to init.
  38790. + *
  38791. + * @return 0 if successful, negative error code otherwise.
  38792. + */
  38793. +void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
  38794. +{
  38795. + /* Channel is already assigned */
  38796. + dwc_hc_t *hc = qh->channel;
  38797. + uint8_t skip_frames = 0;
  38798. +
  38799. + switch (hc->ep_type) {
  38800. + case DWC_OTG_EP_TYPE_CONTROL:
  38801. + case DWC_OTG_EP_TYPE_BULK:
  38802. + init_non_isoc_dma_desc(hcd, qh);
  38803. +
  38804. + dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
  38805. + break;
  38806. + case DWC_OTG_EP_TYPE_INTR:
  38807. + init_non_isoc_dma_desc(hcd, qh);
  38808. +
  38809. + update_frame_list(hcd, qh, 1);
  38810. +
  38811. + dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
  38812. + break;
  38813. + case DWC_OTG_EP_TYPE_ISOC:
  38814. +
  38815. + if (!qh->ntd)
  38816. + skip_frames = recalc_initial_desc_idx(hcd, qh);
  38817. +
  38818. + init_isoc_dma_desc(hcd, qh, skip_frames);
  38819. +
  38820. + if (!hc->xfer_started) {
  38821. +
  38822. + update_frame_list(hcd, qh, 1);
  38823. +
  38824. + /*
  38825. + * Always set to max, instead of actual size.
  38826. + * Otherwise ntd will be changed with
  38827. + * channel being enabled. Not recommended.
  38828. + *
  38829. + */
  38830. + hc->ntd = max_desc_num(qh);
  38831. + /* Enable channel only once for ISOC */
  38832. + dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc);
  38833. + }
  38834. +
  38835. + break;
  38836. + default:
  38837. +
  38838. + break;
  38839. + }
  38840. +}
  38841. +
  38842. +static void complete_isoc_xfer_ddma(dwc_otg_hcd_t * hcd,
  38843. + dwc_hc_t * hc,
  38844. + dwc_otg_hc_regs_t * hc_regs,
  38845. + dwc_otg_halt_status_e halt_status)
  38846. +{
  38847. + struct dwc_otg_hcd_iso_packet_desc *frame_desc;
  38848. + dwc_otg_qtd_t *qtd, *qtd_tmp;
  38849. + dwc_otg_qh_t *qh;
  38850. + dwc_otg_host_dma_desc_t *dma_desc;
  38851. + uint16_t idx, remain;
  38852. + uint8_t urb_compl;
  38853. +
  38854. + qh = hc->qh;
  38855. + idx = qh->td_first;
  38856. +
  38857. + if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
  38858. + DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry)
  38859. + qtd->in_process = 0;
  38860. + return;
  38861. + } else if ((halt_status == DWC_OTG_HC_XFER_AHB_ERR) ||
  38862. + (halt_status == DWC_OTG_HC_XFER_BABBLE_ERR)) {
  38863. + /*
  38864. + * Channel is halted in these error cases.
  38865. + * Considered as serious issues.
  38866. + * Complete all URBs marking all frames as failed,
  38867. + * irrespective whether some of the descriptors(frames) succeeded or no.
  38868. + * Pass error code to completion routine as well, to
  38869. + * update urb->status, some of class drivers might use it to stop
  38870. + * queing transfer requests.
  38871. + */
  38872. + int err = (halt_status == DWC_OTG_HC_XFER_AHB_ERR)
  38873. + ? (-DWC_E_IO)
  38874. + : (-DWC_E_OVERFLOW);
  38875. +
  38876. + DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
  38877. + for (idx = 0; idx < qtd->urb->packet_count; idx++) {
  38878. + frame_desc = &qtd->urb->iso_descs[idx];
  38879. + frame_desc->status = err;
  38880. + }
  38881. + hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, err);
  38882. + dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
  38883. + }
  38884. + return;
  38885. + }
  38886. +
  38887. + DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
  38888. +
  38889. + if (!qtd->in_process)
  38890. + break;
  38891. +
  38892. + urb_compl = 0;
  38893. +
  38894. + do {
  38895. +
  38896. + dma_desc = &qh->desc_list[idx];
  38897. +
  38898. + frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
  38899. + remain = hc->ep_is_in ? dma_desc->status.b_isoc.n_bytes : 0;
  38900. +
  38901. + if (dma_desc->status.b_isoc.sts == DMA_DESC_STS_PKTERR) {
  38902. + /*
  38903. + * XactError or, unable to complete all the transactions
  38904. + * in the scheduled micro-frame/frame,
  38905. + * both indicated by DMA_DESC_STS_PKTERR.
  38906. + */
  38907. + qtd->urb->error_count++;
  38908. + frame_desc->actual_length = qh->n_bytes[idx] - remain;
  38909. + frame_desc->status = -DWC_E_PROTOCOL;
  38910. + } else {
  38911. + /* Success */
  38912. +
  38913. + frame_desc->actual_length = qh->n_bytes[idx] - remain;
  38914. + frame_desc->status = 0;
  38915. + }
  38916. +
  38917. + if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
  38918. + /*
  38919. + * urb->status is not used for isoc transfers here.
  38920. + * The individual frame_desc status are used instead.
  38921. + */
  38922. +
  38923. + hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
  38924. + dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
  38925. +
  38926. + /*
  38927. + * This check is necessary because urb_dequeue can be called
  38928. + * from urb complete callback(sound driver example).
  38929. + * All pending URBs are dequeued there, so no need for
  38930. + * further processing.
  38931. + */
  38932. + if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
  38933. + return;
  38934. + }
  38935. +
  38936. + urb_compl = 1;
  38937. +
  38938. + }
  38939. +
  38940. + qh->ntd--;
  38941. +
  38942. + /* Stop if IOC requested descriptor reached */
  38943. + if (dma_desc->status.b_isoc.ioc) {
  38944. + idx = desclist_idx_inc(idx, qh->interval, hc->speed);
  38945. + goto stop_scan;
  38946. + }
  38947. +
  38948. + idx = desclist_idx_inc(idx, qh->interval, hc->speed);
  38949. +
  38950. + if (urb_compl)
  38951. + break;
  38952. + }
  38953. + while (idx != qh->td_first);
  38954. + }
  38955. +stop_scan:
  38956. + qh->td_first = idx;
  38957. +}
  38958. +
  38959. +uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd,
  38960. + dwc_hc_t * hc,
  38961. + dwc_otg_qtd_t * qtd,
  38962. + dwc_otg_host_dma_desc_t * dma_desc,
  38963. + dwc_otg_halt_status_e halt_status,
  38964. + uint32_t n_bytes, uint8_t * xfer_done)
  38965. +{
  38966. +
  38967. + uint16_t remain = hc->ep_is_in ? dma_desc->status.b.n_bytes : 0;
  38968. + dwc_otg_hcd_urb_t *urb = qtd->urb;
  38969. +
  38970. + if (halt_status == DWC_OTG_HC_XFER_AHB_ERR) {
  38971. + urb->status = -DWC_E_IO;
  38972. + return 1;
  38973. + }
  38974. + if (dma_desc->status.b.sts == DMA_DESC_STS_PKTERR) {
  38975. + switch (halt_status) {
  38976. + case DWC_OTG_HC_XFER_STALL:
  38977. + urb->status = -DWC_E_PIPE;
  38978. + break;
  38979. + case DWC_OTG_HC_XFER_BABBLE_ERR:
  38980. + urb->status = -DWC_E_OVERFLOW;
  38981. + break;
  38982. + case DWC_OTG_HC_XFER_XACT_ERR:
  38983. + urb->status = -DWC_E_PROTOCOL;
  38984. + break;
  38985. + default:
  38986. + DWC_ERROR("%s: Unhandled descriptor error status (%d)\n", __func__,
  38987. + halt_status);
  38988. + break;
  38989. + }
  38990. + return 1;
  38991. + }
  38992. +
  38993. + if (dma_desc->status.b.a == 1) {
  38994. + DWC_DEBUGPL(DBG_HCDV,
  38995. + "Active descriptor encountered on channel %d\n",
  38996. + hc->hc_num);
  38997. + return 0;
  38998. + }
  38999. +
  39000. + if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL) {
  39001. + if (qtd->control_phase == DWC_OTG_CONTROL_DATA) {
  39002. + urb->actual_length += n_bytes - remain;
  39003. + if (remain || urb->actual_length == urb->length) {
  39004. + /*
  39005. + * For Control Data stage do not set urb->status=0 to prevent
  39006. + * URB callback. Set it when Status phase done. See below.
  39007. + */
  39008. + *xfer_done = 1;
  39009. + }
  39010. +
  39011. + } else if (qtd->control_phase == DWC_OTG_CONTROL_STATUS) {
  39012. + urb->status = 0;
  39013. + *xfer_done = 1;
  39014. + }
  39015. + /* No handling for SETUP stage */
  39016. + } else {
  39017. + /* BULK and INTR */
  39018. + urb->actual_length += n_bytes - remain;
  39019. + if (remain || urb->actual_length == urb->length) {
  39020. + urb->status = 0;
  39021. + *xfer_done = 1;
  39022. + }
  39023. + }
  39024. +
  39025. + return 0;
  39026. +}
  39027. +
  39028. +static void complete_non_isoc_xfer_ddma(dwc_otg_hcd_t * hcd,
  39029. + dwc_hc_t * hc,
  39030. + dwc_otg_hc_regs_t * hc_regs,
  39031. + dwc_otg_halt_status_e halt_status)
  39032. +{
  39033. + dwc_otg_hcd_urb_t *urb = NULL;
  39034. + dwc_otg_qtd_t *qtd, *qtd_tmp;
  39035. + dwc_otg_qh_t *qh;
  39036. + dwc_otg_host_dma_desc_t *dma_desc;
  39037. + uint32_t n_bytes, n_desc, i;
  39038. + uint8_t failed = 0, xfer_done;
  39039. +
  39040. + n_desc = 0;
  39041. +
  39042. + qh = hc->qh;
  39043. +
  39044. + if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
  39045. + DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) {
  39046. + qtd->in_process = 0;
  39047. + }
  39048. + return;
  39049. + }
  39050. +
  39051. + DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) {
  39052. +
  39053. + urb = qtd->urb;
  39054. +
  39055. + n_bytes = 0;
  39056. + xfer_done = 0;
  39057. +
  39058. + for (i = 0; i < qtd->n_desc; i++) {
  39059. + dma_desc = &qh->desc_list[n_desc];
  39060. +
  39061. + n_bytes = qh->n_bytes[n_desc];
  39062. +
  39063. + failed =
  39064. + update_non_isoc_urb_state_ddma(hcd, hc, qtd,
  39065. + dma_desc,
  39066. + halt_status, n_bytes,
  39067. + &xfer_done);
  39068. +
  39069. + if (failed
  39070. + || (xfer_done
  39071. + && (urb->status != -DWC_E_IN_PROGRESS))) {
  39072. +
  39073. + hcd->fops->complete(hcd, urb->priv, urb,
  39074. + urb->status);
  39075. + dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
  39076. +
  39077. + if (failed)
  39078. + goto stop_scan;
  39079. + } else if (qh->ep_type == UE_CONTROL) {
  39080. + if (qtd->control_phase == DWC_OTG_CONTROL_SETUP) {
  39081. + if (urb->length > 0) {
  39082. + qtd->control_phase = DWC_OTG_CONTROL_DATA;
  39083. + } else {
  39084. + qtd->control_phase = DWC_OTG_CONTROL_STATUS;
  39085. + }
  39086. + DWC_DEBUGPL(DBG_HCDV, " Control setup transaction done\n");
  39087. + } else if (qtd->control_phase == DWC_OTG_CONTROL_DATA) {
  39088. + if (xfer_done) {
  39089. + qtd->control_phase = DWC_OTG_CONTROL_STATUS;
  39090. + DWC_DEBUGPL(DBG_HCDV, " Control data transfer done\n");
  39091. + } else if (i + 1 == qtd->n_desc) {
  39092. + /*
  39093. + * Last descriptor for Control data stage which is
  39094. + * not completed yet.
  39095. + */
  39096. + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
  39097. + }
  39098. + }
  39099. + }
  39100. +
  39101. + n_desc++;
  39102. + }
  39103. +
  39104. + }
  39105. +
  39106. +stop_scan:
  39107. +
  39108. + if (qh->ep_type != UE_CONTROL) {
  39109. + /*
  39110. + * Resetting the data toggle for bulk
  39111. + * and interrupt endpoints in case of stall. See handle_hc_stall_intr()
  39112. + */
  39113. + if (halt_status == DWC_OTG_HC_XFER_STALL)
  39114. + qh->data_toggle = DWC_OTG_HC_PID_DATA0;
  39115. + else
  39116. + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
  39117. + }
  39118. +
  39119. + if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
  39120. + hcint_data_t hcint;
  39121. + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
  39122. + if (hcint.b.nyet) {
  39123. + /*
  39124. + * Got a NYET on the last transaction of the transfer. It
  39125. + * means that the endpoint should be in the PING state at the
  39126. + * beginning of the next transfer.
  39127. + */
  39128. + qh->ping_state = 1;
  39129. + clear_hc_int(hc_regs, nyet);
  39130. + }
  39131. +
  39132. + }
  39133. +
  39134. +}
  39135. +
  39136. +/**
  39137. + * This function is called from interrupt handlers.
  39138. + * Scans the descriptor list, updates URB's status and
  39139. + * calls completion routine for the URB if it's done.
  39140. + * Releases the channel to be used by other transfers.
  39141. + * In case of Isochronous endpoint the channel is not halted until
  39142. + * the end of the session, i.e. QTD list is empty.
  39143. + * If periodic channel released the FrameList is updated accordingly.
  39144. + *
  39145. + * Calls transaction selection routines to activate pending transfers.
  39146. + *
  39147. + * @param hcd The HCD state structure for the DWC OTG controller.
  39148. + * @param hc Host channel, the transfer is completed on.
  39149. + * @param hc_regs Host channel registers.
  39150. + * @param halt_status Reason the channel is being halted,
  39151. + * or just XferComplete for isochronous transfer
  39152. + */
  39153. +void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd,
  39154. + dwc_hc_t * hc,
  39155. + dwc_otg_hc_regs_t * hc_regs,
  39156. + dwc_otg_halt_status_e halt_status)
  39157. +{
  39158. + uint8_t continue_isoc_xfer = 0;
  39159. + dwc_otg_transaction_type_e tr_type;
  39160. + dwc_otg_qh_t *qh = hc->qh;
  39161. +
  39162. + if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
  39163. +
  39164. + complete_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status);
  39165. +
  39166. + /* Release the channel if halted or session completed */
  39167. + if (halt_status != DWC_OTG_HC_XFER_COMPLETE ||
  39168. + DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
  39169. +
  39170. + /* Halt the channel if session completed */
  39171. + if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
  39172. + dwc_otg_hc_halt(hcd->core_if, hc, halt_status);
  39173. + }
  39174. +
  39175. + release_channel_ddma(hcd, qh);
  39176. + dwc_otg_hcd_qh_remove(hcd, qh);
  39177. + } else {
  39178. + /* Keep in assigned schedule to continue transfer */
  39179. + DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
  39180. + &qh->qh_list_entry);
  39181. + continue_isoc_xfer = 1;
  39182. +
  39183. + }
  39184. + /** @todo Consider the case when period exceeds FrameList size.
  39185. + * Frame Rollover interrupt should be used.
  39186. + */
  39187. + } else {
  39188. + /* Scan descriptor list to complete the URB(s), then release the channel */
  39189. + complete_non_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status);
  39190. +
  39191. + release_channel_ddma(hcd, qh);
  39192. + dwc_otg_hcd_qh_remove(hcd, qh);
  39193. +
  39194. + if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
  39195. + /* Add back to inactive non-periodic schedule on normal completion */
  39196. + dwc_otg_hcd_qh_add(hcd, qh);
  39197. + }
  39198. +
  39199. + }
  39200. + tr_type = dwc_otg_hcd_select_transactions(hcd);
  39201. + if (tr_type != DWC_OTG_TRANSACTION_NONE || continue_isoc_xfer) {
  39202. + if (continue_isoc_xfer) {
  39203. + if (tr_type == DWC_OTG_TRANSACTION_NONE) {
  39204. + tr_type = DWC_OTG_TRANSACTION_PERIODIC;
  39205. + } else if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC) {
  39206. + tr_type = DWC_OTG_TRANSACTION_ALL;
  39207. + }
  39208. + }
  39209. + dwc_otg_hcd_queue_transactions(hcd, tr_type);
  39210. + }
  39211. +}
  39212. +
  39213. +#endif /* DWC_DEVICE_ONLY */
  39214. --- /dev/null
  39215. +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
  39216. @@ -0,0 +1,412 @@
  39217. +/* ==========================================================================
  39218. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_if.h $
  39219. + * $Revision: #12 $
  39220. + * $Date: 2011/10/26 $
  39221. + * $Change: 1873028 $
  39222. + *
  39223. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  39224. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  39225. + * otherwise expressly agreed to in writing between Synopsys and you.
  39226. + *
  39227. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  39228. + * any End User Software License Agreement or Agreement for Licensed Product
  39229. + * with Synopsys or any supplement thereto. You are permitted to use and
  39230. + * redistribute this Software in source and binary forms, with or without
  39231. + * modification, provided that redistributions of source code must retain this
  39232. + * notice. You may not view, use, disclose, copy or distribute this file or
  39233. + * any information contained herein except pursuant to this license grant from
  39234. + * Synopsys. If you do not agree with this notice, including the disclaimer
  39235. + * below, then you are not authorized to use the Software.
  39236. + *
  39237. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  39238. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  39239. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  39240. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  39241. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  39242. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  39243. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  39244. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  39245. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  39246. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  39247. + * DAMAGE.
  39248. + * ========================================================================== */
  39249. +#ifndef DWC_DEVICE_ONLY
  39250. +#ifndef __DWC_HCD_IF_H__
  39251. +#define __DWC_HCD_IF_H__
  39252. +
  39253. +#include "dwc_otg_core_if.h"
  39254. +
  39255. +/** @file
  39256. + * This file defines DWC_OTG HCD Core API.
  39257. + */
  39258. +
  39259. +struct dwc_otg_hcd;
  39260. +typedef struct dwc_otg_hcd dwc_otg_hcd_t;
  39261. +
  39262. +struct dwc_otg_hcd_urb;
  39263. +typedef struct dwc_otg_hcd_urb dwc_otg_hcd_urb_t;
  39264. +
  39265. +/** @name HCD Function Driver Callbacks */
  39266. +/** @{ */
  39267. +
  39268. +/** This function is called whenever core switches to host mode. */
  39269. +typedef int (*dwc_otg_hcd_start_cb_t) (dwc_otg_hcd_t * hcd);
  39270. +
  39271. +/** This function is called when device has been disconnected */
  39272. +typedef int (*dwc_otg_hcd_disconnect_cb_t) (dwc_otg_hcd_t * hcd);
  39273. +
  39274. +/** Wrapper provides this function to HCD to core, so it can get hub information to which device is connected */
  39275. +typedef int (*dwc_otg_hcd_hub_info_from_urb_cb_t) (dwc_otg_hcd_t * hcd,
  39276. + void *urb_handle,
  39277. + uint32_t * hub_addr,
  39278. + uint32_t * port_addr);
  39279. +/** Via this function HCD core gets device speed */
  39280. +typedef int (*dwc_otg_hcd_speed_from_urb_cb_t) (dwc_otg_hcd_t * hcd,
  39281. + void *urb_handle);
  39282. +
  39283. +/** This function is called when urb is completed */
  39284. +typedef int (*dwc_otg_hcd_complete_urb_cb_t) (dwc_otg_hcd_t * hcd,
  39285. + void *urb_handle,
  39286. + dwc_otg_hcd_urb_t * dwc_otg_urb,
  39287. + int32_t status);
  39288. +
  39289. +/** Via this function HCD core gets b_hnp_enable parameter */
  39290. +typedef int (*dwc_otg_hcd_get_b_hnp_enable) (dwc_otg_hcd_t * hcd);
  39291. +
  39292. +struct dwc_otg_hcd_function_ops {
  39293. + dwc_otg_hcd_start_cb_t start;
  39294. + dwc_otg_hcd_disconnect_cb_t disconnect;
  39295. + dwc_otg_hcd_hub_info_from_urb_cb_t hub_info;
  39296. + dwc_otg_hcd_speed_from_urb_cb_t speed;
  39297. + dwc_otg_hcd_complete_urb_cb_t complete;
  39298. + dwc_otg_hcd_get_b_hnp_enable get_b_hnp_enable;
  39299. +};
  39300. +/** @} */
  39301. +
  39302. +/** @name HCD Core API */
  39303. +/** @{ */
  39304. +/** This function allocates dwc_otg_hcd structure and returns pointer on it. */
  39305. +extern dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void);
  39306. +
  39307. +/** This function should be called to initiate HCD Core.
  39308. + *
  39309. + * @param hcd The HCD
  39310. + * @param core_if The DWC_OTG Core
  39311. + *
  39312. + * Returns -DWC_E_NO_MEMORY if no enough memory.
  39313. + * Returns 0 on success
  39314. + */
  39315. +extern int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if);
  39316. +
  39317. +/** Frees HCD
  39318. + *
  39319. + * @param hcd The HCD
  39320. + */
  39321. +extern void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd);
  39322. +
  39323. +/** This function should be called on every hardware interrupt.
  39324. + *
  39325. + * @param dwc_otg_hcd The HCD
  39326. + *
  39327. + * Returns non zero if interrupt is handled
  39328. + * Return 0 if interrupt is not handled
  39329. + */
  39330. +extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd);
  39331. +
  39332. +/**
  39333. + * Returns private data set by
  39334. + * dwc_otg_hcd_set_priv_data function.
  39335. + *
  39336. + * @param hcd The HCD
  39337. + */
  39338. +extern void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd);
  39339. +
  39340. +/**
  39341. + * Set private data.
  39342. + *
  39343. + * @param hcd The HCD
  39344. + * @param priv_data pointer to be stored in private data
  39345. + */
  39346. +extern void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data);
  39347. +
  39348. +/**
  39349. + * This function initializes the HCD Core.
  39350. + *
  39351. + * @param hcd The HCD
  39352. + * @param fops The Function Driver Operations data structure containing pointers to all callbacks.
  39353. + *
  39354. + * Returns -DWC_E_NO_DEVICE if Core is currently is in device mode.
  39355. + * Returns 0 on success
  39356. + */
  39357. +extern int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd,
  39358. + struct dwc_otg_hcd_function_ops *fops);
  39359. +
  39360. +/**
  39361. + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
  39362. + * stopped.
  39363. + *
  39364. + * @param hcd The HCD
  39365. + */
  39366. +extern void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd);
  39367. +
  39368. +/**
  39369. + * Handles hub class-specific requests.
  39370. + *
  39371. + * @param dwc_otg_hcd The HCD
  39372. + * @param typeReq Request Type
  39373. + * @param wValue wValue from control request
  39374. + * @param wIndex wIndex from control request
  39375. + * @param buf data buffer
  39376. + * @param wLength data buffer length
  39377. + *
  39378. + * Returns -DWC_E_INVALID if invalid argument is passed
  39379. + * Returns 0 on success
  39380. + */
  39381. +extern int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd,
  39382. + uint16_t typeReq, uint16_t wValue,
  39383. + uint16_t wIndex, uint8_t * buf,
  39384. + uint16_t wLength);
  39385. +
  39386. +/**
  39387. + * Returns otg port number.
  39388. + *
  39389. + * @param hcd The HCD
  39390. + */
  39391. +extern uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd);
  39392. +
  39393. +/**
  39394. + * Returns OTG version - either 1.3 or 2.0.
  39395. + *
  39396. + * @param core_if The core_if structure pointer
  39397. + */
  39398. +extern uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if);
  39399. +
  39400. +/**
  39401. + * Returns 1 if currently core is acting as B host, and 0 otherwise.
  39402. + *
  39403. + * @param hcd The HCD
  39404. + */
  39405. +extern uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd);
  39406. +
  39407. +/**
  39408. + * Returns current frame number.
  39409. + *
  39410. + * @param hcd The HCD
  39411. + */
  39412. +extern int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * hcd);
  39413. +
  39414. +/**
  39415. + * Dumps hcd state.
  39416. + *
  39417. + * @param hcd The HCD
  39418. + */
  39419. +extern void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd);
  39420. +
  39421. +/**
  39422. + * Dump the average frame remaining at SOF. This can be used to
  39423. + * determine average interrupt latency. Frame remaining is also shown for
  39424. + * start transfer and two additional sample points.
  39425. + * Currently this function is not implemented.
  39426. + *
  39427. + * @param hcd The HCD
  39428. + */
  39429. +extern void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd);
  39430. +
  39431. +/**
  39432. + * Sends LPM transaction to the local device.
  39433. + *
  39434. + * @param hcd The HCD
  39435. + * @param devaddr Device Address
  39436. + * @param hird Host initiated resume duration
  39437. + * @param bRemoteWake Value of bRemoteWake field in LPM transaction
  39438. + *
  39439. + * Returns negative value if sending LPM transaction was not succeeded.
  39440. + * Returns 0 on success.
  39441. + */
  39442. +extern int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr,
  39443. + uint8_t hird, uint8_t bRemoteWake);
  39444. +
  39445. +/* URB interface */
  39446. +
  39447. +/**
  39448. + * Allocates memory for dwc_otg_hcd_urb structure.
  39449. + * Allocated memory should be freed by call of DWC_FREE.
  39450. + *
  39451. + * @param hcd The HCD
  39452. + * @param iso_desc_count Count of ISOC descriptors
  39453. + * @param atomic_alloc Specefies whether to perform atomic allocation.
  39454. + */
  39455. +extern dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd,
  39456. + int iso_desc_count,
  39457. + int atomic_alloc);
  39458. +
  39459. +/**
  39460. + * Set pipe information in URB.
  39461. + *
  39462. + * @param hcd_urb DWC_OTG URB
  39463. + * @param devaddr Device Address
  39464. + * @param ep_num Endpoint Number
  39465. + * @param ep_type Endpoint Type
  39466. + * @param ep_dir Endpoint Direction
  39467. + * @param mps Max Packet Size
  39468. + */
  39469. +extern void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * hcd_urb,
  39470. + uint8_t devaddr, uint8_t ep_num,
  39471. + uint8_t ep_type, uint8_t ep_dir,
  39472. + uint16_t mps);
  39473. +
  39474. +/* Transfer flags */
  39475. +#define URB_GIVEBACK_ASAP 0x1
  39476. +#define URB_SEND_ZERO_PACKET 0x2
  39477. +
  39478. +/**
  39479. + * Sets dwc_otg_hcd_urb parameters.
  39480. + *
  39481. + * @param urb DWC_OTG URB allocated by dwc_otg_hcd_urb_alloc function.
  39482. + * @param urb_handle Unique handle for request, this will be passed back
  39483. + * to function driver in completion callback.
  39484. + * @param buf The buffer for the data
  39485. + * @param dma The DMA buffer for the data
  39486. + * @param buflen Transfer length
  39487. + * @param sp Buffer for setup data
  39488. + * @param sp_dma DMA address of setup data buffer
  39489. + * @param flags Transfer flags
  39490. + * @param interval Polling interval for interrupt or isochronous transfers.
  39491. + */
  39492. +extern void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * urb,
  39493. + void *urb_handle, void *buf,
  39494. + dwc_dma_t dma, uint32_t buflen, void *sp,
  39495. + dwc_dma_t sp_dma, uint32_t flags,
  39496. + uint16_t interval);
  39497. +
  39498. +/** Gets status from dwc_otg_hcd_urb
  39499. + *
  39500. + * @param dwc_otg_urb DWC_OTG URB
  39501. + */
  39502. +extern uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb);
  39503. +
  39504. +/** Gets actual length from dwc_otg_hcd_urb
  39505. + *
  39506. + * @param dwc_otg_urb DWC_OTG URB
  39507. + */
  39508. +extern uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t *
  39509. + dwc_otg_urb);
  39510. +
  39511. +/** Gets error count from dwc_otg_hcd_urb. Only for ISOC URBs
  39512. + *
  39513. + * @param dwc_otg_urb DWC_OTG URB
  39514. + */
  39515. +extern uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t *
  39516. + dwc_otg_urb);
  39517. +
  39518. +/** Set ISOC descriptor offset and length
  39519. + *
  39520. + * @param dwc_otg_urb DWC_OTG URB
  39521. + * @param desc_num ISOC descriptor number
  39522. + * @param offset Offset from beginig of buffer.
  39523. + * @param length Transaction length
  39524. + */
  39525. +extern void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb,
  39526. + int desc_num, uint32_t offset,
  39527. + uint32_t length);
  39528. +
  39529. +/** Get status of ISOC descriptor, specified by desc_num
  39530. + *
  39531. + * @param dwc_otg_urb DWC_OTG URB
  39532. + * @param desc_num ISOC descriptor number
  39533. + */
  39534. +extern uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t *
  39535. + dwc_otg_urb, int desc_num);
  39536. +
  39537. +/** Get actual length of ISOC descriptor, specified by desc_num
  39538. + *
  39539. + * @param dwc_otg_urb DWC_OTG URB
  39540. + * @param desc_num ISOC descriptor number
  39541. + */
  39542. +extern uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t *
  39543. + dwc_otg_urb,
  39544. + int desc_num);
  39545. +
  39546. +/** Queue URB. After transfer is completes, the complete callback will be called with the URB status
  39547. + *
  39548. + * @param dwc_otg_hcd The HCD
  39549. + * @param dwc_otg_urb DWC_OTG URB
  39550. + * @param ep_handle Out parameter for returning endpoint handle
  39551. + * @param atomic_alloc Flag to do atomic allocation if needed
  39552. + *
  39553. + * Returns -DWC_E_NO_DEVICE if no device is connected.
  39554. + * Returns -DWC_E_NO_MEMORY if there is no enough memory.
  39555. + * Returns 0 on success.
  39556. + */
  39557. +extern int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * dwc_otg_hcd,
  39558. + dwc_otg_hcd_urb_t * dwc_otg_urb,
  39559. + void **ep_handle, int atomic_alloc);
  39560. +
  39561. +/** De-queue the specified URB
  39562. + *
  39563. + * @param dwc_otg_hcd The HCD
  39564. + * @param dwc_otg_urb DWC_OTG URB
  39565. + */
  39566. +extern int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * dwc_otg_hcd,
  39567. + dwc_otg_hcd_urb_t * dwc_otg_urb);
  39568. +
  39569. +/** Frees resources in the DWC_otg controller related to a given endpoint.
  39570. + * Any URBs for the endpoint must already be dequeued.
  39571. + *
  39572. + * @param hcd The HCD
  39573. + * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function
  39574. + * @param retry Number of retries if there are queued transfers.
  39575. + *
  39576. + * Returns -DWC_E_INVALID if invalid arguments are passed.
  39577. + * Returns 0 on success
  39578. + */
  39579. +extern int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle,
  39580. + int retry);
  39581. +
  39582. +/* Resets the data toggle in qh structure. This function can be called from
  39583. + * usb_clear_halt routine.
  39584. + *
  39585. + * @param hcd The HCD
  39586. + * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function
  39587. + *
  39588. + * Returns -DWC_E_INVALID if invalid arguments are passed.
  39589. + * Returns 0 on success
  39590. + */
  39591. +extern int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle);
  39592. +
  39593. +/** Returns 1 if status of specified port is changed and 0 otherwise.
  39594. + *
  39595. + * @param hcd The HCD
  39596. + * @param port Port number
  39597. + */
  39598. +extern int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port);
  39599. +
  39600. +/** Call this function to check if bandwidth was allocated for specified endpoint.
  39601. + * Only for ISOC and INTERRUPT endpoints.
  39602. + *
  39603. + * @param hcd The HCD
  39604. + * @param ep_handle Endpoint handle
  39605. + */
  39606. +extern int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd,
  39607. + void *ep_handle);
  39608. +
  39609. +/** Call this function to check if bandwidth was freed for specified endpoint.
  39610. + *
  39611. + * @param hcd The HCD
  39612. + * @param ep_handle Endpoint handle
  39613. + */
  39614. +extern int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle);
  39615. +
  39616. +/** Returns bandwidth allocated for specified endpoint in microseconds.
  39617. + * Only for ISOC and INTERRUPT endpoints.
  39618. + *
  39619. + * @param hcd The HCD
  39620. + * @param ep_handle Endpoint handle
  39621. + */
  39622. +extern uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd,
  39623. + void *ep_handle);
  39624. +
  39625. +/** @} */
  39626. +
  39627. +#endif /* __DWC_HCD_IF_H__ */
  39628. +#endif /* DWC_DEVICE_ONLY */
  39629. --- /dev/null
  39630. +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
  39631. @@ -0,0 +1,2106 @@
  39632. +/* ==========================================================================
  39633. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $
  39634. + * $Revision: #89 $
  39635. + * $Date: 2011/10/20 $
  39636. + * $Change: 1869487 $
  39637. + *
  39638. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  39639. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  39640. + * otherwise expressly agreed to in writing between Synopsys and you.
  39641. + *
  39642. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  39643. + * any End User Software License Agreement or Agreement for Licensed Product
  39644. + * with Synopsys or any supplement thereto. You are permitted to use and
  39645. + * redistribute this Software in source and binary forms, with or without
  39646. + * modification, provided that redistributions of source code must retain this
  39647. + * notice. You may not view, use, disclose, copy or distribute this file or
  39648. + * any information contained herein except pursuant to this license grant from
  39649. + * Synopsys. If you do not agree with this notice, including the disclaimer
  39650. + * below, then you are not authorized to use the Software.
  39651. + *
  39652. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  39653. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  39654. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  39655. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  39656. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  39657. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  39658. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  39659. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  39660. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  39661. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  39662. + * DAMAGE.
  39663. + * ========================================================================== */
  39664. +#ifndef DWC_DEVICE_ONLY
  39665. +
  39666. +#include "dwc_otg_hcd.h"
  39667. +#include "dwc_otg_regs.h"
  39668. +
  39669. +extern bool microframe_schedule;
  39670. +
  39671. +/** @file
  39672. + * This file contains the implementation of the HCD Interrupt handlers.
  39673. + */
  39674. +
  39675. +/** This function handles interrupts for the HCD. */
  39676. +int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
  39677. +{
  39678. + int retval = 0;
  39679. +
  39680. + dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
  39681. + gintsts_data_t gintsts;
  39682. +#ifdef DEBUG
  39683. + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
  39684. +
  39685. + //GRAYG: debugging
  39686. + if (NULL == global_regs) {
  39687. + DWC_DEBUGPL(DBG_HCD, "**** NULL regs: dwc_otg_hcd=%p "
  39688. + "core_if=%p\n",
  39689. + dwc_otg_hcd, global_regs);
  39690. + return retval;
  39691. + }
  39692. +#endif
  39693. +
  39694. + /* Exit from ISR if core is hibernated */
  39695. + if (core_if->hibernation_suspend == 1) {
  39696. + return retval;
  39697. + }
  39698. + DWC_SPINLOCK(dwc_otg_hcd->lock);
  39699. + /* Check if HOST Mode */
  39700. + if (dwc_otg_is_host_mode(core_if)) {
  39701. + gintsts.d32 = dwc_otg_read_core_intr(core_if);
  39702. + if (!gintsts.d32) {
  39703. + DWC_SPINUNLOCK(dwc_otg_hcd->lock);
  39704. + return 0;
  39705. + }
  39706. +#ifdef DEBUG
  39707. + /* Don't print debug message in the interrupt handler on SOF */
  39708. +#ifndef DEBUG_SOF
  39709. + if (gintsts.d32 != DWC_SOF_INTR_MASK)
  39710. +#endif
  39711. + DWC_DEBUGPL(DBG_HCDI, "\n");
  39712. +#endif
  39713. +
  39714. +#ifdef DEBUG
  39715. +#ifndef DEBUG_SOF
  39716. + if (gintsts.d32 != DWC_SOF_INTR_MASK)
  39717. +#endif
  39718. + DWC_DEBUGPL(DBG_HCDI,
  39719. + "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x core_if=%p\n",
  39720. + gintsts.d32, core_if);
  39721. +#endif
  39722. +
  39723. + if (gintsts.b.sofintr) {
  39724. + retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
  39725. + }
  39726. + if (gintsts.b.rxstsqlvl) {
  39727. + retval |=
  39728. + dwc_otg_hcd_handle_rx_status_q_level_intr
  39729. + (dwc_otg_hcd);
  39730. + }
  39731. + if (gintsts.b.nptxfempty) {
  39732. + retval |=
  39733. + dwc_otg_hcd_handle_np_tx_fifo_empty_intr
  39734. + (dwc_otg_hcd);
  39735. + }
  39736. + if (gintsts.b.i2cintr) {
  39737. + /** @todo Implement i2cintr handler. */
  39738. + }
  39739. + if (gintsts.b.portintr) {
  39740. + retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd);
  39741. + }
  39742. + if (gintsts.b.hcintr) {
  39743. + retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd);
  39744. + }
  39745. + if (gintsts.b.ptxfempty) {
  39746. + retval |=
  39747. + dwc_otg_hcd_handle_perio_tx_fifo_empty_intr
  39748. + (dwc_otg_hcd);
  39749. + }
  39750. +#ifdef DEBUG
  39751. +#ifndef DEBUG_SOF
  39752. + if (gintsts.d32 != DWC_SOF_INTR_MASK)
  39753. +#endif
  39754. + {
  39755. + DWC_DEBUGPL(DBG_HCDI,
  39756. + "DWC OTG HCD Finished Servicing Interrupts\n");
  39757. + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintsts=0x%08x\n",
  39758. + DWC_READ_REG32(&global_regs->gintsts));
  39759. + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintmsk=0x%08x\n",
  39760. + DWC_READ_REG32(&global_regs->gintmsk));
  39761. + }
  39762. +#endif
  39763. +
  39764. +#ifdef DEBUG
  39765. +#ifndef DEBUG_SOF
  39766. + if (gintsts.d32 != DWC_SOF_INTR_MASK)
  39767. +#endif
  39768. + DWC_DEBUGPL(DBG_HCDI, "\n");
  39769. +#endif
  39770. +
  39771. + }
  39772. + DWC_SPINUNLOCK(dwc_otg_hcd->lock);
  39773. + return retval;
  39774. +}
  39775. +
  39776. +#ifdef DWC_TRACK_MISSED_SOFS
  39777. +#warning Compiling code to track missed SOFs
  39778. +#define FRAME_NUM_ARRAY_SIZE 1000
  39779. +/**
  39780. + * This function is for debug only.
  39781. + */
  39782. +static inline void track_missed_sofs(uint16_t curr_frame_number)
  39783. +{
  39784. + static uint16_t frame_num_array[FRAME_NUM_ARRAY_SIZE];
  39785. + static uint16_t last_frame_num_array[FRAME_NUM_ARRAY_SIZE];
  39786. + static int frame_num_idx = 0;
  39787. + static uint16_t last_frame_num = DWC_HFNUM_MAX_FRNUM;
  39788. + static int dumped_frame_num_array = 0;
  39789. +
  39790. + if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) {
  39791. + if (((last_frame_num + 1) & DWC_HFNUM_MAX_FRNUM) !=
  39792. + curr_frame_number) {
  39793. + frame_num_array[frame_num_idx] = curr_frame_number;
  39794. + last_frame_num_array[frame_num_idx++] = last_frame_num;
  39795. + }
  39796. + } else if (!dumped_frame_num_array) {
  39797. + int i;
  39798. + DWC_PRINTF("Frame Last Frame\n");
  39799. + DWC_PRINTF("----- ----------\n");
  39800. + for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) {
  39801. + DWC_PRINTF("0x%04x 0x%04x\n",
  39802. + frame_num_array[i], last_frame_num_array[i]);
  39803. + }
  39804. + dumped_frame_num_array = 1;
  39805. + }
  39806. + last_frame_num = curr_frame_number;
  39807. +}
  39808. +#endif
  39809. +
  39810. +/**
  39811. + * Handles the start-of-frame interrupt in host mode. Non-periodic
  39812. + * transactions may be queued to the DWC_otg controller for the current
  39813. + * (micro)frame. Periodic transactions may be queued to the controller for the
  39814. + * next (micro)frame.
  39815. + */
  39816. +int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
  39817. +{
  39818. + hfnum_data_t hfnum;
  39819. + dwc_list_link_t *qh_entry;
  39820. + dwc_otg_qh_t *qh;
  39821. + dwc_otg_transaction_type_e tr_type;
  39822. + gintsts_data_t gintsts = {.d32 = 0 };
  39823. +
  39824. + hfnum.d32 =
  39825. + DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);
  39826. +
  39827. +#ifdef DEBUG_SOF
  39828. + DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n");
  39829. +#endif
  39830. + hcd->frame_number = hfnum.b.frnum;
  39831. +
  39832. +#ifdef DEBUG
  39833. + hcd->frrem_accum += hfnum.b.frrem;
  39834. + hcd->frrem_samples++;
  39835. +#endif
  39836. +
  39837. +#ifdef DWC_TRACK_MISSED_SOFS
  39838. + track_missed_sofs(hcd->frame_number);
  39839. +#endif
  39840. + /* Determine whether any periodic QHs should be executed. */
  39841. + qh_entry = DWC_LIST_FIRST(&hcd->periodic_sched_inactive);
  39842. + while (qh_entry != &hcd->periodic_sched_inactive) {
  39843. + qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry);
  39844. + qh_entry = qh_entry->next;
  39845. + if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) {
  39846. + /*
  39847. + * Move QH to the ready list to be executed next
  39848. + * (micro)frame.
  39849. + */
  39850. + DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
  39851. + &qh->qh_list_entry);
  39852. + }
  39853. + }
  39854. + tr_type = dwc_otg_hcd_select_transactions(hcd);
  39855. + if (tr_type != DWC_OTG_TRANSACTION_NONE) {
  39856. + dwc_otg_hcd_queue_transactions(hcd, tr_type);
  39857. + }
  39858. +
  39859. + /* Clear interrupt */
  39860. + gintsts.b.sofintr = 1;
  39861. + DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32);
  39862. +
  39863. + return 1;
  39864. +}
  39865. +
  39866. +/** Handles the Rx Status Queue Level Interrupt, which indicates that there is at
  39867. + * least one packet in the Rx FIFO. The packets are moved from the FIFO to
  39868. + * memory if the DWC_otg controller is operating in Slave mode. */
  39869. +int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * dwc_otg_hcd)
  39870. +{
  39871. + host_grxsts_data_t grxsts;
  39872. + dwc_hc_t *hc = NULL;
  39873. +
  39874. + DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n");
  39875. +
  39876. + grxsts.d32 =
  39877. + DWC_READ_REG32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp);
  39878. +
  39879. + hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum];
  39880. + if (!hc) {
  39881. + DWC_ERROR("Unable to get corresponding channel\n");
  39882. + return 0;
  39883. + }
  39884. +
  39885. + /* Packet Status */
  39886. + DWC_DEBUGPL(DBG_HCDV, " Ch num = %d\n", grxsts.b.chnum);
  39887. + DWC_DEBUGPL(DBG_HCDV, " Count = %d\n", grxsts.b.bcnt);
  39888. + DWC_DEBUGPL(DBG_HCDV, " DPID = %d, hc.dpid = %d\n", grxsts.b.dpid,
  39889. + hc->data_pid_start);
  39890. + DWC_DEBUGPL(DBG_HCDV, " PStatus = %d\n", grxsts.b.pktsts);
  39891. +
  39892. + switch (grxsts.b.pktsts) {
  39893. + case DWC_GRXSTS_PKTSTS_IN:
  39894. + /* Read the data into the host buffer. */
  39895. + if (grxsts.b.bcnt > 0) {
  39896. + dwc_otg_read_packet(dwc_otg_hcd->core_if,
  39897. + hc->xfer_buff, grxsts.b.bcnt);
  39898. +
  39899. + /* Update the HC fields for the next packet received. */
  39900. + hc->xfer_count += grxsts.b.bcnt;
  39901. + hc->xfer_buff += grxsts.b.bcnt;
  39902. + }
  39903. +
  39904. + case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
  39905. + case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
  39906. + case DWC_GRXSTS_PKTSTS_CH_HALTED:
  39907. + /* Handled in interrupt, just ignore data */
  39908. + break;
  39909. + default:
  39910. + DWC_ERROR("RX_STS_Q Interrupt: Unknown status %d\n",
  39911. + grxsts.b.pktsts);
  39912. + break;
  39913. + }
  39914. +
  39915. + return 1;
  39916. +}
  39917. +
  39918. +/** This interrupt occurs when the non-periodic Tx FIFO is half-empty. More
  39919. + * data packets may be written to the FIFO for OUT transfers. More requests
  39920. + * may be written to the non-periodic request queue for IN transfers. This
  39921. + * interrupt is enabled only in Slave mode. */
  39922. +int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)
  39923. +{
  39924. + DWC_DEBUGPL(DBG_HCD, "--Non-Periodic TxFIFO Empty Interrupt--\n");
  39925. + dwc_otg_hcd_queue_transactions(dwc_otg_hcd,
  39926. + DWC_OTG_TRANSACTION_NON_PERIODIC);
  39927. + return 1;
  39928. +}
  39929. +
  39930. +/** This interrupt occurs when the periodic Tx FIFO is half-empty. More data
  39931. + * packets may be written to the FIFO for OUT transfers. More requests may be
  39932. + * written to the periodic request queue for IN transfers. This interrupt is
  39933. + * enabled only in Slave mode. */
  39934. +int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)
  39935. +{
  39936. + DWC_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n");
  39937. + dwc_otg_hcd_queue_transactions(dwc_otg_hcd,
  39938. + DWC_OTG_TRANSACTION_PERIODIC);
  39939. + return 1;
  39940. +}
  39941. +
  39942. +/** There are multiple conditions that can cause a port interrupt. This function
  39943. + * determines which interrupt conditions have occurred and handles them
  39944. + * appropriately. */
  39945. +int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd)
  39946. +{
  39947. + int retval = 0;
  39948. + hprt0_data_t hprt0;
  39949. + hprt0_data_t hprt0_modify;
  39950. +
  39951. + hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
  39952. + hprt0_modify.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
  39953. +
  39954. + /* Clear appropriate bits in HPRT0 to clear the interrupt bit in
  39955. + * GINTSTS */
  39956. +
  39957. + hprt0_modify.b.prtena = 0;
  39958. + hprt0_modify.b.prtconndet = 0;
  39959. + hprt0_modify.b.prtenchng = 0;
  39960. + hprt0_modify.b.prtovrcurrchng = 0;
  39961. +
  39962. + /* Port Connect Detected
  39963. + * Set flag and clear if detected */
  39964. + if (dwc_otg_hcd->core_if->hibernation_suspend == 1) {
  39965. + // Dont modify port status if we are in hibernation state
  39966. + hprt0_modify.b.prtconndet = 1;
  39967. + hprt0_modify.b.prtenchng = 1;
  39968. + DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32);
  39969. + hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
  39970. + return retval;
  39971. + }
  39972. +
  39973. + if (hprt0.b.prtconndet) {
  39974. + /** @todo - check if steps performed in 'else' block should be perfromed regardles adp */
  39975. + if (dwc_otg_hcd->core_if->adp_enable &&
  39976. + dwc_otg_hcd->core_if->adp.vbuson_timer_started == 1) {
  39977. + DWC_PRINTF("PORT CONNECT DETECTED ----------------\n");
  39978. + DWC_TIMER_CANCEL(dwc_otg_hcd->core_if->adp.vbuson_timer);
  39979. + dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0;
  39980. + /* TODO - check if this is required, as
  39981. + * host initialization was already performed
  39982. + * after initial ADP probing
  39983. + */
  39984. + /*dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0;
  39985. + dwc_otg_core_init(dwc_otg_hcd->core_if);
  39986. + dwc_otg_enable_global_interrupts(dwc_otg_hcd->core_if);
  39987. + cil_hcd_start(dwc_otg_hcd->core_if);*/
  39988. + } else {
  39989. +
  39990. + DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x "
  39991. + "Port Connect Detected--\n", hprt0.d32);
  39992. + dwc_otg_hcd->flags.b.port_connect_status_change = 1;
  39993. + dwc_otg_hcd->flags.b.port_connect_status = 1;
  39994. + hprt0_modify.b.prtconndet = 1;
  39995. +
  39996. + /* B-Device has connected, Delete the connection timer. */
  39997. + DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer);
  39998. + }
  39999. + /* The Hub driver asserts a reset when it sees port connect
  40000. + * status change flag */
  40001. + retval |= 1;
  40002. + }
  40003. +
  40004. + /* Port Enable Changed
  40005. + * Clear if detected - Set internal flag if disabled */
  40006. + if (hprt0.b.prtenchng) {
  40007. + DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x "
  40008. + "Port Enable Changed--\n", hprt0.d32);
  40009. + hprt0_modify.b.prtenchng = 1;
  40010. + if (hprt0.b.prtena == 1) {
  40011. + hfir_data_t hfir;
  40012. + int do_reset = 0;
  40013. + dwc_otg_core_params_t *params =
  40014. + dwc_otg_hcd->core_if->core_params;
  40015. + dwc_otg_core_global_regs_t *global_regs =
  40016. + dwc_otg_hcd->core_if->core_global_regs;
  40017. + dwc_otg_host_if_t *host_if =
  40018. + dwc_otg_hcd->core_if->host_if;
  40019. +
  40020. + /* Every time when port enables calculate
  40021. + * HFIR.FrInterval
  40022. + */
  40023. + hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir);
  40024. + hfir.b.frint = calc_frame_interval(dwc_otg_hcd->core_if);
  40025. + DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32);
  40026. +
  40027. + /* Check if we need to adjust the PHY clock speed for
  40028. + * low power and adjust it */
  40029. + if (params->host_support_fs_ls_low_power) {
  40030. + gusbcfg_data_t usbcfg;
  40031. +
  40032. + usbcfg.d32 =
  40033. + DWC_READ_REG32(&global_regs->gusbcfg);
  40034. +
  40035. + if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED
  40036. + || hprt0.b.prtspd ==
  40037. + DWC_HPRT0_PRTSPD_FULL_SPEED) {
  40038. + /*
  40039. + * Low power
  40040. + */
  40041. + hcfg_data_t hcfg;
  40042. + if (usbcfg.b.phylpwrclksel == 0) {
  40043. + /* Set PHY low power clock select for FS/LS devices */
  40044. + usbcfg.b.phylpwrclksel = 1;
  40045. + DWC_WRITE_REG32
  40046. + (&global_regs->gusbcfg,
  40047. + usbcfg.d32);
  40048. + do_reset = 1;
  40049. + }
  40050. +
  40051. + hcfg.d32 =
  40052. + DWC_READ_REG32
  40053. + (&host_if->host_global_regs->hcfg);
  40054. +
  40055. + if (hprt0.b.prtspd ==
  40056. + DWC_HPRT0_PRTSPD_LOW_SPEED
  40057. + && params->host_ls_low_power_phy_clk
  40058. + ==
  40059. + DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)
  40060. + {
  40061. + /* 6 MHZ */
  40062. + DWC_DEBUGPL(DBG_CIL,
  40063. + "FS_PHY programming HCFG to 6 MHz (Low Power)\n");
  40064. + if (hcfg.b.fslspclksel !=
  40065. + DWC_HCFG_6_MHZ) {
  40066. + hcfg.b.fslspclksel =
  40067. + DWC_HCFG_6_MHZ;
  40068. + DWC_WRITE_REG32
  40069. + (&host_if->host_global_regs->hcfg,
  40070. + hcfg.d32);
  40071. + do_reset = 1;
  40072. + }
  40073. + } else {
  40074. + /* 48 MHZ */
  40075. + DWC_DEBUGPL(DBG_CIL,
  40076. + "FS_PHY programming HCFG to 48 MHz ()\n");
  40077. + if (hcfg.b.fslspclksel !=
  40078. + DWC_HCFG_48_MHZ) {
  40079. + hcfg.b.fslspclksel =
  40080. + DWC_HCFG_48_MHZ;
  40081. + DWC_WRITE_REG32
  40082. + (&host_if->host_global_regs->hcfg,
  40083. + hcfg.d32);
  40084. + do_reset = 1;
  40085. + }
  40086. + }
  40087. + } else {
  40088. + /*
  40089. + * Not low power
  40090. + */
  40091. + if (usbcfg.b.phylpwrclksel == 1) {
  40092. + usbcfg.b.phylpwrclksel = 0;
  40093. + DWC_WRITE_REG32
  40094. + (&global_regs->gusbcfg,
  40095. + usbcfg.d32);
  40096. + do_reset = 1;
  40097. + }
  40098. + }
  40099. +
  40100. + if (do_reset) {
  40101. + DWC_TASK_SCHEDULE(dwc_otg_hcd->reset_tasklet);
  40102. + }
  40103. + }
  40104. +
  40105. + if (!do_reset) {
  40106. + /* Port has been enabled set the reset change flag */
  40107. + dwc_otg_hcd->flags.b.port_reset_change = 1;
  40108. + }
  40109. + } else {
  40110. + dwc_otg_hcd->flags.b.port_enable_change = 1;
  40111. + }
  40112. + retval |= 1;
  40113. + }
  40114. +
  40115. + /** Overcurrent Change Interrupt */
  40116. + if (hprt0.b.prtovrcurrchng) {
  40117. + DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x "
  40118. + "Port Overcurrent Changed--\n", hprt0.d32);
  40119. + dwc_otg_hcd->flags.b.port_over_current_change = 1;
  40120. + hprt0_modify.b.prtovrcurrchng = 1;
  40121. + retval |= 1;
  40122. + }
  40123. +
  40124. + /* Clear Port Interrupts */
  40125. + DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32);
  40126. +
  40127. + return retval;
  40128. +}
  40129. +
  40130. +/** This interrupt indicates that one or more host channels has a pending
  40131. + * interrupt. There are multiple conditions that can cause each host channel
  40132. + * interrupt. This function determines which conditions have occurred for each
  40133. + * host channel interrupt and handles them appropriately. */
  40134. +int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd)
  40135. +{
  40136. + int i;
  40137. + int retval = 0;
  40138. + haint_data_t haint;
  40139. +
  40140. + /* Clear appropriate bits in HCINTn to clear the interrupt bit in
  40141. + * GINTSTS */
  40142. +
  40143. + haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if);
  40144. +
  40145. + for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) {
  40146. + if (haint.b2.chint & (1 << i)) {
  40147. + retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i);
  40148. + }
  40149. + }
  40150. +
  40151. + return retval;
  40152. +}
  40153. +
  40154. +/**
  40155. + * Gets the actual length of a transfer after the transfer halts. _halt_status
  40156. + * holds the reason for the halt.
  40157. + *
  40158. + * For IN transfers where halt_status is DWC_OTG_HC_XFER_COMPLETE,
  40159. + * *short_read is set to 1 upon return if less than the requested
  40160. + * number of bytes were transferred. Otherwise, *short_read is set to 0 upon
  40161. + * return. short_read may also be NULL on entry, in which case it remains
  40162. + * unchanged.
  40163. + */
  40164. +static uint32_t get_actual_xfer_length(dwc_hc_t * hc,
  40165. + dwc_otg_hc_regs_t * hc_regs,
  40166. + dwc_otg_qtd_t * qtd,
  40167. + dwc_otg_halt_status_e halt_status,
  40168. + int *short_read)
  40169. +{
  40170. + hctsiz_data_t hctsiz;
  40171. + uint32_t length;
  40172. +
  40173. + if (short_read != NULL) {
  40174. + *short_read = 0;
  40175. + }
  40176. + hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
  40177. +
  40178. + if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
  40179. + if (hc->ep_is_in) {
  40180. + length = hc->xfer_len - hctsiz.b.xfersize;
  40181. + if (short_read != NULL) {
  40182. + *short_read = (hctsiz.b.xfersize != 0);
  40183. + }
  40184. + } else if (hc->qh->do_split) {
  40185. + length = qtd->ssplit_out_xfer_count;
  40186. + } else {
  40187. + length = hc->xfer_len;
  40188. + }
  40189. + } else {
  40190. + /*
  40191. + * Must use the hctsiz.pktcnt field to determine how much data
  40192. + * has been transferred. This field reflects the number of
  40193. + * packets that have been transferred via the USB. This is
  40194. + * always an integral number of packets if the transfer was
  40195. + * halted before its normal completion. (Can't use the
  40196. + * hctsiz.xfersize field because that reflects the number of
  40197. + * bytes transferred via the AHB, not the USB).
  40198. + */
  40199. + length =
  40200. + (hc->start_pkt_count - hctsiz.b.pktcnt) * hc->max_packet;
  40201. + }
  40202. +
  40203. + return length;
  40204. +}
  40205. +
  40206. +/**
  40207. + * Updates the state of the URB after a Transfer Complete interrupt on the
  40208. + * host channel. Updates the actual_length field of the URB based on the
  40209. + * number of bytes transferred via the host channel. Sets the URB status
  40210. + * if the data transfer is finished.
  40211. + *
  40212. + * @return 1 if the data transfer specified by the URB is completely finished,
  40213. + * 0 otherwise.
  40214. + */
  40215. +static int update_urb_state_xfer_comp(dwc_hc_t * hc,
  40216. + dwc_otg_hc_regs_t * hc_regs,
  40217. + dwc_otg_hcd_urb_t * urb,
  40218. + dwc_otg_qtd_t * qtd)
  40219. +{
  40220. + int xfer_done = 0;
  40221. + int short_read = 0;
  40222. +
  40223. + int xfer_length;
  40224. +
  40225. + xfer_length = get_actual_xfer_length(hc, hc_regs, qtd,
  40226. + DWC_OTG_HC_XFER_COMPLETE,
  40227. + &short_read);
  40228. +
  40229. +
  40230. + /* non DWORD-aligned buffer case handling. */
  40231. + if (hc->align_buff && xfer_length && hc->ep_is_in) {
  40232. + dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,
  40233. + xfer_length);
  40234. + }
  40235. +
  40236. + urb->actual_length += xfer_length;
  40237. +
  40238. + if (xfer_length && (hc->ep_type == DWC_OTG_EP_TYPE_BULK) &&
  40239. + (urb->flags & URB_SEND_ZERO_PACKET)
  40240. + && (urb->actual_length == urb->length)
  40241. + && !(urb->length % hc->max_packet)) {
  40242. + xfer_done = 0;
  40243. + } else if (short_read || urb->actual_length >= urb->length) {
  40244. + xfer_done = 1;
  40245. + urb->status = 0;
  40246. + }
  40247. +
  40248. +#ifdef DEBUG
  40249. + {
  40250. + hctsiz_data_t hctsiz;
  40251. + hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
  40252. + DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",
  40253. + __func__, (hc->ep_is_in ? "IN" : "OUT"),
  40254. + hc->hc_num);
  40255. + DWC_DEBUGPL(DBG_HCDV, " hc->xfer_len %d\n", hc->xfer_len);
  40256. + DWC_DEBUGPL(DBG_HCDV, " hctsiz.xfersize %d\n",
  40257. + hctsiz.b.xfersize);
  40258. + DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n",
  40259. + urb->length);
  40260. + DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n",
  40261. + urb->actual_length);
  40262. + DWC_DEBUGPL(DBG_HCDV, " short_read %d, xfer_done %d\n",
  40263. + short_read, xfer_done);
  40264. + }
  40265. +#endif
  40266. +
  40267. + return xfer_done;
  40268. +}
  40269. +
  40270. +/*
  40271. + * Save the starting data toggle for the next transfer. The data toggle is
  40272. + * saved in the QH for non-control transfers and it's saved in the QTD for
  40273. + * control transfers.
  40274. + */
  40275. +void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
  40276. + dwc_otg_hc_regs_t * hc_regs, dwc_otg_qtd_t * qtd)
  40277. +{
  40278. + hctsiz_data_t hctsiz;
  40279. + hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
  40280. +
  40281. + if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) {
  40282. + dwc_otg_qh_t *qh = hc->qh;
  40283. + if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
  40284. + qh->data_toggle = DWC_OTG_HC_PID_DATA0;
  40285. + } else {
  40286. + qh->data_toggle = DWC_OTG_HC_PID_DATA1;
  40287. + }
  40288. + } else {
  40289. + if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
  40290. + qtd->data_toggle = DWC_OTG_HC_PID_DATA0;
  40291. + } else {
  40292. + qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
  40293. + }
  40294. + }
  40295. +}
  40296. +
  40297. +/**
  40298. + * Updates the state of an Isochronous URB when the transfer is stopped for
  40299. + * any reason. The fields of the current entry in the frame descriptor array
  40300. + * are set based on the transfer state and the input _halt_status. Completes
  40301. + * the Isochronous URB if all the URB frames have been completed.
  40302. + *
  40303. + * @return DWC_OTG_HC_XFER_COMPLETE if there are more frames remaining to be
  40304. + * transferred in the URB. Otherwise return DWC_OTG_HC_XFER_URB_COMPLETE.
  40305. + */
  40306. +static dwc_otg_halt_status_e
  40307. +update_isoc_urb_state(dwc_otg_hcd_t * hcd,
  40308. + dwc_hc_t * hc,
  40309. + dwc_otg_hc_regs_t * hc_regs,
  40310. + dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)
  40311. +{
  40312. + dwc_otg_hcd_urb_t *urb = qtd->urb;
  40313. + dwc_otg_halt_status_e ret_val = halt_status;
  40314. + struct dwc_otg_hcd_iso_packet_desc *frame_desc;
  40315. +
  40316. + frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
  40317. + switch (halt_status) {
  40318. + case DWC_OTG_HC_XFER_COMPLETE:
  40319. + frame_desc->status = 0;
  40320. + frame_desc->actual_length =
  40321. + get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);
  40322. +
  40323. + /* non DWORD-aligned buffer case handling. */
  40324. + if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {
  40325. + dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,
  40326. + hc->qh->dw_align_buf, frame_desc->actual_length);
  40327. + }
  40328. +
  40329. + break;
  40330. + case DWC_OTG_HC_XFER_FRAME_OVERRUN:
  40331. + urb->error_count++;
  40332. + if (hc->ep_is_in) {
  40333. + frame_desc->status = -DWC_E_NO_STREAM_RES;
  40334. + } else {
  40335. + frame_desc->status = -DWC_E_COMMUNICATION;
  40336. + }
  40337. + frame_desc->actual_length = 0;
  40338. + break;
  40339. + case DWC_OTG_HC_XFER_BABBLE_ERR:
  40340. + urb->error_count++;
  40341. + frame_desc->status = -DWC_E_OVERFLOW;
  40342. + /* Don't need to update actual_length in this case. */
  40343. + break;
  40344. + case DWC_OTG_HC_XFER_XACT_ERR:
  40345. + urb->error_count++;
  40346. + frame_desc->status = -DWC_E_PROTOCOL;
  40347. + frame_desc->actual_length =
  40348. + get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);
  40349. +
  40350. + /* non DWORD-aligned buffer case handling. */
  40351. + if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {
  40352. + dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,
  40353. + hc->qh->dw_align_buf, frame_desc->actual_length);
  40354. + }
  40355. + /* Skip whole frame */
  40356. + if (hc->qh->do_split && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) &&
  40357. + hc->ep_is_in && hcd->core_if->dma_enable) {
  40358. + qtd->complete_split = 0;
  40359. + qtd->isoc_split_offset = 0;
  40360. + }
  40361. +
  40362. + break;
  40363. + default:
  40364. + DWC_ASSERT(1, "Unhandled _halt_status (%d)\n", halt_status);
  40365. + break;
  40366. + }
  40367. + if (++qtd->isoc_frame_index == urb->packet_count) {
  40368. + /*
  40369. + * urb->status is not used for isoc transfers.
  40370. + * The individual frame_desc statuses are used instead.
  40371. + */
  40372. + hcd->fops->complete(hcd, urb->priv, urb, 0);
  40373. + ret_val = DWC_OTG_HC_XFER_URB_COMPLETE;
  40374. + } else {
  40375. + ret_val = DWC_OTG_HC_XFER_COMPLETE;
  40376. + }
  40377. + return ret_val;
  40378. +}
  40379. +
  40380. +/**
  40381. + * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic
  40382. + * QHs, removes the QH from the active non-periodic schedule. If any QTDs are
  40383. + * still linked to the QH, the QH is added to the end of the inactive
  40384. + * non-periodic schedule. For periodic QHs, removes the QH from the periodic
  40385. + * schedule if no more QTDs are linked to the QH.
  40386. + */
  40387. +static void deactivate_qh(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, int free_qtd)
  40388. +{
  40389. + int continue_split = 0;
  40390. + dwc_otg_qtd_t *qtd;
  40391. +
  40392. + DWC_DEBUGPL(DBG_HCDV, " %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd);
  40393. +
  40394. + qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
  40395. +
  40396. + if (qtd->complete_split) {
  40397. + continue_split = 1;
  40398. + } else if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID ||
  40399. + qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END) {
  40400. + continue_split = 1;
  40401. + }
  40402. +
  40403. + if (free_qtd) {
  40404. + dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
  40405. + continue_split = 0;
  40406. + }
  40407. +
  40408. + qh->channel = NULL;
  40409. + dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split);
  40410. +}
  40411. +
  40412. +/**
  40413. + * Releases a host channel for use by other transfers. Attempts to select and
  40414. + * queue more transactions since at least one host channel is available.
  40415. + *
  40416. + * @param hcd The HCD state structure.
  40417. + * @param hc The host channel to release.
  40418. + * @param qtd The QTD associated with the host channel. This QTD may be freed
  40419. + * if the transfer is complete or an error has occurred.
  40420. + * @param halt_status Reason the channel is being released. This status
  40421. + * determines the actions taken by this function.
  40422. + */
  40423. +static void release_channel(dwc_otg_hcd_t * hcd,
  40424. + dwc_hc_t * hc,
  40425. + dwc_otg_qtd_t * qtd,
  40426. + dwc_otg_halt_status_e halt_status)
  40427. +{
  40428. + dwc_otg_transaction_type_e tr_type;
  40429. + int free_qtd;
  40430. + dwc_irqflags_t flags;
  40431. + dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC();
  40432. +
  40433. + DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d, xfer_len %d\n",
  40434. + __func__, hc->hc_num, halt_status, hc->xfer_len);
  40435. +
  40436. + switch (halt_status) {
  40437. + case DWC_OTG_HC_XFER_URB_COMPLETE:
  40438. + free_qtd = 1;
  40439. + break;
  40440. + case DWC_OTG_HC_XFER_AHB_ERR:
  40441. + case DWC_OTG_HC_XFER_STALL:
  40442. + case DWC_OTG_HC_XFER_BABBLE_ERR:
  40443. + free_qtd = 1;
  40444. + break;
  40445. + case DWC_OTG_HC_XFER_XACT_ERR:
  40446. + if (qtd->error_count >= 3) {
  40447. + DWC_DEBUGPL(DBG_HCDV,
  40448. + " Complete URB with transaction error\n");
  40449. + free_qtd = 1;
  40450. + qtd->urb->status = -DWC_E_PROTOCOL;
  40451. + hcd->fops->complete(hcd, qtd->urb->priv,
  40452. + qtd->urb, -DWC_E_PROTOCOL);
  40453. + } else {
  40454. + free_qtd = 0;
  40455. + }
  40456. + break;
  40457. + case DWC_OTG_HC_XFER_URB_DEQUEUE:
  40458. + /*
  40459. + * The QTD has already been removed and the QH has been
  40460. + * deactivated. Don't want to do anything except release the
  40461. + * host channel and try to queue more transfers.
  40462. + */
  40463. + goto cleanup;
  40464. + case DWC_OTG_HC_XFER_NO_HALT_STATUS:
  40465. + free_qtd = 0;
  40466. + break;
  40467. + case DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE:
  40468. + DWC_DEBUGPL(DBG_HCDV,
  40469. + " Complete URB with I/O error\n");
  40470. + free_qtd = 1;
  40471. + qtd->urb->status = -DWC_E_IO;
  40472. + hcd->fops->complete(hcd, qtd->urb->priv,
  40473. + qtd->urb, -DWC_E_IO);
  40474. + break;
  40475. + default:
  40476. + free_qtd = 0;
  40477. + break;
  40478. + }
  40479. +
  40480. + deactivate_qh(hcd, hc->qh, free_qtd);
  40481. +
  40482. +cleanup:
  40483. + /*
  40484. + * Release the host channel for use by other transfers. The cleanup
  40485. + * function clears the channel interrupt enables and conditions, so
  40486. + * there's no need to clear the Channel Halted interrupt separately.
  40487. + */
  40488. + dwc_otg_hc_cleanup(hcd->core_if, hc);
  40489. + DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
  40490. +
  40491. + if (!microframe_schedule) {
  40492. + switch (hc->ep_type) {
  40493. + case DWC_OTG_EP_TYPE_CONTROL:
  40494. + case DWC_OTG_EP_TYPE_BULK:
  40495. + hcd->non_periodic_channels--;
  40496. + break;
  40497. +
  40498. + default:
  40499. + /*
  40500. + * Don't release reservations for periodic channels here.
  40501. + * That's done when a periodic transfer is descheduled (i.e.
  40502. + * when the QH is removed from the periodic schedule).
  40503. + */
  40504. + break;
  40505. + }
  40506. + } else {
  40507. +
  40508. + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
  40509. + hcd->available_host_channels++;
  40510. + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
  40511. + }
  40512. +
  40513. + /* Try to queue more transfers now that there's a free channel. */
  40514. + tr_type = dwc_otg_hcd_select_transactions(hcd);
  40515. + if (tr_type != DWC_OTG_TRANSACTION_NONE) {
  40516. + dwc_otg_hcd_queue_transactions(hcd, tr_type);
  40517. + }
  40518. + DWC_SPINLOCK_FREE(channel_lock);
  40519. +}
  40520. +
  40521. +/**
  40522. + * Halts a host channel. If the channel cannot be halted immediately because
  40523. + * the request queue is full, this function ensures that the FIFO empty
  40524. + * interrupt for the appropriate queue is enabled so that the halt request can
  40525. + * be queued when there is space in the request queue.
  40526. + *
  40527. + * This function may also be called in DMA mode. In that case, the channel is
  40528. + * simply released since the core always halts the channel automatically in
  40529. + * DMA mode.
  40530. + */
  40531. +static void halt_channel(dwc_otg_hcd_t * hcd,
  40532. + dwc_hc_t * hc,
  40533. + dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)
  40534. +{
  40535. + if (hcd->core_if->dma_enable) {
  40536. + release_channel(hcd, hc, qtd, halt_status);
  40537. + return;
  40538. + }
  40539. +
  40540. + /* Slave mode processing... */
  40541. + dwc_otg_hc_halt(hcd->core_if, hc, halt_status);
  40542. +
  40543. + if (hc->halt_on_queue) {
  40544. + gintmsk_data_t gintmsk = {.d32 = 0 };
  40545. + dwc_otg_core_global_regs_t *global_regs;
  40546. + global_regs = hcd->core_if->core_global_regs;
  40547. +
  40548. + if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
  40549. + hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
  40550. + /*
  40551. + * Make sure the Non-periodic Tx FIFO empty interrupt
  40552. + * is enabled so that the non-periodic schedule will
  40553. + * be processed.
  40554. + */
  40555. + gintmsk.b.nptxfempty = 1;
  40556. + DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
  40557. + } else {
  40558. + /*
  40559. + * Move the QH from the periodic queued schedule to
  40560. + * the periodic assigned schedule. This allows the
  40561. + * halt to be queued when the periodic schedule is
  40562. + * processed.
  40563. + */
  40564. + DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
  40565. + &hc->qh->qh_list_entry);
  40566. +
  40567. + /*
  40568. + * Make sure the Periodic Tx FIFO Empty interrupt is
  40569. + * enabled so that the periodic schedule will be
  40570. + * processed.
  40571. + */
  40572. + gintmsk.b.ptxfempty = 1;
  40573. + DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
  40574. + }
  40575. + }
  40576. +}
  40577. +
  40578. +/**
  40579. + * Performs common cleanup for non-periodic transfers after a Transfer
  40580. + * Complete interrupt. This function should be called after any endpoint type
  40581. + * specific handling is finished to release the host channel.
  40582. + */
  40583. +static void complete_non_periodic_xfer(dwc_otg_hcd_t * hcd,
  40584. + dwc_hc_t * hc,
  40585. + dwc_otg_hc_regs_t * hc_regs,
  40586. + dwc_otg_qtd_t * qtd,
  40587. + dwc_otg_halt_status_e halt_status)
  40588. +{
  40589. + hcint_data_t hcint;
  40590. +
  40591. + qtd->error_count = 0;
  40592. +
  40593. + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
  40594. + if (hcint.b.nyet) {
  40595. + /*
  40596. + * Got a NYET on the last transaction of the transfer. This
  40597. + * means that the endpoint should be in the PING state at the
  40598. + * beginning of the next transfer.
  40599. + */
  40600. + hc->qh->ping_state = 1;
  40601. + clear_hc_int(hc_regs, nyet);
  40602. + }
  40603. +
  40604. + /*
  40605. + * Always halt and release the host channel to make it available for
  40606. + * more transfers. There may still be more phases for a control
  40607. + * transfer or more data packets for a bulk transfer at this point,
  40608. + * but the host channel is still halted. A channel will be reassigned
  40609. + * to the transfer when the non-periodic schedule is processed after
  40610. + * the channel is released. This allows transactions to be queued
  40611. + * properly via dwc_otg_hcd_queue_transactions, which also enables the
  40612. + * Tx FIFO Empty interrupt if necessary.
  40613. + */
  40614. + if (hc->ep_is_in) {
  40615. + /*
  40616. + * IN transfers in Slave mode require an explicit disable to
  40617. + * halt the channel. (In DMA mode, this call simply releases
  40618. + * the channel.)
  40619. + */
  40620. + halt_channel(hcd, hc, qtd, halt_status);
  40621. + } else {
  40622. + /*
  40623. + * The channel is automatically disabled by the core for OUT
  40624. + * transfers in Slave mode.
  40625. + */
  40626. + release_channel(hcd, hc, qtd, halt_status);
  40627. + }
  40628. +}
  40629. +
  40630. +/**
  40631. + * Performs common cleanup for periodic transfers after a Transfer Complete
  40632. + * interrupt. This function should be called after any endpoint type specific
  40633. + * handling is finished to release the host channel.
  40634. + */
  40635. +static void complete_periodic_xfer(dwc_otg_hcd_t * hcd,
  40636. + dwc_hc_t * hc,
  40637. + dwc_otg_hc_regs_t * hc_regs,
  40638. + dwc_otg_qtd_t * qtd,
  40639. + dwc_otg_halt_status_e halt_status)
  40640. +{
  40641. + hctsiz_data_t hctsiz;
  40642. + qtd->error_count = 0;
  40643. +
  40644. + hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
  40645. + if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) {
  40646. + /* Core halts channel in these cases. */
  40647. + release_channel(hcd, hc, qtd, halt_status);
  40648. + } else {
  40649. + /* Flush any outstanding requests from the Tx queue. */
  40650. + halt_channel(hcd, hc, qtd, halt_status);
  40651. + }
  40652. +}
  40653. +
  40654. +static int32_t handle_xfercomp_isoc_split_in(dwc_otg_hcd_t * hcd,
  40655. + dwc_hc_t * hc,
  40656. + dwc_otg_hc_regs_t * hc_regs,
  40657. + dwc_otg_qtd_t * qtd)
  40658. +{
  40659. + uint32_t len;
  40660. + struct dwc_otg_hcd_iso_packet_desc *frame_desc;
  40661. + frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
  40662. +
  40663. + len = get_actual_xfer_length(hc, hc_regs, qtd,
  40664. + DWC_OTG_HC_XFER_COMPLETE, NULL);
  40665. +
  40666. + if (!len) {
  40667. + qtd->complete_split = 0;
  40668. + qtd->isoc_split_offset = 0;
  40669. + return 0;
  40670. + }
  40671. + frame_desc->actual_length += len;
  40672. +
  40673. + if (hc->align_buff && len)
  40674. + dwc_memcpy(qtd->urb->buf + frame_desc->offset +
  40675. + qtd->isoc_split_offset, hc->qh->dw_align_buf, len);
  40676. + qtd->isoc_split_offset += len;
  40677. +
  40678. + if (frame_desc->length == frame_desc->actual_length) {
  40679. + frame_desc->status = 0;
  40680. + qtd->isoc_frame_index++;
  40681. + qtd->complete_split = 0;
  40682. + qtd->isoc_split_offset = 0;
  40683. + }
  40684. +
  40685. + if (qtd->isoc_frame_index == qtd->urb->packet_count) {
  40686. + hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
  40687. + release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
  40688. + } else {
  40689. + release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
  40690. + }
  40691. +
  40692. + return 1; /* Indicates that channel released */
  40693. +}
  40694. +
  40695. +/**
  40696. + * Handles a host channel Transfer Complete interrupt. This handler may be
  40697. + * called in either DMA mode or Slave mode.
  40698. + */
  40699. +static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t * hcd,
  40700. + dwc_hc_t * hc,
  40701. + dwc_otg_hc_regs_t * hc_regs,
  40702. + dwc_otg_qtd_t * qtd)
  40703. +{
  40704. + int urb_xfer_done;
  40705. + dwc_otg_halt_status_e halt_status = DWC_OTG_HC_XFER_COMPLETE;
  40706. + dwc_otg_hcd_urb_t *urb = qtd->urb;
  40707. + int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
  40708. +
  40709. + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
  40710. + "Transfer Complete--\n", hc->hc_num);
  40711. +
  40712. + if (hcd->core_if->dma_desc_enable) {
  40713. + dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, halt_status);
  40714. + if (pipe_type == UE_ISOCHRONOUS) {
  40715. + /* Do not disable the interrupt, just clear it */
  40716. + clear_hc_int(hc_regs, xfercomp);
  40717. + return 1;
  40718. + }
  40719. + goto handle_xfercomp_done;
  40720. + }
  40721. +
  40722. + /*
  40723. + * Handle xfer complete on CSPLIT.
  40724. + */
  40725. +
  40726. + if (hc->qh->do_split) {
  40727. + if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hc->ep_is_in
  40728. + && hcd->core_if->dma_enable) {
  40729. + if (qtd->complete_split
  40730. + && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs,
  40731. + qtd))
  40732. + goto handle_xfercomp_done;
  40733. + } else {
  40734. + qtd->complete_split = 0;
  40735. + }
  40736. + }
  40737. +
  40738. + /* Update the QTD and URB states. */
  40739. + switch (pipe_type) {
  40740. + case UE_CONTROL:
  40741. + switch (qtd->control_phase) {
  40742. + case DWC_OTG_CONTROL_SETUP:
  40743. + if (urb->length > 0) {
  40744. + qtd->control_phase = DWC_OTG_CONTROL_DATA;
  40745. + } else {
  40746. + qtd->control_phase = DWC_OTG_CONTROL_STATUS;
  40747. + }
  40748. + DWC_DEBUGPL(DBG_HCDV,
  40749. + " Control setup transaction done\n");
  40750. + halt_status = DWC_OTG_HC_XFER_COMPLETE;
  40751. + break;
  40752. + case DWC_OTG_CONTROL_DATA:{
  40753. + urb_xfer_done =
  40754. + update_urb_state_xfer_comp(hc, hc_regs, urb,
  40755. + qtd);
  40756. + if (urb_xfer_done) {
  40757. + qtd->control_phase =
  40758. + DWC_OTG_CONTROL_STATUS;
  40759. + DWC_DEBUGPL(DBG_HCDV,
  40760. + " Control data transfer done\n");
  40761. + } else {
  40762. + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
  40763. + }
  40764. + halt_status = DWC_OTG_HC_XFER_COMPLETE;
  40765. + break;
  40766. + }
  40767. + case DWC_OTG_CONTROL_STATUS:
  40768. + DWC_DEBUGPL(DBG_HCDV, " Control transfer complete\n");
  40769. + if (urb->status == -DWC_E_IN_PROGRESS) {
  40770. + urb->status = 0;
  40771. + }
  40772. + hcd->fops->complete(hcd, urb->priv, urb, urb->status);
  40773. + halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
  40774. + break;
  40775. + }
  40776. +
  40777. + complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
  40778. + break;
  40779. + case UE_BULK:
  40780. + DWC_DEBUGPL(DBG_HCDV, " Bulk transfer complete\n");
  40781. + urb_xfer_done =
  40782. + update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
  40783. + if (urb_xfer_done) {
  40784. + hcd->fops->complete(hcd, urb->priv, urb, urb->status);
  40785. + halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
  40786. + } else {
  40787. + halt_status = DWC_OTG_HC_XFER_COMPLETE;
  40788. + }
  40789. +
  40790. + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
  40791. + complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
  40792. + break;
  40793. + case UE_INTERRUPT:
  40794. + DWC_DEBUGPL(DBG_HCDV, " Interrupt transfer complete\n");
  40795. + urb_xfer_done =
  40796. + update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
  40797. +
  40798. + /*
  40799. + * Interrupt URB is done on the first transfer complete
  40800. + * interrupt.
  40801. + */
  40802. + if (urb_xfer_done) {
  40803. + hcd->fops->complete(hcd, urb->priv, urb, urb->status);
  40804. + halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
  40805. + } else {
  40806. + halt_status = DWC_OTG_HC_XFER_COMPLETE;
  40807. + }
  40808. +
  40809. + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
  40810. + complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
  40811. + break;
  40812. + case UE_ISOCHRONOUS:
  40813. + DWC_DEBUGPL(DBG_HCDV, " Isochronous transfer complete\n");
  40814. + if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) {
  40815. + halt_status =
  40816. + update_isoc_urb_state(hcd, hc, hc_regs, qtd,
  40817. + DWC_OTG_HC_XFER_COMPLETE);
  40818. + }
  40819. + complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
  40820. + break;
  40821. + }
  40822. +
  40823. +handle_xfercomp_done:
  40824. + disable_hc_int(hc_regs, xfercompl);
  40825. +
  40826. + return 1;
  40827. +}
  40828. +
  40829. +/**
  40830. + * Handles a host channel STALL interrupt. This handler may be called in
  40831. + * either DMA mode or Slave mode.
  40832. + */
  40833. +static int32_t handle_hc_stall_intr(dwc_otg_hcd_t * hcd,
  40834. + dwc_hc_t * hc,
  40835. + dwc_otg_hc_regs_t * hc_regs,
  40836. + dwc_otg_qtd_t * qtd)
  40837. +{
  40838. + dwc_otg_hcd_urb_t *urb = qtd->urb;
  40839. + int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
  40840. +
  40841. + DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
  40842. + "STALL Received--\n", hc->hc_num);
  40843. +
  40844. + if (hcd->core_if->dma_desc_enable) {
  40845. + dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_STALL);
  40846. + goto handle_stall_done;
  40847. + }
  40848. +
  40849. + if (pipe_type == UE_CONTROL) {
  40850. + hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);
  40851. + }
  40852. +
  40853. + if (pipe_type == UE_BULK || pipe_type == UE_INTERRUPT) {
  40854. + hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);
  40855. + /*
  40856. + * USB protocol requires resetting the data toggle for bulk
  40857. + * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT)
  40858. + * setup command is issued to the endpoint. Anticipate the
  40859. + * CLEAR_FEATURE command since a STALL has occurred and reset
  40860. + * the data toggle now.
  40861. + */
  40862. + hc->qh->data_toggle = 0;
  40863. + }
  40864. +
  40865. + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL);
  40866. +
  40867. +handle_stall_done:
  40868. + disable_hc_int(hc_regs, stall);
  40869. +
  40870. + return 1;
  40871. +}
  40872. +
  40873. +/*
  40874. + * Updates the state of the URB when a transfer has been stopped due to an
  40875. + * abnormal condition before the transfer completes. Modifies the
  40876. + * actual_length field of the URB to reflect the number of bytes that have
  40877. + * actually been transferred via the host channel.
  40878. + */
  40879. +static void update_urb_state_xfer_intr(dwc_hc_t * hc,
  40880. + dwc_otg_hc_regs_t * hc_regs,
  40881. + dwc_otg_hcd_urb_t * urb,
  40882. + dwc_otg_qtd_t * qtd,
  40883. + dwc_otg_halt_status_e halt_status)
  40884. +{
  40885. + uint32_t bytes_transferred = get_actual_xfer_length(hc, hc_regs, qtd,
  40886. + halt_status, NULL);
  40887. + /* non DWORD-aligned buffer case handling. */
  40888. + if (hc->align_buff && bytes_transferred && hc->ep_is_in) {
  40889. + dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,
  40890. + bytes_transferred);
  40891. + }
  40892. +
  40893. + urb->actual_length += bytes_transferred;
  40894. +
  40895. +#ifdef DEBUG
  40896. + {
  40897. + hctsiz_data_t hctsiz;
  40898. + hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
  40899. + DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",
  40900. + __func__, (hc->ep_is_in ? "IN" : "OUT"),
  40901. + hc->hc_num);
  40902. + DWC_DEBUGPL(DBG_HCDV, " hc->start_pkt_count %d\n",
  40903. + hc->start_pkt_count);
  40904. + DWC_DEBUGPL(DBG_HCDV, " hctsiz.pktcnt %d\n", hctsiz.b.pktcnt);
  40905. + DWC_DEBUGPL(DBG_HCDV, " hc->max_packet %d\n", hc->max_packet);
  40906. + DWC_DEBUGPL(DBG_HCDV, " bytes_transferred %d\n",
  40907. + bytes_transferred);
  40908. + DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n",
  40909. + urb->actual_length);
  40910. + DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n",
  40911. + urb->length);
  40912. + }
  40913. +#endif
  40914. +}
  40915. +
  40916. +/**
  40917. + * Handles a host channel NAK interrupt. This handler may be called in either
  40918. + * DMA mode or Slave mode.
  40919. + */
  40920. +static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd,
  40921. + dwc_hc_t * hc,
  40922. + dwc_otg_hc_regs_t * hc_regs,
  40923. + dwc_otg_qtd_t * qtd)
  40924. +{
  40925. + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
  40926. + "NAK Received--\n", hc->hc_num);
  40927. +
  40928. + /*
  40929. + * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and
  40930. + * interrupt. Re-start the SSPLIT transfer.
  40931. + */
  40932. + if (hc->do_split) {
  40933. + if (hc->complete_split) {
  40934. + qtd->error_count = 0;
  40935. + }
  40936. + qtd->complete_split = 0;
  40937. + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
  40938. + goto handle_nak_done;
  40939. + }
  40940. +
  40941. + switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
  40942. + case UE_CONTROL:
  40943. + case UE_BULK:
  40944. + if (hcd->core_if->dma_enable && hc->ep_is_in) {
  40945. + /*
  40946. + * NAK interrupts are enabled on bulk/control IN
  40947. + * transfers in DMA mode for the sole purpose of
  40948. + * resetting the error count after a transaction error
  40949. + * occurs. The core will continue transferring data.
  40950. + */
  40951. + qtd->error_count = 0;
  40952. + goto handle_nak_done;
  40953. + }
  40954. +
  40955. + /*
  40956. + * NAK interrupts normally occur during OUT transfers in DMA
  40957. + * or Slave mode. For IN transfers, more requests will be
  40958. + * queued as request queue space is available.
  40959. + */
  40960. + qtd->error_count = 0;
  40961. +
  40962. + if (!hc->qh->ping_state) {
  40963. + update_urb_state_xfer_intr(hc, hc_regs,
  40964. + qtd->urb, qtd,
  40965. + DWC_OTG_HC_XFER_NAK);
  40966. + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
  40967. +
  40968. + if (hc->speed == DWC_OTG_EP_SPEED_HIGH)
  40969. + hc->qh->ping_state = 1;
  40970. + }
  40971. +
  40972. + /*
  40973. + * Halt the channel so the transfer can be re-started from
  40974. + * the appropriate point or the PING protocol will
  40975. + * start/continue.
  40976. + */
  40977. + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
  40978. + break;
  40979. + case UE_INTERRUPT:
  40980. + qtd->error_count = 0;
  40981. + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
  40982. + break;
  40983. + case UE_ISOCHRONOUS:
  40984. + /* Should never get called for isochronous transfers. */
  40985. + DWC_ASSERT(1, "NACK interrupt for ISOC transfer\n");
  40986. + break;
  40987. + }
  40988. +
  40989. +handle_nak_done:
  40990. + disable_hc_int(hc_regs, nak);
  40991. +
  40992. + return 1;
  40993. +}
  40994. +
  40995. +/**
  40996. + * Handles a host channel ACK interrupt. This interrupt is enabled when
  40997. + * performing the PING protocol in Slave mode, when errors occur during
  40998. + * either Slave mode or DMA mode, and during Start Split transactions.
  40999. + */
  41000. +static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd,
  41001. + dwc_hc_t * hc,
  41002. + dwc_otg_hc_regs_t * hc_regs,
  41003. + dwc_otg_qtd_t * qtd)
  41004. +{
  41005. + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
  41006. + "ACK Received--\n", hc->hc_num);
  41007. +
  41008. + if (hc->do_split) {
  41009. + /*
  41010. + * Handle ACK on SSPLIT.
  41011. + * ACK should not occur in CSPLIT.
  41012. + */
  41013. + if (!hc->ep_is_in && hc->data_pid_start != DWC_OTG_HC_PID_SETUP) {
  41014. + qtd->ssplit_out_xfer_count = hc->xfer_len;
  41015. + }
  41016. + if (!(hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)) {
  41017. + /* Don't need complete for isochronous out transfers. */
  41018. + qtd->complete_split = 1;
  41019. + }
  41020. +
  41021. + /* ISOC OUT */
  41022. + if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {
  41023. + switch (hc->xact_pos) {
  41024. + case DWC_HCSPLIT_XACTPOS_ALL:
  41025. + break;
  41026. + case DWC_HCSPLIT_XACTPOS_END:
  41027. + qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
  41028. + qtd->isoc_split_offset = 0;
  41029. + break;
  41030. + case DWC_HCSPLIT_XACTPOS_BEGIN:
  41031. + case DWC_HCSPLIT_XACTPOS_MID:
  41032. + /*
  41033. + * For BEGIN or MID, calculate the length for
  41034. + * the next microframe to determine the correct
  41035. + * SSPLIT token, either MID or END.
  41036. + */
  41037. + {
  41038. + struct dwc_otg_hcd_iso_packet_desc
  41039. + *frame_desc;
  41040. +
  41041. + frame_desc =
  41042. + &qtd->urb->
  41043. + iso_descs[qtd->isoc_frame_index];
  41044. + qtd->isoc_split_offset += 188;
  41045. +
  41046. + if ((frame_desc->length -
  41047. + qtd->isoc_split_offset) <= 188) {
  41048. + qtd->isoc_split_pos =
  41049. + DWC_HCSPLIT_XACTPOS_END;
  41050. + } else {
  41051. + qtd->isoc_split_pos =
  41052. + DWC_HCSPLIT_XACTPOS_MID;
  41053. + }
  41054. +
  41055. + }
  41056. + break;
  41057. + }
  41058. + } else {
  41059. + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
  41060. + }
  41061. + } else {
  41062. + qtd->error_count = 0;
  41063. +
  41064. + if (hc->qh->ping_state) {
  41065. + hc->qh->ping_state = 0;
  41066. + /*
  41067. + * Halt the channel so the transfer can be re-started
  41068. + * from the appropriate point. This only happens in
  41069. + * Slave mode. In DMA mode, the ping_state is cleared
  41070. + * when the transfer is started because the core
  41071. + * automatically executes the PING, then the transfer.
  41072. + */
  41073. + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
  41074. + }
  41075. + }
  41076. +
  41077. + /*
  41078. + * If the ACK occurred when _not_ in the PING state, let the channel
  41079. + * continue transferring data after clearing the error count.
  41080. + */
  41081. +
  41082. + disable_hc_int(hc_regs, ack);
  41083. +
  41084. + return 1;
  41085. +}
  41086. +
  41087. +/**
  41088. + * Handles a host channel NYET interrupt. This interrupt should only occur on
  41089. + * Bulk and Control OUT endpoints and for complete split transactions. If a
  41090. + * NYET occurs at the same time as a Transfer Complete interrupt, it is
  41091. + * handled in the xfercomp interrupt handler, not here. This handler may be
  41092. + * called in either DMA mode or Slave mode.
  41093. + */
  41094. +static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd,
  41095. + dwc_hc_t * hc,
  41096. + dwc_otg_hc_regs_t * hc_regs,
  41097. + dwc_otg_qtd_t * qtd)
  41098. +{
  41099. + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
  41100. + "NYET Received--\n", hc->hc_num);
  41101. +
  41102. + /*
  41103. + * NYET on CSPLIT
  41104. + * re-do the CSPLIT immediately on non-periodic
  41105. + */
  41106. + if (hc->do_split && hc->complete_split) {
  41107. + if (hc->ep_is_in && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
  41108. + && hcd->core_if->dma_enable) {
  41109. + qtd->complete_split = 0;
  41110. + qtd->isoc_split_offset = 0;
  41111. + if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
  41112. + hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
  41113. + release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
  41114. + }
  41115. + else
  41116. + release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
  41117. + goto handle_nyet_done;
  41118. + }
  41119. +
  41120. + if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
  41121. + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
  41122. + int frnum = dwc_otg_hcd_get_frame_number(hcd);
  41123. +
  41124. + if (dwc_full_frame_num(frnum) !=
  41125. + dwc_full_frame_num(hc->qh->sched_frame)) {
  41126. + /*
  41127. + * No longer in the same full speed frame.
  41128. + * Treat this as a transaction error.
  41129. + */
  41130. +#if 0
  41131. + /** @todo Fix system performance so this can
  41132. + * be treated as an error. Right now complete
  41133. + * splits cannot be scheduled precisely enough
  41134. + * due to other system activity, so this error
  41135. + * occurs regularly in Slave mode.
  41136. + */
  41137. + qtd->error_count++;
  41138. +#endif
  41139. + qtd->complete_split = 0;
  41140. + halt_channel(hcd, hc, qtd,
  41141. + DWC_OTG_HC_XFER_XACT_ERR);
  41142. + /** @todo add support for isoc release */
  41143. + goto handle_nyet_done;
  41144. + }
  41145. + }
  41146. +
  41147. + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
  41148. + goto handle_nyet_done;
  41149. + }
  41150. +
  41151. + hc->qh->ping_state = 1;
  41152. + qtd->error_count = 0;
  41153. +
  41154. + update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd,
  41155. + DWC_OTG_HC_XFER_NYET);
  41156. + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
  41157. +
  41158. + /*
  41159. + * Halt the channel and re-start the transfer so the PING
  41160. + * protocol will start.
  41161. + */
  41162. + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
  41163. +
  41164. +handle_nyet_done:
  41165. + disable_hc_int(hc_regs, nyet);
  41166. + return 1;
  41167. +}
  41168. +
  41169. +/**
  41170. + * Handles a host channel babble interrupt. This handler may be called in
  41171. + * either DMA mode or Slave mode.
  41172. + */
  41173. +static int32_t handle_hc_babble_intr(dwc_otg_hcd_t * hcd,
  41174. + dwc_hc_t * hc,
  41175. + dwc_otg_hc_regs_t * hc_regs,
  41176. + dwc_otg_qtd_t * qtd)
  41177. +{
  41178. + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
  41179. + "Babble Error--\n", hc->hc_num);
  41180. +
  41181. + if (hcd->core_if->dma_desc_enable) {
  41182. + dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
  41183. + DWC_OTG_HC_XFER_BABBLE_ERR);
  41184. + goto handle_babble_done;
  41185. + }
  41186. +
  41187. + if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
  41188. + hcd->fops->complete(hcd, qtd->urb->priv,
  41189. + qtd->urb, -DWC_E_OVERFLOW);
  41190. + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_BABBLE_ERR);
  41191. + } else {
  41192. + dwc_otg_halt_status_e halt_status;
  41193. + halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd,
  41194. + DWC_OTG_HC_XFER_BABBLE_ERR);
  41195. + halt_channel(hcd, hc, qtd, halt_status);
  41196. + }
  41197. +
  41198. +handle_babble_done:
  41199. + disable_hc_int(hc_regs, bblerr);
  41200. + return 1;
  41201. +}
  41202. +
  41203. +/**
  41204. + * Handles a host channel AHB error interrupt. This handler is only called in
  41205. + * DMA mode.
  41206. + */
  41207. +static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t * hcd,
  41208. + dwc_hc_t * hc,
  41209. + dwc_otg_hc_regs_t * hc_regs,
  41210. + dwc_otg_qtd_t * qtd)
  41211. +{
  41212. + hcchar_data_t hcchar;
  41213. + hcsplt_data_t hcsplt;
  41214. + hctsiz_data_t hctsiz;
  41215. + uint32_t hcdma;
  41216. + char *pipetype, *speed;
  41217. +
  41218. + dwc_otg_hcd_urb_t *urb = qtd->urb;
  41219. +
  41220. + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
  41221. + "AHB Error--\n", hc->hc_num);
  41222. +
  41223. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  41224. + hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
  41225. + hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
  41226. + hcdma = DWC_READ_REG32(&hc_regs->hcdma);
  41227. +
  41228. + DWC_ERROR("AHB ERROR, Channel %d\n", hc->hc_num);
  41229. + DWC_ERROR(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32);
  41230. + DWC_ERROR(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma);
  41231. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Enqueue\n");
  41232. + DWC_ERROR(" Device address: %d\n",
  41233. + dwc_otg_hcd_get_dev_addr(&urb->pipe_info));
  41234. + DWC_ERROR(" Endpoint: %d, %s\n",
  41235. + dwc_otg_hcd_get_ep_num(&urb->pipe_info),
  41236. + (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT"));
  41237. +
  41238. + switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
  41239. + case UE_CONTROL:
  41240. + pipetype = "CONTROL";
  41241. + break;
  41242. + case UE_BULK:
  41243. + pipetype = "BULK";
  41244. + break;
  41245. + case UE_INTERRUPT:
  41246. + pipetype = "INTERRUPT";
  41247. + break;
  41248. + case UE_ISOCHRONOUS:
  41249. + pipetype = "ISOCHRONOUS";
  41250. + break;
  41251. + default:
  41252. + pipetype = "UNKNOWN";
  41253. + break;
  41254. + }
  41255. +
  41256. + DWC_ERROR(" Endpoint type: %s\n", pipetype);
  41257. +
  41258. + switch (hc->speed) {
  41259. + case DWC_OTG_EP_SPEED_HIGH:
  41260. + speed = "HIGH";
  41261. + break;
  41262. + case DWC_OTG_EP_SPEED_FULL:
  41263. + speed = "FULL";
  41264. + break;
  41265. + case DWC_OTG_EP_SPEED_LOW:
  41266. + speed = "LOW";
  41267. + break;
  41268. + default:
  41269. + speed = "UNKNOWN";
  41270. + break;
  41271. + };
  41272. +
  41273. + DWC_ERROR(" Speed: %s\n", speed);
  41274. +
  41275. + DWC_ERROR(" Max packet size: %d\n",
  41276. + dwc_otg_hcd_get_mps(&urb->pipe_info));
  41277. + DWC_ERROR(" Data buffer length: %d\n", urb->length);
  41278. + DWC_ERROR(" Transfer buffer: %p, Transfer DMA: %p\n",
  41279. + urb->buf, (void *)urb->dma);
  41280. + DWC_ERROR(" Setup buffer: %p, Setup DMA: %p\n",
  41281. + urb->setup_packet, (void *)urb->setup_dma);
  41282. + DWC_ERROR(" Interval: %d\n", urb->interval);
  41283. +
  41284. + /* Core haltes the channel for Descriptor DMA mode */
  41285. + if (hcd->core_if->dma_desc_enable) {
  41286. + dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
  41287. + DWC_OTG_HC_XFER_AHB_ERR);
  41288. + goto handle_ahberr_done;
  41289. + }
  41290. +
  41291. + hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_IO);
  41292. +
  41293. + /*
  41294. + * Force a channel halt. Don't call halt_channel because that won't
  41295. + * write to the HCCHARn register in DMA mode to force the halt.
  41296. + */
  41297. + dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR);
  41298. +handle_ahberr_done:
  41299. + disable_hc_int(hc_regs, ahberr);
  41300. + return 1;
  41301. +}
  41302. +
  41303. +/**
  41304. + * Handles a host channel transaction error interrupt. This handler may be
  41305. + * called in either DMA mode or Slave mode.
  41306. + */
  41307. +static int32_t handle_hc_xacterr_intr(dwc_otg_hcd_t * hcd,
  41308. + dwc_hc_t * hc,
  41309. + dwc_otg_hc_regs_t * hc_regs,
  41310. + dwc_otg_qtd_t * qtd)
  41311. +{
  41312. + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
  41313. + "Transaction Error--\n", hc->hc_num);
  41314. +
  41315. + if (hcd->core_if->dma_desc_enable) {
  41316. + dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
  41317. + DWC_OTG_HC_XFER_XACT_ERR);
  41318. + goto handle_xacterr_done;
  41319. + }
  41320. +
  41321. + switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
  41322. + case UE_CONTROL:
  41323. + case UE_BULK:
  41324. + qtd->error_count++;
  41325. + if (!hc->qh->ping_state) {
  41326. +
  41327. + update_urb_state_xfer_intr(hc, hc_regs,
  41328. + qtd->urb, qtd,
  41329. + DWC_OTG_HC_XFER_XACT_ERR);
  41330. + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
  41331. + if (!hc->ep_is_in && hc->speed == DWC_OTG_EP_SPEED_HIGH) {
  41332. + hc->qh->ping_state = 1;
  41333. + }
  41334. + }
  41335. +
  41336. + /*
  41337. + * Halt the channel so the transfer can be re-started from
  41338. + * the appropriate point or the PING protocol will start.
  41339. + */
  41340. + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
  41341. + break;
  41342. + case UE_INTERRUPT:
  41343. + qtd->error_count++;
  41344. + if (hc->do_split && hc->complete_split) {
  41345. + qtd->complete_split = 0;
  41346. + }
  41347. + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
  41348. + break;
  41349. + case UE_ISOCHRONOUS:
  41350. + {
  41351. + dwc_otg_halt_status_e halt_status;
  41352. + halt_status =
  41353. + update_isoc_urb_state(hcd, hc, hc_regs, qtd,
  41354. + DWC_OTG_HC_XFER_XACT_ERR);
  41355. +
  41356. + halt_channel(hcd, hc, qtd, halt_status);
  41357. + }
  41358. + break;
  41359. + }
  41360. +handle_xacterr_done:
  41361. + disable_hc_int(hc_regs, xacterr);
  41362. +
  41363. + return 1;
  41364. +}
  41365. +
  41366. +/**
  41367. + * Handles a host channel frame overrun interrupt. This handler may be called
  41368. + * in either DMA mode or Slave mode.
  41369. + */
  41370. +static int32_t handle_hc_frmovrun_intr(dwc_otg_hcd_t * hcd,
  41371. + dwc_hc_t * hc,
  41372. + dwc_otg_hc_regs_t * hc_regs,
  41373. + dwc_otg_qtd_t * qtd)
  41374. +{
  41375. + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
  41376. + "Frame Overrun--\n", hc->hc_num);
  41377. +
  41378. + switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
  41379. + case UE_CONTROL:
  41380. + case UE_BULK:
  41381. + break;
  41382. + case UE_INTERRUPT:
  41383. + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN);
  41384. + break;
  41385. + case UE_ISOCHRONOUS:
  41386. + {
  41387. + dwc_otg_halt_status_e halt_status;
  41388. + halt_status =
  41389. + update_isoc_urb_state(hcd, hc, hc_regs, qtd,
  41390. + DWC_OTG_HC_XFER_FRAME_OVERRUN);
  41391. +
  41392. + halt_channel(hcd, hc, qtd, halt_status);
  41393. + }
  41394. + break;
  41395. + }
  41396. +
  41397. + disable_hc_int(hc_regs, frmovrun);
  41398. +
  41399. + return 1;
  41400. +}
  41401. +
  41402. +/**
  41403. + * Handles a host channel data toggle error interrupt. This handler may be
  41404. + * called in either DMA mode or Slave mode.
  41405. + */
  41406. +static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t * hcd,
  41407. + dwc_hc_t * hc,
  41408. + dwc_otg_hc_regs_t * hc_regs,
  41409. + dwc_otg_qtd_t * qtd)
  41410. +{
  41411. + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
  41412. + "Data Toggle Error--\n", hc->hc_num);
  41413. +
  41414. + if (hc->ep_is_in) {
  41415. + qtd->error_count = 0;
  41416. + } else {
  41417. + DWC_ERROR("Data Toggle Error on OUT transfer,"
  41418. + "channel %d\n", hc->hc_num);
  41419. + }
  41420. +
  41421. + disable_hc_int(hc_regs, datatglerr);
  41422. +
  41423. + return 1;
  41424. +}
  41425. +
  41426. +#ifdef DEBUG
  41427. +/**
  41428. + * This function is for debug only. It checks that a valid halt status is set
  41429. + * and that HCCHARn.chdis is clear. If there's a problem, corrective action is
  41430. + * taken and a warning is issued.
  41431. + * @return 1 if halt status is ok, 0 otherwise.
  41432. + */
  41433. +static inline int halt_status_ok(dwc_otg_hcd_t * hcd,
  41434. + dwc_hc_t * hc,
  41435. + dwc_otg_hc_regs_t * hc_regs,
  41436. + dwc_otg_qtd_t * qtd)
  41437. +{
  41438. + hcchar_data_t hcchar;
  41439. + hctsiz_data_t hctsiz;
  41440. + hcint_data_t hcint;
  41441. + hcintmsk_data_t hcintmsk;
  41442. + hcsplt_data_t hcsplt;
  41443. +
  41444. + if (hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS) {
  41445. + /*
  41446. + * This code is here only as a check. This condition should
  41447. + * never happen. Ignore the halt if it does occur.
  41448. + */
  41449. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  41450. + hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
  41451. + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
  41452. + hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
  41453. + hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
  41454. + DWC_WARN
  41455. + ("%s: hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS, "
  41456. + "channel %d, hcchar 0x%08x, hctsiz 0x%08x, "
  41457. + "hcint 0x%08x, hcintmsk 0x%08x, "
  41458. + "hcsplt 0x%08x, qtd->complete_split %d\n", __func__,
  41459. + hc->hc_num, hcchar.d32, hctsiz.d32, hcint.d32,
  41460. + hcintmsk.d32, hcsplt.d32, qtd->complete_split);
  41461. +
  41462. + DWC_WARN("%s: no halt status, channel %d, ignoring interrupt\n",
  41463. + __func__, hc->hc_num);
  41464. + DWC_WARN("\n");
  41465. + clear_hc_int(hc_regs, chhltd);
  41466. + return 0;
  41467. + }
  41468. +
  41469. + /*
  41470. + * This code is here only as a check. hcchar.chdis should
  41471. + * never be set when the halt interrupt occurs. Halt the
  41472. + * channel again if it does occur.
  41473. + */
  41474. + hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
  41475. + if (hcchar.b.chdis) {
  41476. + DWC_WARN("%s: hcchar.chdis set unexpectedly, "
  41477. + "hcchar 0x%08x, trying to halt again\n",
  41478. + __func__, hcchar.d32);
  41479. + clear_hc_int(hc_regs, chhltd);
  41480. + hc->halt_pending = 0;
  41481. + halt_channel(hcd, hc, qtd, hc->halt_status);
  41482. + return 0;
  41483. + }
  41484. +
  41485. + return 1;
  41486. +}
  41487. +#endif
  41488. +
  41489. +/**
  41490. + * Handles a host Channel Halted interrupt in DMA mode. This handler
  41491. + * determines the reason the channel halted and proceeds accordingly.
  41492. + */
  41493. +static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
  41494. + dwc_hc_t * hc,
  41495. + dwc_otg_hc_regs_t * hc_regs,
  41496. + dwc_otg_qtd_t * qtd)
  41497. +{
  41498. + hcint_data_t hcint;
  41499. + hcintmsk_data_t hcintmsk;
  41500. + int out_nak_enh = 0;
  41501. +
  41502. + /* For core with OUT NAK enhancement, the flow for high-
  41503. + * speed CONTROL/BULK OUT is handled a little differently.
  41504. + */
  41505. + if (hcd->core_if->snpsid >= OTG_CORE_REV_2_71a) {
  41506. + if (hc->speed == DWC_OTG_EP_SPEED_HIGH && !hc->ep_is_in &&
  41507. + (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
  41508. + hc->ep_type == DWC_OTG_EP_TYPE_BULK)) {
  41509. + out_nak_enh = 1;
  41510. + }
  41511. + }
  41512. +
  41513. + if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||
  41514. + (hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR
  41515. + && !hcd->core_if->dma_desc_enable)) {
  41516. + /*
  41517. + * Just release the channel. A dequeue can happen on a
  41518. + * transfer timeout. In the case of an AHB Error, the channel
  41519. + * was forced to halt because there's no way to gracefully
  41520. + * recover.
  41521. + */
  41522. + if (hcd->core_if->dma_desc_enable)
  41523. + dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
  41524. + hc->halt_status);
  41525. + else
  41526. + release_channel(hcd, hc, qtd, hc->halt_status);
  41527. + return;
  41528. + }
  41529. +
  41530. + /* Read the HCINTn register to determine the cause for the halt. */
  41531. + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
  41532. + hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
  41533. +
  41534. + if (hcint.b.xfercomp) {
  41535. + /** @todo This is here because of a possible hardware bug. Spec
  41536. + * says that on SPLIT-ISOC OUT transfers in DMA mode that a HALT
  41537. + * interrupt w/ACK bit set should occur, but I only see the
  41538. + * XFERCOMP bit, even with it masked out. This is a workaround
  41539. + * for that behavior. Should fix this when hardware is fixed.
  41540. + */
  41541. + if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {
  41542. + handle_hc_ack_intr(hcd, hc, hc_regs, qtd);
  41543. + }
  41544. + handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd);
  41545. + } else if (hcint.b.stall) {
  41546. + handle_hc_stall_intr(hcd, hc, hc_regs, qtd);
  41547. + } else if (hcint.b.xacterr && !hcd->core_if->dma_desc_enable) {
  41548. + if (out_nak_enh) {
  41549. + if (hcint.b.nyet || hcint.b.nak || hcint.b.ack) {
  41550. + DWC_DEBUGPL(DBG_HCD, "XactErr with NYET/NAK/ACK\n");
  41551. + qtd->error_count = 0;
  41552. + } else {
  41553. + DWC_DEBUGPL(DBG_HCD, "XactErr without NYET/NAK/ACK\n");
  41554. + }
  41555. + }
  41556. +
  41557. + /*
  41558. + * Must handle xacterr before nak or ack. Could get a xacterr
  41559. + * at the same time as either of these on a BULK/CONTROL OUT
  41560. + * that started with a PING. The xacterr takes precedence.
  41561. + */
  41562. + handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
  41563. + } else if (hcint.b.xcs_xact && hcd->core_if->dma_desc_enable) {
  41564. + handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
  41565. + } else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) {
  41566. + handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd);
  41567. + } else if (hcint.b.bblerr) {
  41568. + handle_hc_babble_intr(hcd, hc, hc_regs, qtd);
  41569. + } else if (hcint.b.frmovrun) {
  41570. + handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd);
  41571. + } else if (!out_nak_enh) {
  41572. + if (hcint.b.nyet) {
  41573. + /*
  41574. + * Must handle nyet before nak or ack. Could get a nyet at the
  41575. + * same time as either of those on a BULK/CONTROL OUT that
  41576. + * started with a PING. The nyet takes precedence.
  41577. + */
  41578. + handle_hc_nyet_intr(hcd, hc, hc_regs, qtd);
  41579. + } else if (hcint.b.nak && !hcintmsk.b.nak) {
  41580. + /*
  41581. + * If nak is not masked, it's because a non-split IN transfer
  41582. + * is in an error state. In that case, the nak is handled by
  41583. + * the nak interrupt handler, not here. Handle nak here for
  41584. + * BULK/CONTROL OUT transfers, which halt on a NAK to allow
  41585. + * rewinding the buffer pointer.
  41586. + */
  41587. + handle_hc_nak_intr(hcd, hc, hc_regs, qtd);
  41588. + } else if (hcint.b.ack && !hcintmsk.b.ack) {
  41589. + /*
  41590. + * If ack is not masked, it's because a non-split IN transfer
  41591. + * is in an error state. In that case, the ack is handled by
  41592. + * the ack interrupt handler, not here. Handle ack here for
  41593. + * split transfers. Start splits halt on ACK.
  41594. + */
  41595. + handle_hc_ack_intr(hcd, hc, hc_regs, qtd);
  41596. + } else {
  41597. + if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
  41598. + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
  41599. + /*
  41600. + * A periodic transfer halted with no other channel
  41601. + * interrupts set. Assume it was halted by the core
  41602. + * because it could not be completed in its scheduled
  41603. + * (micro)frame.
  41604. + */
  41605. +#ifdef DEBUG
  41606. + DWC_PRINTF
  41607. + ("%s: Halt channel %d (assume incomplete periodic transfer)\n",
  41608. + __func__, hc->hc_num);
  41609. +#endif
  41610. + halt_channel(hcd, hc, qtd,
  41611. + DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE);
  41612. + } else {
  41613. + DWC_ERROR
  41614. + ("%s: Channel %d, DMA Mode -- ChHltd set, but reason "
  41615. + "for halting is unknown, hcint 0x%08x, intsts 0x%08x\n",
  41616. + __func__, hc->hc_num, hcint.d32,
  41617. + DWC_READ_REG32(&hcd->
  41618. + core_if->core_global_regs->
  41619. + gintsts));
  41620. + }
  41621. +
  41622. + }
  41623. + } else {
  41624. + DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n",
  41625. + hcint.d32);
  41626. + }
  41627. +}
  41628. +
  41629. +/**
  41630. + * Handles a host channel Channel Halted interrupt.
  41631. + *
  41632. + * In slave mode, this handler is called only when the driver specifically
  41633. + * requests a halt. This occurs during handling other host channel interrupts
  41634. + * (e.g. nak, xacterr, stall, nyet, etc.).
  41635. + *
  41636. + * In DMA mode, this is the interrupt that occurs when the core has finished
  41637. + * processing a transfer on a channel. Other host channel interrupts (except
  41638. + * ahberr) are disabled in DMA mode.
  41639. + */
  41640. +static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd,
  41641. + dwc_hc_t * hc,
  41642. + dwc_otg_hc_regs_t * hc_regs,
  41643. + dwc_otg_qtd_t * qtd)
  41644. +{
  41645. + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
  41646. + "Channel Halted--\n", hc->hc_num);
  41647. +
  41648. + if (hcd->core_if->dma_enable) {
  41649. + handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd);
  41650. + } else {
  41651. +#ifdef DEBUG
  41652. + if (!halt_status_ok(hcd, hc, hc_regs, qtd)) {
  41653. + return 1;
  41654. + }
  41655. +#endif
  41656. + release_channel(hcd, hc, qtd, hc->halt_status);
  41657. + }
  41658. +
  41659. + return 1;
  41660. +}
  41661. +
  41662. +/** Handles interrupt for a specific Host Channel */
  41663. +int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
  41664. +{
  41665. + int retval = 0;
  41666. + hcint_data_t hcint;
  41667. + hcintmsk_data_t hcintmsk;
  41668. + dwc_hc_t *hc;
  41669. + dwc_otg_hc_regs_t *hc_regs;
  41670. + dwc_otg_qtd_t *qtd;
  41671. +
  41672. + DWC_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", num);
  41673. +
  41674. + hc = dwc_otg_hcd->hc_ptr_array[num];
  41675. + hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num];
  41676. + qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list);
  41677. +
  41678. + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
  41679. + hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
  41680. + DWC_DEBUGPL(DBG_HCDV,
  41681. + " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
  41682. + hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32));
  41683. + hcint.d32 = hcint.d32 & hcintmsk.d32;
  41684. +
  41685. + if (!dwc_otg_hcd->core_if->dma_enable) {
  41686. + if (hcint.b.chhltd && hcint.d32 != 0x2) {
  41687. + hcint.b.chhltd = 0;
  41688. + }
  41689. + }
  41690. +
  41691. + if (hcint.b.xfercomp) {
  41692. + retval |=
  41693. + handle_hc_xfercomp_intr(dwc_otg_hcd, hc, hc_regs, qtd);
  41694. + /*
  41695. + * If NYET occurred at same time as Xfer Complete, the NYET is
  41696. + * handled by the Xfer Complete interrupt handler. Don't want
  41697. + * to call the NYET interrupt handler in this case.
  41698. + */
  41699. + hcint.b.nyet = 0;
  41700. + }
  41701. + if (hcint.b.chhltd) {
  41702. + retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd);
  41703. + }
  41704. + if (hcint.b.ahberr) {
  41705. + retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
  41706. + }
  41707. + if (hcint.b.stall) {
  41708. + retval |= handle_hc_stall_intr(dwc_otg_hcd, hc, hc_regs, qtd);
  41709. + }
  41710. + if (hcint.b.nak) {
  41711. + retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd);
  41712. + }
  41713. + if (hcint.b.ack) {
  41714. + retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd);
  41715. + }
  41716. + if (hcint.b.nyet) {
  41717. + retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd);
  41718. + }
  41719. + if (hcint.b.xacterr) {
  41720. + retval |= handle_hc_xacterr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
  41721. + }
  41722. + if (hcint.b.bblerr) {
  41723. + retval |= handle_hc_babble_intr(dwc_otg_hcd, hc, hc_regs, qtd);
  41724. + }
  41725. + if (hcint.b.frmovrun) {
  41726. + retval |=
  41727. + handle_hc_frmovrun_intr(dwc_otg_hcd, hc, hc_regs, qtd);
  41728. + }
  41729. + if (hcint.b.datatglerr) {
  41730. + retval |=
  41731. + handle_hc_datatglerr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
  41732. + }
  41733. +
  41734. + return retval;
  41735. +}
  41736. +
  41737. +#endif /* DWC_DEVICE_ONLY */
  41738. --- /dev/null
  41739. +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
  41740. @@ -0,0 +1,893 @@
  41741. +/* ==========================================================================
  41742. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $
  41743. + * $Revision: #20 $
  41744. + * $Date: 2011/10/26 $
  41745. + * $Change: 1872981 $
  41746. + *
  41747. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  41748. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  41749. + * otherwise expressly agreed to in writing between Synopsys and you.
  41750. + *
  41751. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  41752. + * any End User Software License Agreement or Agreement for Licensed Product
  41753. + * with Synopsys or any supplement thereto. You are permitted to use and
  41754. + * redistribute this Software in source and binary forms, with or without
  41755. + * modification, provided that redistributions of source code must retain this
  41756. + * notice. You may not view, use, disclose, copy or distribute this file or
  41757. + * any information contained herein except pursuant to this license grant from
  41758. + * Synopsys. If you do not agree with this notice, including the disclaimer
  41759. + * below, then you are not authorized to use the Software.
  41760. + *
  41761. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  41762. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  41763. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  41764. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  41765. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  41766. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  41767. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  41768. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  41769. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  41770. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  41771. + * DAMAGE.
  41772. + * ========================================================================== */
  41773. +#ifndef DWC_DEVICE_ONLY
  41774. +
  41775. +/**
  41776. + * @file
  41777. + *
  41778. + * This file contains the implementation of the HCD. In Linux, the HCD
  41779. + * implements the hc_driver API.
  41780. + */
  41781. +#include <linux/kernel.h>
  41782. +#include <linux/module.h>
  41783. +#include <linux/moduleparam.h>
  41784. +#include <linux/init.h>
  41785. +#include <linux/device.h>
  41786. +#include <linux/errno.h>
  41787. +#include <linux/list.h>
  41788. +#include <linux/interrupt.h>
  41789. +#include <linux/string.h>
  41790. +#include <linux/dma-mapping.h>
  41791. +#include <linux/version.h>
  41792. +#include <asm/io.h>
  41793. +#include <linux/usb.h>
  41794. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
  41795. +#include <../drivers/usb/core/hcd.h>
  41796. +#else
  41797. +#include <linux/usb/hcd.h>
  41798. +#endif
  41799. +
  41800. +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
  41801. +#define USB_URB_EP_LINKING 1
  41802. +#else
  41803. +#define USB_URB_EP_LINKING 0
  41804. +#endif
  41805. +
  41806. +#include "dwc_otg_hcd_if.h"
  41807. +#include "dwc_otg_dbg.h"
  41808. +#include "dwc_otg_driver.h"
  41809. +#include "dwc_otg_hcd.h"
  41810. +/**
  41811. + * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is
  41812. + * qualified with its direction (possible 32 endpoints per device).
  41813. + */
  41814. +#define dwc_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \
  41815. + ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4)
  41816. +
  41817. +static const char dwc_otg_hcd_name[] = "dwc_otg_hcd";
  41818. +
  41819. +/** @name Linux HC Driver API Functions */
  41820. +/** @{ */
  41821. +/* manage i/o requests, device state */
  41822. +static int dwc_otg_urb_enqueue(struct usb_hcd *hcd,
  41823. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
  41824. + struct usb_host_endpoint *ep,
  41825. +#endif
  41826. + struct urb *urb, gfp_t mem_flags);
  41827. +
  41828. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
  41829. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
  41830. +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb);
  41831. +#endif
  41832. +#else /* kernels at or post 2.6.30 */
  41833. +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd,
  41834. + struct urb *urb, int status);
  41835. +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) */
  41836. +
  41837. +static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
  41838. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
  41839. +static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
  41840. +#endif
  41841. +static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd);
  41842. +extern int hcd_start(struct usb_hcd *hcd);
  41843. +extern void hcd_stop(struct usb_hcd *hcd);
  41844. +static int get_frame_number(struct usb_hcd *hcd);
  41845. +extern int hub_status_data(struct usb_hcd *hcd, char *buf);
  41846. +extern int hub_control(struct usb_hcd *hcd,
  41847. + u16 typeReq,
  41848. + u16 wValue, u16 wIndex, char *buf, u16 wLength);
  41849. +
  41850. +struct wrapper_priv_data {
  41851. + dwc_otg_hcd_t *dwc_otg_hcd;
  41852. +};
  41853. +
  41854. +/** @} */
  41855. +
  41856. +static struct hc_driver dwc_otg_hc_driver = {
  41857. +
  41858. + .description = dwc_otg_hcd_name,
  41859. + .product_desc = "DWC OTG Controller",
  41860. + .hcd_priv_size = sizeof(struct wrapper_priv_data),
  41861. +
  41862. + .irq = dwc_otg_hcd_irq,
  41863. +
  41864. + .flags = HCD_MEMORY | HCD_USB2,
  41865. +
  41866. + //.reset =
  41867. + .start = hcd_start,
  41868. + //.suspend =
  41869. + //.resume =
  41870. + .stop = hcd_stop,
  41871. +
  41872. + .urb_enqueue = dwc_otg_urb_enqueue,
  41873. + .urb_dequeue = dwc_otg_urb_dequeue,
  41874. + .endpoint_disable = endpoint_disable,
  41875. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
  41876. + .endpoint_reset = endpoint_reset,
  41877. +#endif
  41878. + .get_frame_number = get_frame_number,
  41879. +
  41880. + .hub_status_data = hub_status_data,
  41881. + .hub_control = hub_control,
  41882. + //.bus_suspend =
  41883. + //.bus_resume =
  41884. +};
  41885. +
  41886. +/** Gets the dwc_otg_hcd from a struct usb_hcd */
  41887. +static inline dwc_otg_hcd_t *hcd_to_dwc_otg_hcd(struct usb_hcd *hcd)
  41888. +{
  41889. + struct wrapper_priv_data *p;
  41890. + p = (struct wrapper_priv_data *)(hcd->hcd_priv);
  41891. + return p->dwc_otg_hcd;
  41892. +}
  41893. +
  41894. +/** Gets the struct usb_hcd that contains a dwc_otg_hcd_t. */
  41895. +static inline struct usb_hcd *dwc_otg_hcd_to_hcd(dwc_otg_hcd_t * dwc_otg_hcd)
  41896. +{
  41897. + return dwc_otg_hcd_get_priv_data(dwc_otg_hcd);
  41898. +}
  41899. +
  41900. +/** Gets the usb_host_endpoint associated with an URB. */
  41901. +inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb)
  41902. +{
  41903. + struct usb_device *dev = urb->dev;
  41904. + int ep_num = usb_pipeendpoint(urb->pipe);
  41905. +
  41906. + if (usb_pipein(urb->pipe))
  41907. + return dev->ep_in[ep_num];
  41908. + else
  41909. + return dev->ep_out[ep_num];
  41910. +}
  41911. +
  41912. +static int _disconnect(dwc_otg_hcd_t * hcd)
  41913. +{
  41914. + struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
  41915. +
  41916. + usb_hcd->self.is_b_host = 0;
  41917. + return 0;
  41918. +}
  41919. +
  41920. +static int _start(dwc_otg_hcd_t * hcd)
  41921. +{
  41922. + struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
  41923. +
  41924. + usb_hcd->self.is_b_host = dwc_otg_hcd_is_b_host(hcd);
  41925. + hcd_start(usb_hcd);
  41926. +
  41927. + return 0;
  41928. +}
  41929. +
  41930. +static int _hub_info(dwc_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr,
  41931. + uint32_t * port_addr)
  41932. +{
  41933. + struct urb *urb = (struct urb *)urb_handle;
  41934. + struct usb_bus *bus;
  41935. +#if 1 //GRAYG - temporary
  41936. + if (NULL == urb_handle)
  41937. + DWC_ERROR("**** %s - NULL URB handle\n", __func__);//GRAYG
  41938. + if (NULL == urb->dev)
  41939. + DWC_ERROR("**** %s - URB has no device\n", __func__);//GRAYG
  41940. + if (NULL == port_addr)
  41941. + DWC_ERROR("**** %s - NULL port_address\n", __func__);//GRAYG
  41942. +#endif
  41943. + if (urb->dev->tt) {
  41944. + if (NULL == urb->dev->tt->hub) {
  41945. + DWC_ERROR("**** %s - (URB's transactor has no TT - giving no hub)\n",
  41946. + __func__); //GRAYG
  41947. + //*hub_addr = (u8)usb_pipedevice(urb->pipe); //GRAYG
  41948. + *hub_addr = 0; //GRAYG
  41949. + // we probably shouldn't have a transaction translator if
  41950. + // there's no associated hub?
  41951. + } else {
  41952. + bus = hcd_to_bus(dwc_otg_hcd_to_hcd(hcd));
  41953. + if (urb->dev->tt->hub == bus->root_hub)
  41954. + *hub_addr = 0;
  41955. + else
  41956. + *hub_addr = urb->dev->tt->hub->devnum;
  41957. + }
  41958. + *port_addr = urb->dev->tt->multi ? urb->dev->ttport : 1;
  41959. + } else {
  41960. + *hub_addr = 0;
  41961. + *port_addr = urb->dev->ttport;
  41962. + }
  41963. + return 0;
  41964. +}
  41965. +
  41966. +static int _speed(dwc_otg_hcd_t * hcd, void *urb_handle)
  41967. +{
  41968. + struct urb *urb = (struct urb *)urb_handle;
  41969. + return urb->dev->speed;
  41970. +}
  41971. +
  41972. +static int _get_b_hnp_enable(dwc_otg_hcd_t * hcd)
  41973. +{
  41974. + struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
  41975. + return usb_hcd->self.b_hnp_enable;
  41976. +}
  41977. +
  41978. +static void allocate_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
  41979. + struct urb *urb)
  41980. +{
  41981. + hcd_to_bus(hcd)->bandwidth_allocated += bw / urb->interval;
  41982. + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
  41983. + hcd_to_bus(hcd)->bandwidth_isoc_reqs++;
  41984. + } else {
  41985. + hcd_to_bus(hcd)->bandwidth_int_reqs++;
  41986. + }
  41987. +}
  41988. +
  41989. +static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
  41990. + struct urb *urb)
  41991. +{
  41992. + hcd_to_bus(hcd)->bandwidth_allocated -= bw / urb->interval;
  41993. + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
  41994. + hcd_to_bus(hcd)->bandwidth_isoc_reqs--;
  41995. + } else {
  41996. + hcd_to_bus(hcd)->bandwidth_int_reqs--;
  41997. + }
  41998. +}
  41999. +
  42000. +/**
  42001. + * Sets the final status of an URB and returns it to the device driver. Any
  42002. + * required cleanup of the URB is performed.
  42003. + */
  42004. +static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
  42005. + dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status)
  42006. +{
  42007. + struct urb *urb = (struct urb *)urb_handle;
  42008. +
  42009. + if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
  42010. + DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n",
  42011. + __func__, urb, usb_pipedevice(urb->pipe),
  42012. + usb_pipeendpoint(urb->pipe),
  42013. + usb_pipein(urb->pipe) ? "IN" : "OUT", status);
  42014. + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
  42015. + int i;
  42016. + for (i = 0; i < urb->number_of_packets; i++) {
  42017. + DWC_PRINTF(" ISO Desc %d status: %d\n",
  42018. + i, urb->iso_frame_desc[i].status);
  42019. + }
  42020. + }
  42021. + }
  42022. +
  42023. + urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb);
  42024. + /* Convert status value. */
  42025. + switch (status) {
  42026. + case -DWC_E_PROTOCOL:
  42027. + status = -EPROTO;
  42028. + break;
  42029. + case -DWC_E_IN_PROGRESS:
  42030. + status = -EINPROGRESS;
  42031. + break;
  42032. + case -DWC_E_PIPE:
  42033. + status = -EPIPE;
  42034. + break;
  42035. + case -DWC_E_IO:
  42036. + status = -EIO;
  42037. + break;
  42038. + case -DWC_E_TIMEOUT:
  42039. + status = -ETIMEDOUT;
  42040. + break;
  42041. + case -DWC_E_OVERFLOW:
  42042. + status = -EOVERFLOW;
  42043. + break;
  42044. + default:
  42045. + if (status) {
  42046. + DWC_PRINTF("Uknown urb status %d\n", status);
  42047. +
  42048. + }
  42049. + }
  42050. +
  42051. + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
  42052. + int i;
  42053. +
  42054. + urb->error_count = dwc_otg_hcd_urb_get_error_count(dwc_otg_urb);
  42055. + for (i = 0; i < urb->number_of_packets; ++i) {
  42056. + urb->iso_frame_desc[i].actual_length =
  42057. + dwc_otg_hcd_urb_get_iso_desc_actual_length
  42058. + (dwc_otg_urb, i);
  42059. + urb->iso_frame_desc[i].status =
  42060. + dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_urb, i);
  42061. + }
  42062. + }
  42063. +
  42064. + urb->status = status;
  42065. + urb->hcpriv = NULL;
  42066. + if (!status) {
  42067. + if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
  42068. + (urb->actual_length < urb->transfer_buffer_length)) {
  42069. + urb->status = -EREMOTEIO;
  42070. + }
  42071. + }
  42072. +
  42073. + if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) ||
  42074. + (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
  42075. + struct usb_host_endpoint *ep = dwc_urb_to_endpoint(urb);
  42076. + if (ep) {
  42077. + free_bus_bandwidth(dwc_otg_hcd_to_hcd(hcd),
  42078. + dwc_otg_hcd_get_ep_bandwidth(hcd,
  42079. + ep->hcpriv),
  42080. + urb);
  42081. + }
  42082. + }
  42083. +
  42084. + DWC_FREE(dwc_otg_urb);
  42085. +
  42086. +#if USB_URB_EP_LINKING
  42087. + usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
  42088. +#endif
  42089. + DWC_SPINUNLOCK(hcd->lock);
  42090. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
  42091. + usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);
  42092. +#else
  42093. + usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status);
  42094. +#endif
  42095. + DWC_SPINLOCK(hcd->lock);
  42096. +
  42097. + return 0;
  42098. +}
  42099. +
  42100. +static struct dwc_otg_hcd_function_ops hcd_fops = {
  42101. + .start = _start,
  42102. + .disconnect = _disconnect,
  42103. + .hub_info = _hub_info,
  42104. + .speed = _speed,
  42105. + .complete = _complete,
  42106. + .get_b_hnp_enable = _get_b_hnp_enable,
  42107. +};
  42108. +
  42109. +/**
  42110. + * Initializes the HCD. This function allocates memory for and initializes the
  42111. + * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the
  42112. + * USB bus with the core and calls the hc_driver->start() function. It returns
  42113. + * a negative error on failure.
  42114. + */
  42115. +int hcd_init(dwc_bus_dev_t *_dev)
  42116. +{
  42117. + struct usb_hcd *hcd = NULL;
  42118. + dwc_otg_hcd_t *dwc_otg_hcd = NULL;
  42119. + dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
  42120. + int retval = 0;
  42121. + u64 dmamask;
  42122. +
  42123. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT otg_dev=%p\n", otg_dev);
  42124. +
  42125. + /* Set device flags indicating whether the HCD supports DMA. */
  42126. + if (dwc_otg_is_dma_enable(otg_dev->core_if))
  42127. + dmamask = DMA_BIT_MASK(32);
  42128. + else
  42129. + dmamask = 0;
  42130. +
  42131. +#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE)
  42132. + dma_set_mask(&_dev->dev, dmamask);
  42133. + dma_set_coherent_mask(&_dev->dev, dmamask);
  42134. +#elif defined(PCI_INTERFACE)
  42135. + pci_set_dma_mask(_dev, dmamask);
  42136. + pci_set_consistent_dma_mask(_dev, dmamask);
  42137. +#endif
  42138. +
  42139. + /*
  42140. + * Allocate memory for the base HCD plus the DWC OTG HCD.
  42141. + * Initialize the base HCD.
  42142. + */
  42143. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
  42144. + hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, _dev->dev.bus_id);
  42145. +#else
  42146. + hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, dev_name(&_dev->dev));
  42147. + hcd->has_tt = 1;
  42148. +// hcd->uses_new_polling = 1;
  42149. +// hcd->poll_rh = 0;
  42150. +#endif
  42151. + if (!hcd) {
  42152. + retval = -ENOMEM;
  42153. + goto error1;
  42154. + }
  42155. +
  42156. + hcd->regs = otg_dev->os_dep.base;
  42157. +
  42158. + /* Initialize the DWC OTG HCD. */
  42159. + dwc_otg_hcd = dwc_otg_hcd_alloc_hcd();
  42160. + if (!dwc_otg_hcd) {
  42161. + goto error2;
  42162. + }
  42163. + ((struct wrapper_priv_data *)(hcd->hcd_priv))->dwc_otg_hcd =
  42164. + dwc_otg_hcd;
  42165. + otg_dev->hcd = dwc_otg_hcd;
  42166. +
  42167. + if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) {
  42168. + goto error2;
  42169. + }
  42170. +
  42171. + otg_dev->hcd->otg_dev = otg_dev;
  42172. + hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd);
  42173. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel)
  42174. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) //version field absent later
  42175. + hcd->self.otg_version = dwc_otg_get_otg_version(otg_dev->core_if);
  42176. +#endif
  42177. + /* Don't support SG list at this point */
  42178. + hcd->self.sg_tablesize = 0;
  42179. +#endif
  42180. + /*
  42181. + * Finish generic HCD initialization and start the HCD. This function
  42182. + * allocates the DMA buffer pool, registers the USB bus, requests the
  42183. + * IRQ line, and calls hcd_start method.
  42184. + */
  42185. +#ifdef PLATFORM_INTERFACE
  42186. + retval = usb_add_hcd(hcd, platform_get_irq(_dev, 0), IRQF_SHARED | IRQF_DISABLED);
  42187. +#else
  42188. + retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED | IRQF_DISABLED);
  42189. +#endif
  42190. + if (retval < 0) {
  42191. + goto error2;
  42192. + }
  42193. +
  42194. + dwc_otg_hcd_set_priv_data(dwc_otg_hcd, hcd);
  42195. + return 0;
  42196. +
  42197. +error2:
  42198. + usb_put_hcd(hcd);
  42199. +error1:
  42200. + return retval;
  42201. +}
  42202. +
  42203. +/**
  42204. + * Removes the HCD.
  42205. + * Frees memory and resources associated with the HCD and deregisters the bus.
  42206. + */
  42207. +void hcd_remove(dwc_bus_dev_t *_dev)
  42208. +{
  42209. + dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
  42210. + dwc_otg_hcd_t *dwc_otg_hcd;
  42211. + struct usb_hcd *hcd;
  42212. +
  42213. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD REMOVE otg_dev=%p\n", otg_dev);
  42214. +
  42215. + if (!otg_dev) {
  42216. + DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);
  42217. + return;
  42218. + }
  42219. +
  42220. + dwc_otg_hcd = otg_dev->hcd;
  42221. +
  42222. + if (!dwc_otg_hcd) {
  42223. + DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__);
  42224. + return;
  42225. + }
  42226. +
  42227. + hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd);
  42228. +
  42229. + if (!hcd) {
  42230. + DWC_DEBUGPL(DBG_ANY,
  42231. + "%s: dwc_otg_hcd_to_hcd(dwc_otg_hcd) NULL!\n",
  42232. + __func__);
  42233. + return;
  42234. + }
  42235. + usb_remove_hcd(hcd);
  42236. + dwc_otg_hcd_set_priv_data(dwc_otg_hcd, NULL);
  42237. + dwc_otg_hcd_remove(dwc_otg_hcd);
  42238. + usb_put_hcd(hcd);
  42239. +}
  42240. +
  42241. +/* =========================================================================
  42242. + * Linux HC Driver Functions
  42243. + * ========================================================================= */
  42244. +
  42245. +/** Initializes the DWC_otg controller and its root hub and prepares it for host
  42246. + * mode operation. Activates the root port. Returns 0 on success and a negative
  42247. + * error code on failure. */
  42248. +int hcd_start(struct usb_hcd *hcd)
  42249. +{
  42250. + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
  42251. + struct usb_bus *bus;
  42252. +
  42253. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n");
  42254. + bus = hcd_to_bus(hcd);
  42255. +
  42256. + hcd->state = HC_STATE_RUNNING;
  42257. + if (dwc_otg_hcd_start(dwc_otg_hcd, &hcd_fops)) {
  42258. + return 0;
  42259. + }
  42260. +
  42261. + /* Initialize and connect root hub if one is not already attached */
  42262. + if (bus->root_hub) {
  42263. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Has Root Hub\n");
  42264. + /* Inform the HUB driver to resume. */
  42265. + usb_hcd_resume_root_hub(hcd);
  42266. + }
  42267. +
  42268. + return 0;
  42269. +}
  42270. +
  42271. +/**
  42272. + * Halts the DWC_otg host mode operations in a clean manner. USB transfers are
  42273. + * stopped.
  42274. + */
  42275. +void hcd_stop(struct usb_hcd *hcd)
  42276. +{
  42277. + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
  42278. +
  42279. + dwc_otg_hcd_stop(dwc_otg_hcd);
  42280. +}
  42281. +
  42282. +/** Returns the current frame number. */
  42283. +static int get_frame_number(struct usb_hcd *hcd)
  42284. +{
  42285. + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
  42286. +
  42287. + return dwc_otg_hcd_get_frame_number(dwc_otg_hcd);
  42288. +}
  42289. +
  42290. +#ifdef DEBUG
  42291. +static void dump_urb_info(struct urb *urb, char *fn_name)
  42292. +{
  42293. + DWC_PRINTF("%s, urb %p\n", fn_name, urb);
  42294. + DWC_PRINTF(" Device address: %d\n", usb_pipedevice(urb->pipe));
  42295. + DWC_PRINTF(" Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe),
  42296. + (usb_pipein(urb->pipe) ? "IN" : "OUT"));
  42297. + DWC_PRINTF(" Endpoint type: %s\n", ( {
  42298. + char *pipetype;
  42299. + switch (usb_pipetype(urb->pipe)) {
  42300. +case PIPE_CONTROL:
  42301. +pipetype = "CONTROL"; break; case PIPE_BULK:
  42302. +pipetype = "BULK"; break; case PIPE_INTERRUPT:
  42303. +pipetype = "INTERRUPT"; break; case PIPE_ISOCHRONOUS:
  42304. +pipetype = "ISOCHRONOUS"; break; default:
  42305. + pipetype = "UNKNOWN"; break;};
  42306. + pipetype;}
  42307. + )) ;
  42308. + DWC_PRINTF(" Speed: %s\n", ( {
  42309. + char *speed; switch (urb->dev->speed) {
  42310. +case USB_SPEED_HIGH:
  42311. +speed = "HIGH"; break; case USB_SPEED_FULL:
  42312. +speed = "FULL"; break; case USB_SPEED_LOW:
  42313. +speed = "LOW"; break; default:
  42314. + speed = "UNKNOWN"; break;};
  42315. + speed;}
  42316. + )) ;
  42317. + DWC_PRINTF(" Max packet size: %d\n",
  42318. + usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)));
  42319. + DWC_PRINTF(" Data buffer length: %d\n", urb->transfer_buffer_length);
  42320. + DWC_PRINTF(" Transfer buffer: %p, Transfer DMA: %p\n",
  42321. + urb->transfer_buffer, (void *)urb->transfer_dma);
  42322. + DWC_PRINTF(" Setup buffer: %p, Setup DMA: %p\n",
  42323. + urb->setup_packet, (void *)urb->setup_dma);
  42324. + DWC_PRINTF(" Interval: %d\n", urb->interval);
  42325. + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
  42326. + int i;
  42327. + for (i = 0; i < urb->number_of_packets; i++) {
  42328. + DWC_PRINTF(" ISO Desc %d:\n", i);
  42329. + DWC_PRINTF(" offset: %d, length %d\n",
  42330. + urb->iso_frame_desc[i].offset,
  42331. + urb->iso_frame_desc[i].length);
  42332. + }
  42333. + }
  42334. +}
  42335. +#endif
  42336. +
  42337. +/** Starts processing a USB transfer request specified by a USB Request Block
  42338. + * (URB). mem_flags indicates the type of memory allocation to use while
  42339. + * processing this URB. */
  42340. +static int dwc_otg_urb_enqueue(struct usb_hcd *hcd,
  42341. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
  42342. + struct usb_host_endpoint *ep,
  42343. +#endif
  42344. + struct urb *urb, gfp_t mem_flags)
  42345. +{
  42346. + int retval = 0;
  42347. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
  42348. + struct usb_host_endpoint *ep = urb->ep;
  42349. +#endif
  42350. +#if USB_URB_EP_LINKING
  42351. + dwc_irqflags_t irqflags;
  42352. +#endif
  42353. + void **ref_ep_hcpriv = &ep->hcpriv;
  42354. + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
  42355. + dwc_otg_hcd_urb_t *dwc_otg_urb;
  42356. + int i;
  42357. + int alloc_bandwidth = 0;
  42358. + uint8_t ep_type = 0;
  42359. + uint32_t flags = 0;
  42360. + void *buf;
  42361. +
  42362. +#ifdef DEBUG
  42363. + if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
  42364. + dump_urb_info(urb, "dwc_otg_urb_enqueue");
  42365. + }
  42366. +#endif
  42367. +
  42368. + if (!urb->transfer_buffer && urb->transfer_buffer_length)
  42369. + return -EINVAL;
  42370. +
  42371. + if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
  42372. + || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
  42373. + if (!dwc_otg_hcd_is_bandwidth_allocated
  42374. + (dwc_otg_hcd, ref_ep_hcpriv)) {
  42375. + alloc_bandwidth = 1;
  42376. + }
  42377. + }
  42378. +
  42379. + switch (usb_pipetype(urb->pipe)) {
  42380. + case PIPE_CONTROL:
  42381. + ep_type = USB_ENDPOINT_XFER_CONTROL;
  42382. + break;
  42383. + case PIPE_ISOCHRONOUS:
  42384. + ep_type = USB_ENDPOINT_XFER_ISOC;
  42385. + break;
  42386. + case PIPE_BULK:
  42387. + ep_type = USB_ENDPOINT_XFER_BULK;
  42388. + break;
  42389. + case PIPE_INTERRUPT:
  42390. + ep_type = USB_ENDPOINT_XFER_INT;
  42391. + break;
  42392. + default:
  42393. + DWC_WARN("Wrong EP type - %d\n", usb_pipetype(urb->pipe));
  42394. + }
  42395. +
  42396. + /* # of packets is often 0 - do we really need to call this then? */
  42397. + dwc_otg_urb = dwc_otg_hcd_urb_alloc(dwc_otg_hcd,
  42398. + urb->number_of_packets,
  42399. + mem_flags == GFP_ATOMIC ? 1 : 0);
  42400. +
  42401. + if(dwc_otg_urb == NULL)
  42402. + return -ENOMEM;
  42403. +
  42404. + urb->hcpriv = dwc_otg_urb;
  42405. + if (!dwc_otg_urb && urb->number_of_packets)
  42406. + return -ENOMEM;
  42407. +
  42408. + dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe),
  42409. + usb_pipeendpoint(urb->pipe), ep_type,
  42410. + usb_pipein(urb->pipe),
  42411. + usb_maxpacket(urb->dev, urb->pipe,
  42412. + !(usb_pipein(urb->pipe))));
  42413. +
  42414. + buf = urb->transfer_buffer;
  42415. + if (hcd->self.uses_dma) {
  42416. + /*
  42417. + * Calculate virtual address from physical address,
  42418. + * because some class driver may not fill transfer_buffer.
  42419. + * In Buffer DMA mode virual address is used,
  42420. + * when handling non DWORD aligned buffers.
  42421. + */
  42422. + //buf = phys_to_virt(urb->transfer_dma);
  42423. + // DMA addresses are bus addresses not physical addresses!
  42424. + buf = dma_to_virt(&urb->dev->dev, urb->transfer_dma);
  42425. + }
  42426. +
  42427. + if (!(urb->transfer_flags & URB_NO_INTERRUPT))
  42428. + flags |= URB_GIVEBACK_ASAP;
  42429. + if (urb->transfer_flags & URB_ZERO_PACKET)
  42430. + flags |= URB_SEND_ZERO_PACKET;
  42431. +
  42432. + dwc_otg_hcd_urb_set_params(dwc_otg_urb, urb, buf,
  42433. + urb->transfer_dma,
  42434. + urb->transfer_buffer_length,
  42435. + urb->setup_packet,
  42436. + urb->setup_dma, flags, urb->interval);
  42437. +
  42438. + for (i = 0; i < urb->number_of_packets; ++i) {
  42439. + dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_urb, i,
  42440. + urb->
  42441. + iso_frame_desc[i].offset,
  42442. + urb->
  42443. + iso_frame_desc[i].length);
  42444. + }
  42445. +
  42446. +#if USB_URB_EP_LINKING
  42447. + DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
  42448. + retval = usb_hcd_link_urb_to_ep(hcd, urb);
  42449. + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
  42450. + if (0 == retval)
  42451. +#endif
  42452. + {
  42453. + retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb,
  42454. + /*(dwc_otg_qh_t **)*/
  42455. + ref_ep_hcpriv,
  42456. + mem_flags == GFP_ATOMIC ? 1 : 0);
  42457. + if (0 == retval) {
  42458. + if (alloc_bandwidth) {
  42459. + allocate_bus_bandwidth(hcd,
  42460. + dwc_otg_hcd_get_ep_bandwidth(
  42461. + dwc_otg_hcd, *ref_ep_hcpriv),
  42462. + urb);
  42463. + }
  42464. + } else {
  42465. +#if USB_URB_EP_LINKING
  42466. + dwc_irqflags_t irqflags;
  42467. + DWC_DEBUGPL(DBG_HCD, "DWC OTG dwc_otg_hcd_urb_enqueue failed rc %d\n", retval);
  42468. + DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags);
  42469. + usb_hcd_unlink_urb_from_ep(hcd, urb);
  42470. + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
  42471. +#endif
  42472. + if (retval == -DWC_E_NO_DEVICE) {
  42473. + retval = -ENODEV;
  42474. + }
  42475. + }
  42476. + }
  42477. + return retval;
  42478. +}
  42479. +
  42480. +/** Aborts/cancels a USB transfer request. Always returns 0 to indicate
  42481. + * success. */
  42482. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
  42483. +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
  42484. +#else
  42485. +static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
  42486. +#endif
  42487. +{
  42488. + dwc_irqflags_t flags;
  42489. + dwc_otg_hcd_t *dwc_otg_hcd;
  42490. + int rc;
  42491. +
  42492. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n");
  42493. +
  42494. + dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
  42495. +
  42496. +#ifdef DEBUG
  42497. + if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
  42498. + dump_urb_info(urb, "dwc_otg_urb_dequeue");
  42499. + }
  42500. +#endif
  42501. +
  42502. + DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
  42503. + rc = usb_hcd_check_unlink_urb(hcd, urb, status);
  42504. + if (0 == rc) {
  42505. + if(urb->hcpriv != NULL) {
  42506. + dwc_otg_hcd_urb_dequeue(dwc_otg_hcd,
  42507. + (dwc_otg_hcd_urb_t *)urb->hcpriv);
  42508. +
  42509. + DWC_FREE(urb->hcpriv);
  42510. + urb->hcpriv = NULL;
  42511. + }
  42512. + }
  42513. +
  42514. + if (0 == rc) {
  42515. + /* Higher layer software sets URB status. */
  42516. +#if USB_URB_EP_LINKING
  42517. + usb_hcd_unlink_urb_from_ep(hcd, urb);
  42518. +#endif
  42519. + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
  42520. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
  42521. + usb_hcd_giveback_urb(hcd, urb);
  42522. +#else
  42523. + usb_hcd_giveback_urb(hcd, urb, status);
  42524. +#endif
  42525. + if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
  42526. + DWC_PRINTF("Called usb_hcd_giveback_urb() \n");
  42527. + DWC_PRINTF(" 1urb->status = %d\n", urb->status);
  42528. + }
  42529. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue OK\n");
  42530. + } else {
  42531. + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
  42532. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue failed - rc %d\n",
  42533. + rc);
  42534. + }
  42535. +
  42536. + return rc;
  42537. +}
  42538. +
  42539. +/* Frees resources in the DWC_otg controller related to a given endpoint. Also
  42540. + * clears state in the HCD related to the endpoint. Any URBs for the endpoint
  42541. + * must already be dequeued. */
  42542. +static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
  42543. +{
  42544. + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
  42545. +
  42546. + DWC_DEBUGPL(DBG_HCD,
  42547. + "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, "
  42548. + "endpoint=%d\n", ep->desc.bEndpointAddress,
  42549. + dwc_ep_addr_to_endpoint(ep->desc.bEndpointAddress));
  42550. + dwc_otg_hcd_endpoint_disable(dwc_otg_hcd, ep->hcpriv, 250);
  42551. + ep->hcpriv = NULL;
  42552. +}
  42553. +
  42554. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
  42555. +/* Resets endpoint specific parameter values, in current version used to reset
  42556. + * the data toggle(as a WA). This function can be called from usb_clear_halt routine */
  42557. +static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
  42558. +{
  42559. + dwc_irqflags_t flags;
  42560. + struct usb_device *udev = NULL;
  42561. + int epnum = usb_endpoint_num(&ep->desc);
  42562. + int is_out = usb_endpoint_dir_out(&ep->desc);
  42563. + int is_control = usb_endpoint_xfer_control(&ep->desc);
  42564. + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
  42565. + struct device *dev = DWC_OTG_OS_GETDEV(dwc_otg_hcd->otg_dev->os_dep);
  42566. +
  42567. + if (dev)
  42568. + udev = to_usb_device(dev);
  42569. + else
  42570. + return;
  42571. +
  42572. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD EP RESET: Endpoint Num=0x%02d\n", epnum);
  42573. +
  42574. + DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
  42575. + usb_settoggle(udev, epnum, is_out, 0);
  42576. + if (is_control)
  42577. + usb_settoggle(udev, epnum, !is_out, 0);
  42578. +
  42579. + if (ep->hcpriv) {
  42580. + dwc_otg_hcd_endpoint_reset(dwc_otg_hcd, ep->hcpriv);
  42581. + }
  42582. + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
  42583. +}
  42584. +#endif
  42585. +
  42586. +/** Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if
  42587. + * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid
  42588. + * interrupt.
  42589. + *
  42590. + * This function is called by the USB core when an interrupt occurs */
  42591. +static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd)
  42592. +{
  42593. + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
  42594. + int32_t retval = dwc_otg_hcd_handle_intr(dwc_otg_hcd);
  42595. + if (retval != 0) {
  42596. + S3C2410X_CLEAR_EINTPEND();
  42597. + }
  42598. + return IRQ_RETVAL(retval);
  42599. +}
  42600. +
  42601. +/** Creates Status Change bitmap for the root hub and root port. The bitmap is
  42602. + * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1
  42603. + * is the status change indicator for the single root port. Returns 1 if either
  42604. + * change indicator is 1, otherwise returns 0. */
  42605. +int hub_status_data(struct usb_hcd *hcd, char *buf)
  42606. +{
  42607. + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
  42608. +
  42609. + buf[0] = 0;
  42610. + buf[0] |= (dwc_otg_hcd_is_status_changed(dwc_otg_hcd, 1)) << 1;
  42611. +
  42612. + return (buf[0] != 0);
  42613. +}
  42614. +
  42615. +/** Handles hub class-specific requests. */
  42616. +int hub_control(struct usb_hcd *hcd,
  42617. + u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength)
  42618. +{
  42619. + int retval;
  42620. +
  42621. + retval = dwc_otg_hcd_hub_control(hcd_to_dwc_otg_hcd(hcd),
  42622. + typeReq, wValue, wIndex, buf, wLength);
  42623. +
  42624. + switch (retval) {
  42625. + case -DWC_E_INVALID:
  42626. + retval = -EINVAL;
  42627. + break;
  42628. + }
  42629. +
  42630. + return retval;
  42631. +}
  42632. +
  42633. +#endif /* DWC_DEVICE_ONLY */
  42634. --- /dev/null
  42635. +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
  42636. @@ -0,0 +1,923 @@
  42637. +/* ==========================================================================
  42638. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $
  42639. + * $Revision: #44 $
  42640. + * $Date: 2011/10/26 $
  42641. + * $Change: 1873028 $
  42642. + *
  42643. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  42644. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  42645. + * otherwise expressly agreed to in writing between Synopsys and you.
  42646. + *
  42647. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  42648. + * any End User Software License Agreement or Agreement for Licensed Product
  42649. + * with Synopsys or any supplement thereto. You are permitted to use and
  42650. + * redistribute this Software in source and binary forms, with or without
  42651. + * modification, provided that redistributions of source code must retain this
  42652. + * notice. You may not view, use, disclose, copy or distribute this file or
  42653. + * any information contained herein except pursuant to this license grant from
  42654. + * Synopsys. If you do not agree with this notice, including the disclaimer
  42655. + * below, then you are not authorized to use the Software.
  42656. + *
  42657. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  42658. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  42659. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  42660. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  42661. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  42662. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  42663. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  42664. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  42665. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  42666. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  42667. + * DAMAGE.
  42668. + * ========================================================================== */
  42669. +#ifndef DWC_DEVICE_ONLY
  42670. +
  42671. +/**
  42672. + * @file
  42673. + *
  42674. + * This file contains the functions to manage Queue Heads and Queue
  42675. + * Transfer Descriptors.
  42676. + */
  42677. +
  42678. +#include "dwc_otg_hcd.h"
  42679. +#include "dwc_otg_regs.h"
  42680. +
  42681. +extern bool microframe_schedule;
  42682. +
  42683. +/**
  42684. + * Free each QTD in the QH's QTD-list then free the QH. QH should already be
  42685. + * removed from a list. QTD list should already be empty if called from URB
  42686. + * Dequeue.
  42687. + *
  42688. + * @param hcd HCD instance.
  42689. + * @param qh The QH to free.
  42690. + */
  42691. +void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
  42692. +{
  42693. + dwc_otg_qtd_t *qtd, *qtd_tmp;
  42694. + dwc_irqflags_t flags;
  42695. +
  42696. + /* Free each QTD in the QTD list */
  42697. + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
  42698. + DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) {
  42699. + DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry);
  42700. + dwc_otg_hcd_qtd_free(qtd);
  42701. + }
  42702. +
  42703. + if (hcd->core_if->dma_desc_enable) {
  42704. + dwc_otg_hcd_qh_free_ddma(hcd, qh);
  42705. + } else if (qh->dw_align_buf) {
  42706. + uint32_t buf_size;
  42707. + if (qh->ep_type == UE_ISOCHRONOUS) {
  42708. + buf_size = 4096;
  42709. + } else {
  42710. + buf_size = hcd->core_if->core_params->max_transfer_size;
  42711. + }
  42712. + DWC_DMA_FREE(buf_size, qh->dw_align_buf, qh->dw_align_buf_dma);
  42713. + }
  42714. +
  42715. + DWC_FREE(qh);
  42716. + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
  42717. + return;
  42718. +}
  42719. +
  42720. +#define BitStuffTime(bytecount) ((8 * 7* bytecount) / 6)
  42721. +#define HS_HOST_DELAY 5 /* nanoseconds */
  42722. +#define FS_LS_HOST_DELAY 1000 /* nanoseconds */
  42723. +#define HUB_LS_SETUP 333 /* nanoseconds */
  42724. +#define NS_TO_US(ns) ((ns + 500) / 1000)
  42725. + /* convert & round nanoseconds to microseconds */
  42726. +
  42727. +static uint32_t calc_bus_time(int speed, int is_in, int is_isoc, int bytecount)
  42728. +{
  42729. + unsigned long retval;
  42730. +
  42731. + switch (speed) {
  42732. + case USB_SPEED_HIGH:
  42733. + if (is_isoc) {
  42734. + retval =
  42735. + ((38 * 8 * 2083) +
  42736. + (2083 * (3 + BitStuffTime(bytecount)))) / 1000 +
  42737. + HS_HOST_DELAY;
  42738. + } else {
  42739. + retval =
  42740. + ((55 * 8 * 2083) +
  42741. + (2083 * (3 + BitStuffTime(bytecount)))) / 1000 +
  42742. + HS_HOST_DELAY;
  42743. + }
  42744. + break;
  42745. + case USB_SPEED_FULL:
  42746. + if (is_isoc) {
  42747. + retval =
  42748. + (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000;
  42749. + if (is_in) {
  42750. + retval = 7268 + FS_LS_HOST_DELAY + retval;
  42751. + } else {
  42752. + retval = 6265 + FS_LS_HOST_DELAY + retval;
  42753. + }
  42754. + } else {
  42755. + retval =
  42756. + (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000;
  42757. + retval = 9107 + FS_LS_HOST_DELAY + retval;
  42758. + }
  42759. + break;
  42760. + case USB_SPEED_LOW:
  42761. + if (is_in) {
  42762. + retval =
  42763. + (67667 * (31 + 10 * BitStuffTime(bytecount))) /
  42764. + 1000;
  42765. + retval =
  42766. + 64060 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY +
  42767. + retval;
  42768. + } else {
  42769. + retval =
  42770. + (66700 * (31 + 10 * BitStuffTime(bytecount))) /
  42771. + 1000;
  42772. + retval =
  42773. + 64107 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY +
  42774. + retval;
  42775. + }
  42776. + break;
  42777. + default:
  42778. + DWC_WARN("Unknown device speed\n");
  42779. + retval = -1;
  42780. + }
  42781. +
  42782. + return NS_TO_US(retval);
  42783. +}
  42784. +
  42785. +/**
  42786. + * Initializes a QH structure.
  42787. + *
  42788. + * @param hcd The HCD state structure for the DWC OTG controller.
  42789. + * @param qh The QH to init.
  42790. + * @param urb Holds the information about the device/endpoint that we need
  42791. + * to initialize the QH.
  42792. + */
  42793. +#define SCHEDULE_SLOP 10
  42794. +void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb)
  42795. +{
  42796. + char *speed, *type;
  42797. + int dev_speed;
  42798. + uint32_t hub_addr, hub_port;
  42799. +
  42800. + dwc_memset(qh, 0, sizeof(dwc_otg_qh_t));
  42801. +
  42802. + /* Initialize QH */
  42803. + qh->ep_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
  42804. + qh->ep_is_in = dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0;
  42805. +
  42806. + qh->data_toggle = DWC_OTG_HC_PID_DATA0;
  42807. + qh->maxp = dwc_otg_hcd_get_mps(&urb->pipe_info);
  42808. + DWC_CIRCLEQ_INIT(&qh->qtd_list);
  42809. + DWC_LIST_INIT(&qh->qh_list_entry);
  42810. + qh->channel = NULL;
  42811. +
  42812. + /* FS/LS Enpoint on HS Hub
  42813. + * NOT virtual root hub */
  42814. + dev_speed = hcd->fops->speed(hcd, urb->priv);
  42815. +
  42816. + hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &hub_port);
  42817. + qh->do_split = 0;
  42818. + if (microframe_schedule)
  42819. + qh->speed = dev_speed;
  42820. +
  42821. +
  42822. + if (((dev_speed == USB_SPEED_LOW) ||
  42823. + (dev_speed == USB_SPEED_FULL)) &&
  42824. + (hub_addr != 0 && hub_addr != 1)) {
  42825. + DWC_DEBUGPL(DBG_HCD,
  42826. + "QH init: EP %d: TT found at hub addr %d, for port %d\n",
  42827. + dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr,
  42828. + hub_port);
  42829. + qh->do_split = 1;
  42830. + }
  42831. +
  42832. + if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) {
  42833. + /* Compute scheduling parameters once and save them. */
  42834. + hprt0_data_t hprt;
  42835. +
  42836. + /** @todo Account for split transfers in the bus time. */
  42837. + int bytecount =
  42838. + dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp);
  42839. +
  42840. + qh->usecs =
  42841. + calc_bus_time((qh->do_split ? USB_SPEED_HIGH : dev_speed),
  42842. + qh->ep_is_in, (qh->ep_type == UE_ISOCHRONOUS),
  42843. + bytecount);
  42844. + /* Start in a slightly future (micro)frame. */
  42845. + qh->sched_frame = dwc_frame_num_inc(hcd->frame_number,
  42846. + SCHEDULE_SLOP);
  42847. + qh->interval = urb->interval;
  42848. +
  42849. +#if 0
  42850. + /* Increase interrupt polling rate for debugging. */
  42851. + if (qh->ep_type == UE_INTERRUPT) {
  42852. + qh->interval = 8;
  42853. + }
  42854. +#endif
  42855. + hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0);
  42856. + if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) &&
  42857. + ((dev_speed == USB_SPEED_LOW) ||
  42858. + (dev_speed == USB_SPEED_FULL))) {
  42859. + qh->interval *= 8;
  42860. + qh->sched_frame |= 0x7;
  42861. + qh->start_split_frame = qh->sched_frame;
  42862. + }
  42863. +
  42864. + }
  42865. +
  42866. + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n");
  42867. + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - qh = %p\n", qh);
  42868. + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Device Address = %d\n",
  42869. + dwc_otg_hcd_get_dev_addr(&urb->pipe_info));
  42870. + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Endpoint %d, %s\n",
  42871. + dwc_otg_hcd_get_ep_num(&urb->pipe_info),
  42872. + dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT");
  42873. + switch (dev_speed) {
  42874. + case USB_SPEED_LOW:
  42875. + qh->dev_speed = DWC_OTG_EP_SPEED_LOW;
  42876. + speed = "low";
  42877. + break;
  42878. + case USB_SPEED_FULL:
  42879. + qh->dev_speed = DWC_OTG_EP_SPEED_FULL;
  42880. + speed = "full";
  42881. + break;
  42882. + case USB_SPEED_HIGH:
  42883. + qh->dev_speed = DWC_OTG_EP_SPEED_HIGH;
  42884. + speed = "high";
  42885. + break;
  42886. + default:
  42887. + speed = "?";
  42888. + break;
  42889. + }
  42890. + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Speed = %s\n", speed);
  42891. +
  42892. + switch (qh->ep_type) {
  42893. + case UE_ISOCHRONOUS:
  42894. + type = "isochronous";
  42895. + break;
  42896. + case UE_INTERRUPT:
  42897. + type = "interrupt";
  42898. + break;
  42899. + case UE_CONTROL:
  42900. + type = "control";
  42901. + break;
  42902. + case UE_BULK:
  42903. + type = "bulk";
  42904. + break;
  42905. + default:
  42906. + type = "?";
  42907. + break;
  42908. + }
  42909. +
  42910. + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Type = %s\n", type);
  42911. +
  42912. +#ifdef DEBUG
  42913. + if (qh->ep_type == UE_INTERRUPT) {
  42914. + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - usecs = %d\n",
  42915. + qh->usecs);
  42916. + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - interval = %d\n",
  42917. + qh->interval);
  42918. + }
  42919. +#endif
  42920. +
  42921. +}
  42922. +
  42923. +/**
  42924. + * This function allocates and initializes a QH.
  42925. + *
  42926. + * @param hcd The HCD state structure for the DWC OTG controller.
  42927. + * @param urb Holds the information about the device/endpoint that we need
  42928. + * to initialize the QH.
  42929. + * @param atomic_alloc Flag to do atomic allocation if needed
  42930. + *
  42931. + * @return Returns pointer to the newly allocated QH, or NULL on error. */
  42932. +dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd,
  42933. + dwc_otg_hcd_urb_t * urb, int atomic_alloc)
  42934. +{
  42935. + dwc_otg_qh_t *qh;
  42936. +
  42937. + /* Allocate memory */
  42938. + /** @todo add memflags argument */
  42939. + qh = dwc_otg_hcd_qh_alloc(atomic_alloc);
  42940. + if (qh == NULL) {
  42941. + DWC_ERROR("qh allocation failed");
  42942. + return NULL;
  42943. + }
  42944. +
  42945. + qh_init(hcd, qh, urb);
  42946. +
  42947. + if (hcd->core_if->dma_desc_enable
  42948. + && (dwc_otg_hcd_qh_init_ddma(hcd, qh) < 0)) {
  42949. + dwc_otg_hcd_qh_free(hcd, qh);
  42950. + return NULL;
  42951. + }
  42952. +
  42953. + return qh;
  42954. +}
  42955. +
  42956. +/* microframe_schedule=0 start */
  42957. +
  42958. +/**
  42959. + * Checks that a channel is available for a periodic transfer.
  42960. + *
  42961. + * @return 0 if successful, negative error code otherise.
  42962. + */
  42963. +static int periodic_channel_available(dwc_otg_hcd_t * hcd)
  42964. +{
  42965. + /*
  42966. + * Currently assuming that there is a dedicated host channnel for each
  42967. + * periodic transaction plus at least one host channel for
  42968. + * non-periodic transactions.
  42969. + */
  42970. + int status;
  42971. + int num_channels;
  42972. +
  42973. + num_channels = hcd->core_if->core_params->host_channels;
  42974. + if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels)
  42975. + && (hcd->periodic_channels < num_channels - 1)) {
  42976. + status = 0;
  42977. + } else {
  42978. + DWC_INFO("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n",
  42979. + __func__, num_channels, hcd->periodic_channels, hcd->non_periodic_channels); //NOTICE
  42980. + status = -DWC_E_NO_SPACE;
  42981. + }
  42982. +
  42983. + return status;
  42984. +}
  42985. +
  42986. +/**
  42987. + * Checks that there is sufficient bandwidth for the specified QH in the
  42988. + * periodic schedule. For simplicity, this calculation assumes that all the
  42989. + * transfers in the periodic schedule may occur in the same (micro)frame.
  42990. + *
  42991. + * @param hcd The HCD state structure for the DWC OTG controller.
  42992. + * @param qh QH containing periodic bandwidth required.
  42993. + *
  42994. + * @return 0 if successful, negative error code otherwise.
  42995. + */
  42996. +static int check_periodic_bandwidth(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
  42997. +{
  42998. + int status;
  42999. + int16_t max_claimed_usecs;
  43000. +
  43001. + status = 0;
  43002. +
  43003. + if ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) || qh->do_split) {
  43004. + /*
  43005. + * High speed mode.
  43006. + * Max periodic usecs is 80% x 125 usec = 100 usec.
  43007. + */
  43008. +
  43009. + max_claimed_usecs = 100 - qh->usecs;
  43010. + } else {
  43011. + /*
  43012. + * Full speed mode.
  43013. + * Max periodic usecs is 90% x 1000 usec = 900 usec.
  43014. + */
  43015. + max_claimed_usecs = 900 - qh->usecs;
  43016. + }
  43017. +
  43018. + if (hcd->periodic_usecs > max_claimed_usecs) {
  43019. + DWC_INFO("%s: already claimed usecs %d, required usecs %d\n", __func__, hcd->periodic_usecs, qh->usecs); //NOTICE
  43020. + status = -DWC_E_NO_SPACE;
  43021. + }
  43022. +
  43023. + return status;
  43024. +}
  43025. +
  43026. +/* microframe_schedule=0 end */
  43027. +
  43028. +/**
  43029. + * Microframe scheduler
  43030. + * track the total use in hcd->frame_usecs
  43031. + * keep each qh use in qh->frame_usecs
  43032. + * when surrendering the qh then donate the time back
  43033. + */
  43034. +const unsigned short max_uframe_usecs[]={ 100, 100, 100, 100, 100, 100, 30, 0 };
  43035. +
  43036. +/*
  43037. + * called from dwc_otg_hcd.c:dwc_otg_hcd_init
  43038. + */
  43039. +int init_hcd_usecs(dwc_otg_hcd_t *_hcd)
  43040. +{
  43041. + int i;
  43042. + for (i=0; i<8; i++) {
  43043. + _hcd->frame_usecs[i] = max_uframe_usecs[i];
  43044. + }
  43045. + return 0;
  43046. +}
  43047. +
  43048. +static int find_single_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
  43049. +{
  43050. + int i;
  43051. + unsigned short utime;
  43052. + int t_left;
  43053. + int ret;
  43054. + int done;
  43055. +
  43056. + ret = -1;
  43057. + utime = _qh->usecs;
  43058. + t_left = utime;
  43059. + i = 0;
  43060. + done = 0;
  43061. + while (done == 0) {
  43062. + /* At the start _hcd->frame_usecs[i] = max_uframe_usecs[i]; */
  43063. + if (utime <= _hcd->frame_usecs[i]) {
  43064. + _hcd->frame_usecs[i] -= utime;
  43065. + _qh->frame_usecs[i] += utime;
  43066. + t_left -= utime;
  43067. + ret = i;
  43068. + done = 1;
  43069. + return ret;
  43070. + } else {
  43071. + i++;
  43072. + if (i == 8) {
  43073. + done = 1;
  43074. + ret = -1;
  43075. + }
  43076. + }
  43077. + }
  43078. + return ret;
  43079. + }
  43080. +
  43081. +/*
  43082. + * use this for FS apps that can span multiple uframes
  43083. + */
  43084. +static int find_multi_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
  43085. +{
  43086. + int i;
  43087. + int j;
  43088. + unsigned short utime;
  43089. + int t_left;
  43090. + int ret;
  43091. + int done;
  43092. + unsigned short xtime;
  43093. +
  43094. + ret = -1;
  43095. + utime = _qh->usecs;
  43096. + t_left = utime;
  43097. + i = 0;
  43098. + done = 0;
  43099. +loop:
  43100. + while (done == 0) {
  43101. + if(_hcd->frame_usecs[i] <= 0) {
  43102. + i++;
  43103. + if (i == 8) {
  43104. + done = 1;
  43105. + ret = -1;
  43106. + }
  43107. + goto loop;
  43108. + }
  43109. +
  43110. + /*
  43111. + * we need n consecutive slots
  43112. + * so use j as a start slot j plus j+1 must be enough time (for now)
  43113. + */
  43114. + xtime= _hcd->frame_usecs[i];
  43115. + for (j = i+1 ; j < 8 ; j++ ) {
  43116. + /*
  43117. + * if we add this frame remaining time to xtime we may
  43118. + * be OK, if not we need to test j for a complete frame
  43119. + */
  43120. + if ((xtime+_hcd->frame_usecs[j]) < utime) {
  43121. + if (_hcd->frame_usecs[j] < max_uframe_usecs[j]) {
  43122. + j = 8;
  43123. + ret = -1;
  43124. + continue;
  43125. + }
  43126. + }
  43127. + if (xtime >= utime) {
  43128. + ret = i;
  43129. + j = 8; /* stop loop with a good value ret */
  43130. + continue;
  43131. + }
  43132. + /* add the frame time to x time */
  43133. + xtime += _hcd->frame_usecs[j];
  43134. + /* we must have a fully available next frame or break */
  43135. + if ((xtime < utime)
  43136. + && (_hcd->frame_usecs[j] == max_uframe_usecs[j])) {
  43137. + ret = -1;
  43138. + j = 8; /* stop loop with a bad value ret */
  43139. + continue;
  43140. + }
  43141. + }
  43142. + if (ret >= 0) {
  43143. + t_left = utime;
  43144. + for (j = i; (t_left>0) && (j < 8); j++ ) {
  43145. + t_left -= _hcd->frame_usecs[j];
  43146. + if ( t_left <= 0 ) {
  43147. + _qh->frame_usecs[j] += _hcd->frame_usecs[j] + t_left;
  43148. + _hcd->frame_usecs[j]= -t_left;
  43149. + ret = i;
  43150. + done = 1;
  43151. + } else {
  43152. + _qh->frame_usecs[j] += _hcd->frame_usecs[j];
  43153. + _hcd->frame_usecs[j] = 0;
  43154. + }
  43155. + }
  43156. + } else {
  43157. + i++;
  43158. + if (i == 8) {
  43159. + done = 1;
  43160. + ret = -1;
  43161. + }
  43162. + }
  43163. + }
  43164. + return ret;
  43165. +}
  43166. +
  43167. +static int find_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh)
  43168. +{
  43169. + int ret;
  43170. + ret = -1;
  43171. +
  43172. + if (_qh->speed == USB_SPEED_HIGH) {
  43173. + /* if this is a hs transaction we need a full frame */
  43174. + ret = find_single_uframe(_hcd, _qh);
  43175. + } else {
  43176. + /* if this is a fs transaction we may need a sequence of frames */
  43177. + ret = find_multi_uframe(_hcd, _qh);
  43178. + }
  43179. + return ret;
  43180. +}
  43181. +
  43182. +/**
  43183. + * Checks that the max transfer size allowed in a host channel is large enough
  43184. + * to handle the maximum data transfer in a single (micro)frame for a periodic
  43185. + * transfer.
  43186. + *
  43187. + * @param hcd The HCD state structure for the DWC OTG controller.
  43188. + * @param qh QH for a periodic endpoint.
  43189. + *
  43190. + * @return 0 if successful, negative error code otherwise.
  43191. + */
  43192. +static int check_max_xfer_size(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
  43193. +{
  43194. + int status;
  43195. + uint32_t max_xfer_size;
  43196. + uint32_t max_channel_xfer_size;
  43197. +
  43198. + status = 0;
  43199. +
  43200. + max_xfer_size = dwc_max_packet(qh->maxp) * dwc_hb_mult(qh->maxp);
  43201. + max_channel_xfer_size = hcd->core_if->core_params->max_transfer_size;
  43202. +
  43203. + if (max_xfer_size > max_channel_xfer_size) {
  43204. + DWC_INFO("%s: Periodic xfer length %d > " "max xfer length for channel %d\n",
  43205. + __func__, max_xfer_size, max_channel_xfer_size); //NOTICE
  43206. + status = -DWC_E_NO_SPACE;
  43207. + }
  43208. +
  43209. + return status;
  43210. +}
  43211. +
  43212. +/**
  43213. + * Schedules an interrupt or isochronous transfer in the periodic schedule.
  43214. + *
  43215. + * @param hcd The HCD state structure for the DWC OTG controller.
  43216. + * @param qh QH for the periodic transfer. The QH should already contain the
  43217. + * scheduling information.
  43218. + *
  43219. + * @return 0 if successful, negative error code otherwise.
  43220. + */
  43221. +static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
  43222. +{
  43223. + int status = 0;
  43224. +
  43225. + if (microframe_schedule) {
  43226. + int frame;
  43227. + status = find_uframe(hcd, qh);
  43228. + frame = -1;
  43229. + if (status == 0) {
  43230. + frame = 7;
  43231. + } else {
  43232. + if (status > 0 )
  43233. + frame = status-1;
  43234. + }
  43235. +
  43236. + /* Set the new frame up */
  43237. + if (frame > -1) {
  43238. + qh->sched_frame &= ~0x7;
  43239. + qh->sched_frame |= (frame & 7);
  43240. + }
  43241. +
  43242. + if (status != -1)
  43243. + status = 0;
  43244. + } else {
  43245. + status = periodic_channel_available(hcd);
  43246. + if (status) {
  43247. + DWC_INFO("%s: No host channel available for periodic " "transfer.\n", __func__); //NOTICE
  43248. + return status;
  43249. + }
  43250. +
  43251. + status = check_periodic_bandwidth(hcd, qh);
  43252. + }
  43253. + if (status) {
  43254. + DWC_INFO("%s: Insufficient periodic bandwidth for "
  43255. + "periodic transfer.\n", __func__);
  43256. + return status;
  43257. + }
  43258. + status = check_max_xfer_size(hcd, qh);
  43259. + if (status) {
  43260. + DWC_INFO("%s: Channel max transfer size too small "
  43261. + "for periodic transfer.\n", __func__);
  43262. + return status;
  43263. + }
  43264. +
  43265. + if (hcd->core_if->dma_desc_enable) {
  43266. + /* Don't rely on SOF and start in ready schedule */
  43267. + DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry);
  43268. + }
  43269. + else {
  43270. + /* Always start in the inactive schedule. */
  43271. + DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry);
  43272. + }
  43273. +
  43274. + if (!microframe_schedule) {
  43275. + /* Reserve the periodic channel. */
  43276. + hcd->periodic_channels++;
  43277. + }
  43278. +
  43279. + /* Update claimed usecs per (micro)frame. */
  43280. + hcd->periodic_usecs += qh->usecs;
  43281. +
  43282. + return status;
  43283. +}
  43284. +
  43285. +/**
  43286. + * This function adds a QH to either the non periodic or periodic schedule if
  43287. + * it is not already in the schedule. If the QH is already in the schedule, no
  43288. + * action is taken.
  43289. + *
  43290. + * @return 0 if successful, negative error code otherwise.
  43291. + */
  43292. +int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
  43293. +{
  43294. + int status = 0;
  43295. + gintmsk_data_t intr_mask = {.d32 = 0 };
  43296. +
  43297. + if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) {
  43298. + /* QH already in a schedule. */
  43299. + return status;
  43300. + }
  43301. +
  43302. + /* Add the new QH to the appropriate schedule */
  43303. + if (dwc_qh_is_non_per(qh)) {
  43304. + /* Always start in the inactive schedule. */
  43305. + DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive,
  43306. + &qh->qh_list_entry);
  43307. + } else {
  43308. + status = schedule_periodic(hcd, qh);
  43309. + if ( !hcd->periodic_qh_count ) {
  43310. + intr_mask.b.sofintr = 1;
  43311. + DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,
  43312. + intr_mask.d32, intr_mask.d32);
  43313. + }
  43314. + hcd->periodic_qh_count++;
  43315. + }
  43316. +
  43317. + return status;
  43318. +}
  43319. +
  43320. +/**
  43321. + * Removes an interrupt or isochronous transfer from the periodic schedule.
  43322. + *
  43323. + * @param hcd The HCD state structure for the DWC OTG controller.
  43324. + * @param qh QH for the periodic transfer.
  43325. + */
  43326. +static void deschedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
  43327. +{
  43328. + int i;
  43329. + DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
  43330. +
  43331. + /* Update claimed usecs per (micro)frame. */
  43332. + hcd->periodic_usecs -= qh->usecs;
  43333. +
  43334. + if (!microframe_schedule) {
  43335. + /* Release the periodic channel reservation. */
  43336. + hcd->periodic_channels--;
  43337. + } else {
  43338. + for (i = 0; i < 8; i++) {
  43339. + hcd->frame_usecs[i] += qh->frame_usecs[i];
  43340. + qh->frame_usecs[i] = 0;
  43341. + }
  43342. + }
  43343. +}
  43344. +
  43345. +/**
  43346. + * Removes a QH from either the non-periodic or periodic schedule. Memory is
  43347. + * not freed.
  43348. + *
  43349. + * @param hcd The HCD state structure.
  43350. + * @param qh QH to remove from schedule. */
  43351. +void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
  43352. +{
  43353. + gintmsk_data_t intr_mask = {.d32 = 0 };
  43354. +
  43355. + if (DWC_LIST_EMPTY(&qh->qh_list_entry)) {
  43356. + /* QH is not in a schedule. */
  43357. + return;
  43358. + }
  43359. +
  43360. + if (dwc_qh_is_non_per(qh)) {
  43361. + if (hcd->non_periodic_qh_ptr == &qh->qh_list_entry) {
  43362. + hcd->non_periodic_qh_ptr =
  43363. + hcd->non_periodic_qh_ptr->next;
  43364. + }
  43365. + DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
  43366. + } else {
  43367. + deschedule_periodic(hcd, qh);
  43368. + hcd->periodic_qh_count--;
  43369. + if( !hcd->periodic_qh_count ) {
  43370. + intr_mask.b.sofintr = 1;
  43371. + DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,
  43372. + intr_mask.d32, 0);
  43373. + }
  43374. + }
  43375. +}
  43376. +
  43377. +/**
  43378. + * Deactivates a QH. For non-periodic QHs, removes the QH from the active
  43379. + * non-periodic schedule. The QH is added to the inactive non-periodic
  43380. + * schedule if any QTDs are still attached to the QH.
  43381. + *
  43382. + * For periodic QHs, the QH is removed from the periodic queued schedule. If
  43383. + * there are any QTDs still attached to the QH, the QH is added to either the
  43384. + * periodic inactive schedule or the periodic ready schedule and its next
  43385. + * scheduled frame is calculated. The QH is placed in the ready schedule if
  43386. + * the scheduled frame has been reached already. Otherwise it's placed in the
  43387. + * inactive schedule. If there are no QTDs attached to the QH, the QH is
  43388. + * completely removed from the periodic schedule.
  43389. + */
  43390. +void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
  43391. + int sched_next_periodic_split)
  43392. +{
  43393. + if (dwc_qh_is_non_per(qh)) {
  43394. + dwc_otg_hcd_qh_remove(hcd, qh);
  43395. + if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
  43396. + /* Add back to inactive non-periodic schedule. */
  43397. + dwc_otg_hcd_qh_add(hcd, qh);
  43398. + }
  43399. + } else {
  43400. + uint16_t frame_number = dwc_otg_hcd_get_frame_number(hcd);
  43401. +
  43402. + if (qh->do_split) {
  43403. + /* Schedule the next continuing periodic split transfer */
  43404. + if (sched_next_periodic_split) {
  43405. +
  43406. + qh->sched_frame = frame_number;
  43407. + if (dwc_frame_num_le(frame_number,
  43408. + dwc_frame_num_inc
  43409. + (qh->start_split_frame,
  43410. + 1))) {
  43411. + /*
  43412. + * Allow one frame to elapse after start
  43413. + * split microframe before scheduling
  43414. + * complete split, but DONT if we are
  43415. + * doing the next start split in the
  43416. + * same frame for an ISOC out.
  43417. + */
  43418. + if ((qh->ep_type != UE_ISOCHRONOUS) ||
  43419. + (qh->ep_is_in != 0)) {
  43420. + qh->sched_frame =
  43421. + dwc_frame_num_inc(qh->sched_frame, 1);
  43422. + }
  43423. + }
  43424. + } else {
  43425. + qh->sched_frame =
  43426. + dwc_frame_num_inc(qh->start_split_frame,
  43427. + qh->interval);
  43428. + if (dwc_frame_num_le
  43429. + (qh->sched_frame, frame_number)) {
  43430. + qh->sched_frame = frame_number;
  43431. + }
  43432. + qh->sched_frame |= 0x7;
  43433. + qh->start_split_frame = qh->sched_frame;
  43434. + }
  43435. + } else {
  43436. + qh->sched_frame =
  43437. + dwc_frame_num_inc(qh->sched_frame, qh->interval);
  43438. + if (dwc_frame_num_le(qh->sched_frame, frame_number)) {
  43439. + qh->sched_frame = frame_number;
  43440. + }
  43441. + }
  43442. +
  43443. + if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
  43444. + dwc_otg_hcd_qh_remove(hcd, qh);
  43445. + } else {
  43446. + /*
  43447. + * Remove from periodic_sched_queued and move to
  43448. + * appropriate queue.
  43449. + */
  43450. + if ((microframe_schedule && dwc_frame_num_le(qh->sched_frame, frame_number)) ||
  43451. + (!microframe_schedule && qh->sched_frame == frame_number)) {
  43452. + DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
  43453. + &qh->qh_list_entry);
  43454. + } else {
  43455. + DWC_LIST_MOVE_HEAD
  43456. + (&hcd->periodic_sched_inactive,
  43457. + &qh->qh_list_entry);
  43458. + }
  43459. + }
  43460. + }
  43461. +}
  43462. +
  43463. +/**
  43464. + * This function allocates and initializes a QTD.
  43465. + *
  43466. + * @param urb The URB to create a QTD from. Each URB-QTD pair will end up
  43467. + * pointing to each other so each pair should have a unique correlation.
  43468. + * @param atomic_alloc Flag to do atomic alloc if needed
  43469. + *
  43470. + * @return Returns pointer to the newly allocated QTD, or NULL on error. */
  43471. +dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, int atomic_alloc)
  43472. +{
  43473. + dwc_otg_qtd_t *qtd;
  43474. +
  43475. + qtd = dwc_otg_hcd_qtd_alloc(atomic_alloc);
  43476. + if (qtd == NULL) {
  43477. + return NULL;
  43478. + }
  43479. +
  43480. + dwc_otg_hcd_qtd_init(qtd, urb);
  43481. + return qtd;
  43482. +}
  43483. +
  43484. +/**
  43485. + * Initializes a QTD structure.
  43486. + *
  43487. + * @param qtd The QTD to initialize.
  43488. + * @param urb The URB to use for initialization. */
  43489. +void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb)
  43490. +{
  43491. + dwc_memset(qtd, 0, sizeof(dwc_otg_qtd_t));
  43492. + qtd->urb = urb;
  43493. + if (dwc_otg_hcd_get_pipe_type(&urb->pipe_info) == UE_CONTROL) {
  43494. + /*
  43495. + * The only time the QTD data toggle is used is on the data
  43496. + * phase of control transfers. This phase always starts with
  43497. + * DATA1.
  43498. + */
  43499. + qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
  43500. + qtd->control_phase = DWC_OTG_CONTROL_SETUP;
  43501. + }
  43502. +
  43503. + /* start split */
  43504. + qtd->complete_split = 0;
  43505. + qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
  43506. + qtd->isoc_split_offset = 0;
  43507. + qtd->in_process = 0;
  43508. +
  43509. + /* Store the qtd ptr in the urb to reference what QTD. */
  43510. + urb->qtd = qtd;
  43511. + return;
  43512. +}
  43513. +
  43514. +/**
  43515. + * This function adds a QTD to the QTD-list of a QH. It will find the correct
  43516. + * QH to place the QTD into. If it does not find a QH, then it will create a
  43517. + * new QH. If the QH to which the QTD is added is not currently scheduled, it
  43518. + * is placed into the proper schedule based on its EP type.
  43519. + *
  43520. + * @param[in] qtd The QTD to add
  43521. + * @param[in] hcd The DWC HCD structure
  43522. + * @param[out] qh out parameter to return queue head
  43523. + * @param atomic_alloc Flag to do atomic alloc if needed
  43524. + *
  43525. + * @return 0 if successful, negative error code otherwise.
  43526. + */
  43527. +int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd,
  43528. + dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh, int atomic_alloc)
  43529. +{
  43530. + int retval = 0;
  43531. + dwc_irqflags_t flags;
  43532. +
  43533. + dwc_otg_hcd_urb_t *urb = qtd->urb;
  43534. +
  43535. + /*
  43536. + * Get the QH which holds the QTD-list to insert to. Create QH if it
  43537. + * doesn't exist.
  43538. + */
  43539. + if (*qh == NULL) {
  43540. + *qh = dwc_otg_hcd_qh_create(hcd, urb, atomic_alloc);
  43541. + if (*qh == NULL) {
  43542. + retval = -1;
  43543. + goto done;
  43544. + }
  43545. + }
  43546. + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
  43547. + retval = dwc_otg_hcd_qh_add(hcd, *qh);
  43548. + if (retval == 0) {
  43549. + DWC_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd,
  43550. + qtd_list_entry);
  43551. + }
  43552. + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
  43553. +
  43554. +done:
  43555. +
  43556. + return retval;
  43557. +}
  43558. +
  43559. +#endif /* DWC_DEVICE_ONLY */
  43560. --- /dev/null
  43561. +++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
  43562. @@ -0,0 +1,185 @@
  43563. +#ifndef _DWC_OS_DEP_H_
  43564. +#define _DWC_OS_DEP_H_
  43565. +
  43566. +/**
  43567. + * @file
  43568. + *
  43569. + * This file contains OS dependent structures.
  43570. + *
  43571. + */
  43572. +
  43573. +#include <linux/kernel.h>
  43574. +#include <linux/module.h>
  43575. +#include <linux/moduleparam.h>
  43576. +#include <linux/init.h>
  43577. +#include <linux/device.h>
  43578. +#include <linux/errno.h>
  43579. +#include <linux/types.h>
  43580. +#include <linux/slab.h>
  43581. +#include <linux/list.h>
  43582. +#include <linux/interrupt.h>
  43583. +#include <linux/ctype.h>
  43584. +#include <linux/string.h>
  43585. +#include <linux/dma-mapping.h>
  43586. +#include <linux/jiffies.h>
  43587. +#include <linux/delay.h>
  43588. +#include <linux/timer.h>
  43589. +#include <linux/workqueue.h>
  43590. +#include <linux/stat.h>
  43591. +#include <linux/pci.h>
  43592. +
  43593. +#include <linux/version.h>
  43594. +
  43595. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
  43596. +# include <linux/irq.h>
  43597. +#endif
  43598. +
  43599. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
  43600. +# include <linux/usb/ch9.h>
  43601. +#else
  43602. +# include <linux/usb_ch9.h>
  43603. +#endif
  43604. +
  43605. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
  43606. +# include <linux/usb/gadget.h>
  43607. +#else
  43608. +# include <linux/usb_gadget.h>
  43609. +#endif
  43610. +
  43611. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
  43612. +# include <asm/irq.h>
  43613. +#endif
  43614. +
  43615. +#ifdef PCI_INTERFACE
  43616. +# include <asm/io.h>
  43617. +#endif
  43618. +
  43619. +#ifdef LM_INTERFACE
  43620. +# include <asm/unaligned.h>
  43621. +# include <asm/sizes.h>
  43622. +# include <asm/param.h>
  43623. +# include <asm/io.h>
  43624. +# if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
  43625. +# include <asm/arch/hardware.h>
  43626. +# include <asm/arch/lm.h>
  43627. +# include <asm/arch/irqs.h>
  43628. +# include <asm/arch/regs-irq.h>
  43629. +# else
  43630. +/* in 2.6.31, at least, we seem to have lost the generic LM infrastructure -
  43631. + here we assume that the machine architecture provides definitions
  43632. + in its own header
  43633. +*/
  43634. +# include <mach/lm.h>
  43635. +# include <mach/hardware.h>
  43636. +# endif
  43637. +#endif
  43638. +
  43639. +#ifdef PLATFORM_INTERFACE
  43640. +#include <linux/platform_device.h>
  43641. +#include <asm/mach/map.h>
  43642. +#endif
  43643. +
  43644. +/** The OS page size */
  43645. +#define DWC_OS_PAGE_SIZE PAGE_SIZE
  43646. +
  43647. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
  43648. +typedef int gfp_t;
  43649. +#endif
  43650. +
  43651. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
  43652. +# define IRQF_SHARED SA_SHIRQ
  43653. +#endif
  43654. +
  43655. +typedef struct os_dependent {
  43656. + /** Base address returned from ioremap() */
  43657. + void *base;
  43658. +
  43659. + /** Register offset for Diagnostic API */
  43660. + uint32_t reg_offset;
  43661. +
  43662. +#ifdef LM_INTERFACE
  43663. + struct lm_device *lmdev;
  43664. +#elif defined(PCI_INTERFACE)
  43665. + struct pci_dev *pcidev;
  43666. +
  43667. + /** Start address of a PCI region */
  43668. + resource_size_t rsrc_start;
  43669. +
  43670. + /** Length address of a PCI region */
  43671. + resource_size_t rsrc_len;
  43672. +#elif defined(PLATFORM_INTERFACE)
  43673. + struct platform_device *platformdev;
  43674. +#endif
  43675. +
  43676. +} os_dependent_t;
  43677. +
  43678. +#ifdef __cplusplus
  43679. +}
  43680. +#endif
  43681. +
  43682. +
  43683. +
  43684. +/* Type for the our device on the chosen bus */
  43685. +#if defined(LM_INTERFACE)
  43686. +typedef struct lm_device dwc_bus_dev_t;
  43687. +#elif defined(PCI_INTERFACE)
  43688. +typedef struct pci_dev dwc_bus_dev_t;
  43689. +#elif defined(PLATFORM_INTERFACE)
  43690. +typedef struct platform_device dwc_bus_dev_t;
  43691. +#endif
  43692. +
  43693. +/* Helper macro to retrieve drvdata from the device on the chosen bus */
  43694. +#if defined(LM_INTERFACE)
  43695. +#define DWC_OTG_BUSDRVDATA(_dev) lm_get_drvdata(_dev)
  43696. +#elif defined(PCI_INTERFACE)
  43697. +#define DWC_OTG_BUSDRVDATA(_dev) pci_get_drvdata(_dev)
  43698. +#elif defined(PLATFORM_INTERFACE)
  43699. +#define DWC_OTG_BUSDRVDATA(_dev) platform_get_drvdata(_dev)
  43700. +#endif
  43701. +
  43702. +/**
  43703. + * Helper macro returning the otg_device structure of a given struct device
  43704. + *
  43705. + * c.f. static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev)
  43706. + */
  43707. +#ifdef LM_INTERFACE
  43708. +#define DWC_OTG_GETDRVDEV(_var, _dev) do { \
  43709. + struct lm_device *lm_dev = \
  43710. + container_of(_dev, struct lm_device, dev); \
  43711. + _var = lm_get_drvdata(lm_dev); \
  43712. + } while (0)
  43713. +
  43714. +#elif defined(PCI_INTERFACE)
  43715. +#define DWC_OTG_GETDRVDEV(_var, _dev) do { \
  43716. + _var = dev_get_drvdata(_dev); \
  43717. + } while (0)
  43718. +
  43719. +#elif defined(PLATFORM_INTERFACE)
  43720. +#define DWC_OTG_GETDRVDEV(_var, _dev) do { \
  43721. + struct platform_device *platform_dev = \
  43722. + container_of(_dev, struct platform_device, dev); \
  43723. + _var = platform_get_drvdata(platform_dev); \
  43724. + } while (0)
  43725. +#endif
  43726. +
  43727. +
  43728. +/**
  43729. + * Helper macro returning the struct dev of the given struct os_dependent
  43730. + *
  43731. + * c.f. static struct device *dwc_otg_getdev(struct os_dependent *osdep)
  43732. + */
  43733. +#ifdef LM_INTERFACE
  43734. +#define DWC_OTG_OS_GETDEV(_osdep) \
  43735. + ((_osdep).lmdev == NULL? NULL: &(_osdep).lmdev->dev)
  43736. +#elif defined(PCI_INTERFACE)
  43737. +#define DWC_OTG_OS_GETDEV(_osdep) \
  43738. + ((_osdep).pci_dev == NULL? NULL: &(_osdep).pci_dev->dev)
  43739. +#elif defined(PLATFORM_INTERFACE)
  43740. +#define DWC_OTG_OS_GETDEV(_osdep) \
  43741. + ((_osdep).platformdev == NULL? NULL: &(_osdep).platformdev->dev)
  43742. +#endif
  43743. +
  43744. +
  43745. +
  43746. +
  43747. +#endif /* _DWC_OS_DEP_H_ */
  43748. --- /dev/null
  43749. +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c
  43750. @@ -0,0 +1,2712 @@
  43751. +/* ==========================================================================
  43752. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $
  43753. + * $Revision: #101 $
  43754. + * $Date: 2012/08/10 $
  43755. + * $Change: 2047372 $
  43756. + *
  43757. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  43758. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  43759. + * otherwise expressly agreed to in writing between Synopsys and you.
  43760. + *
  43761. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  43762. + * any End User Software License Agreement or Agreement for Licensed Product
  43763. + * with Synopsys or any supplement thereto. You are permitted to use and
  43764. + * redistribute this Software in source and binary forms, with or without
  43765. + * modification, provided that redistributions of source code must retain this
  43766. + * notice. You may not view, use, disclose, copy or distribute this file or
  43767. + * any information contained herein except pursuant to this license grant from
  43768. + * Synopsys. If you do not agree with this notice, including the disclaimer
  43769. + * below, then you are not authorized to use the Software.
  43770. + *
  43771. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  43772. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  43773. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  43774. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  43775. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  43776. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  43777. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  43778. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  43779. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  43780. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  43781. + * DAMAGE.
  43782. + * ========================================================================== */
  43783. +#ifndef DWC_HOST_ONLY
  43784. +
  43785. +/** @file
  43786. + * This file implements PCD Core. All code in this file is portable and doesn't
  43787. + * use any OS specific functions.
  43788. + * PCD Core provides Interface, defined in <code><dwc_otg_pcd_if.h></code>
  43789. + * header file, which can be used to implement OS specific PCD interface.
  43790. + *
  43791. + * An important function of the PCD is managing interrupts generated
  43792. + * by the DWC_otg controller. The implementation of the DWC_otg device
  43793. + * mode interrupt service routines is in dwc_otg_pcd_intr.c.
  43794. + *
  43795. + * @todo Add Device Mode test modes (Test J mode, Test K mode, etc).
  43796. + * @todo Does it work when the request size is greater than DEPTSIZ
  43797. + * transfer size
  43798. + *
  43799. + */
  43800. +
  43801. +#include "dwc_otg_pcd.h"
  43802. +
  43803. +#ifdef DWC_UTE_CFI
  43804. +#include "dwc_otg_cfi.h"
  43805. +
  43806. +extern int init_cfi(cfiobject_t * cfiobj);
  43807. +#endif
  43808. +
  43809. +/**
  43810. + * Choose endpoint from ep arrays using usb_ep structure.
  43811. + */
  43812. +static dwc_otg_pcd_ep_t *get_ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)
  43813. +{
  43814. + int i;
  43815. + if (pcd->ep0.priv == handle) {
  43816. + return &pcd->ep0;
  43817. + }
  43818. + for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {
  43819. + if (pcd->in_ep[i].priv == handle)
  43820. + return &pcd->in_ep[i];
  43821. + if (pcd->out_ep[i].priv == handle)
  43822. + return &pcd->out_ep[i];
  43823. + }
  43824. +
  43825. + return NULL;
  43826. +}
  43827. +
  43828. +/**
  43829. + * This function completes a request. It call's the request call back.
  43830. + */
  43831. +void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req,
  43832. + int32_t status)
  43833. +{
  43834. + unsigned stopped = ep->stopped;
  43835. +
  43836. + DWC_DEBUGPL(DBG_PCDV, "%s(ep %p req %p)\n", __func__, ep, req);
  43837. + DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);
  43838. +
  43839. + /* don't modify queue heads during completion callback */
  43840. + ep->stopped = 1;
  43841. + /* spin_unlock/spin_lock now done in fops->complete() */
  43842. + ep->pcd->fops->complete(ep->pcd, ep->priv, req->priv, status,
  43843. + req->actual);
  43844. +
  43845. + if (ep->pcd->request_pending > 0) {
  43846. + --ep->pcd->request_pending;
  43847. + }
  43848. +
  43849. + ep->stopped = stopped;
  43850. + DWC_FREE(req);
  43851. +}
  43852. +
  43853. +/**
  43854. + * This function terminates all the requsts in the EP request queue.
  43855. + */
  43856. +void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep)
  43857. +{
  43858. + dwc_otg_pcd_request_t *req;
  43859. +
  43860. + ep->stopped = 1;
  43861. +
  43862. + /* called with irqs blocked?? */
  43863. + while (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
  43864. + req = DWC_CIRCLEQ_FIRST(&ep->queue);
  43865. + dwc_otg_request_done(ep, req, -DWC_E_SHUTDOWN);
  43866. + }
  43867. +}
  43868. +
  43869. +void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd,
  43870. + const struct dwc_otg_pcd_function_ops *fops)
  43871. +{
  43872. + pcd->fops = fops;
  43873. +}
  43874. +
  43875. +/**
  43876. + * PCD Callback function for initializing the PCD when switching to
  43877. + * device mode.
  43878. + *
  43879. + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
  43880. + */
  43881. +static int32_t dwc_otg_pcd_start_cb(void *p)
  43882. +{
  43883. + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
  43884. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  43885. +
  43886. + /*
  43887. + * Initialized the Core for Device mode.
  43888. + */
  43889. + if (dwc_otg_is_device_mode(core_if)) {
  43890. + dwc_otg_core_dev_init(core_if);
  43891. + /* Set core_if's lock pointer to the pcd->lock */
  43892. + core_if->lock = pcd->lock;
  43893. + }
  43894. + return 1;
  43895. +}
  43896. +
  43897. +/** CFI-specific buffer allocation function for EP */
  43898. +#ifdef DWC_UTE_CFI
  43899. +uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,
  43900. + size_t buflen, int flags)
  43901. +{
  43902. + dwc_otg_pcd_ep_t *ep;
  43903. + ep = get_ep_from_handle(pcd, pep);
  43904. + if (!ep) {
  43905. + DWC_WARN("bad ep\n");
  43906. + return -DWC_E_INVALID;
  43907. + }
  43908. +
  43909. + return pcd->cfi->ops.ep_alloc_buf(pcd->cfi, pcd, ep, addr, buflen,
  43910. + flags);
  43911. +}
  43912. +#else
  43913. +uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr,
  43914. + size_t buflen, int flags);
  43915. +#endif
  43916. +
  43917. +/**
  43918. + * PCD Callback function for notifying the PCD when resuming from
  43919. + * suspend.
  43920. + *
  43921. + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
  43922. + */
  43923. +static int32_t dwc_otg_pcd_resume_cb(void *p)
  43924. +{
  43925. + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
  43926. +
  43927. + if (pcd->fops->resume) {
  43928. + pcd->fops->resume(pcd);
  43929. + }
  43930. +
  43931. + /* Stop the SRP timeout timer. */
  43932. + if ((GET_CORE_IF(pcd)->core_params->phy_type != DWC_PHY_TYPE_PARAM_FS)
  43933. + || (!GET_CORE_IF(pcd)->core_params->i2c_enable)) {
  43934. + if (GET_CORE_IF(pcd)->srp_timer_started) {
  43935. + GET_CORE_IF(pcd)->srp_timer_started = 0;
  43936. + DWC_TIMER_CANCEL(GET_CORE_IF(pcd)->srp_timer);
  43937. + }
  43938. + }
  43939. + return 1;
  43940. +}
  43941. +
  43942. +/**
  43943. + * PCD Callback function for notifying the PCD device is suspended.
  43944. + *
  43945. + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
  43946. + */
  43947. +static int32_t dwc_otg_pcd_suspend_cb(void *p)
  43948. +{
  43949. + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
  43950. +
  43951. + if (pcd->fops->suspend) {
  43952. + DWC_SPINUNLOCK(pcd->lock);
  43953. + pcd->fops->suspend(pcd);
  43954. + DWC_SPINLOCK(pcd->lock);
  43955. + }
  43956. +
  43957. + return 1;
  43958. +}
  43959. +
  43960. +/**
  43961. + * PCD Callback function for stopping the PCD when switching to Host
  43962. + * mode.
  43963. + *
  43964. + * @param p void pointer to the <code>dwc_otg_pcd_t</code>
  43965. + */
  43966. +static int32_t dwc_otg_pcd_stop_cb(void *p)
  43967. +{
  43968. + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p;
  43969. + extern void dwc_otg_pcd_stop(dwc_otg_pcd_t * _pcd);
  43970. +
  43971. + dwc_otg_pcd_stop(pcd);
  43972. + return 1;
  43973. +}
  43974. +
  43975. +/**
  43976. + * PCD Callback structure for handling mode switching.
  43977. + */
  43978. +static dwc_otg_cil_callbacks_t pcd_callbacks = {
  43979. + .start = dwc_otg_pcd_start_cb,
  43980. + .stop = dwc_otg_pcd_stop_cb,
  43981. + .suspend = dwc_otg_pcd_suspend_cb,
  43982. + .resume_wakeup = dwc_otg_pcd_resume_cb,
  43983. + .p = 0, /* Set at registration */
  43984. +};
  43985. +
  43986. +/**
  43987. + * This function allocates a DMA Descriptor chain for the Endpoint
  43988. + * buffer to be used for a transfer to/from the specified endpoint.
  43989. + */
  43990. +dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(dwc_dma_t * dma_desc_addr,
  43991. + uint32_t count)
  43992. +{
  43993. + return DWC_DMA_ALLOC_ATOMIC(count * sizeof(dwc_otg_dev_dma_desc_t),
  43994. + dma_desc_addr);
  43995. +}
  43996. +
  43997. +/**
  43998. + * This function frees a DMA Descriptor chain that was allocated by ep_alloc_desc.
  43999. + */
  44000. +void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr,
  44001. + uint32_t dma_desc_addr, uint32_t count)
  44002. +{
  44003. + DWC_DMA_FREE(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr,
  44004. + dma_desc_addr);
  44005. +}
  44006. +
  44007. +#ifdef DWC_EN_ISOC
  44008. +
  44009. +/**
  44010. + * This function initializes a descriptor chain for Isochronous transfer
  44011. + *
  44012. + * @param core_if Programming view of DWC_otg controller.
  44013. + * @param dwc_ep The EP to start the transfer on.
  44014. + *
  44015. + */
  44016. +void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if,
  44017. + dwc_ep_t * dwc_ep)
  44018. +{
  44019. +
  44020. + dsts_data_t dsts = {.d32 = 0 };
  44021. + depctl_data_t depctl = {.d32 = 0 };
  44022. + volatile uint32_t *addr;
  44023. + int i, j;
  44024. + uint32_t len;
  44025. +
  44026. + if (dwc_ep->is_in)
  44027. + dwc_ep->desc_cnt = dwc_ep->buf_proc_intrvl / dwc_ep->bInterval;
  44028. + else
  44029. + dwc_ep->desc_cnt =
  44030. + dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
  44031. + dwc_ep->bInterval;
  44032. +
  44033. + /** Allocate descriptors for double buffering */
  44034. + dwc_ep->iso_desc_addr =
  44035. + dwc_otg_ep_alloc_desc_chain(&dwc_ep->iso_dma_desc_addr,
  44036. + dwc_ep->desc_cnt * 2);
  44037. + if (dwc_ep->desc_addr) {
  44038. + DWC_WARN("%s, can't allocate DMA descriptor chain\n", __func__);
  44039. + return;
  44040. + }
  44041. +
  44042. + dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
  44043. +
  44044. + /** ISO OUT EP */
  44045. + if (dwc_ep->is_in == 0) {
  44046. + dev_dma_desc_sts_t sts = {.d32 = 0 };
  44047. + dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;
  44048. + dma_addr_t dma_ad;
  44049. + uint32_t data_per_desc;
  44050. + dwc_otg_dev_out_ep_regs_t *out_regs =
  44051. + core_if->dev_if->out_ep_regs[dwc_ep->num];
  44052. + int offset;
  44053. +
  44054. + addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;
  44055. + dma_ad = (dma_addr_t) DWC_READ_REG32(&(out_regs->doepdma));
  44056. +
  44057. + /** Buffer 0 descriptors setup */
  44058. + dma_ad = dwc_ep->dma_addr0;
  44059. +
  44060. + sts.b_iso_out.bs = BS_HOST_READY;
  44061. + sts.b_iso_out.rxsts = 0;
  44062. + sts.b_iso_out.l = 0;
  44063. + sts.b_iso_out.sp = 0;
  44064. + sts.b_iso_out.ioc = 0;
  44065. + sts.b_iso_out.pid = 0;
  44066. + sts.b_iso_out.framenum = 0;
  44067. +
  44068. + offset = 0;
  44069. + for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
  44070. + i += dwc_ep->pkt_per_frm) {
  44071. +
  44072. + for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
  44073. + uint32_t len = (j + 1) * dwc_ep->maxpacket;
  44074. + if (len > dwc_ep->data_per_frame)
  44075. + data_per_desc =
  44076. + dwc_ep->data_per_frame -
  44077. + j * dwc_ep->maxpacket;
  44078. + else
  44079. + data_per_desc = dwc_ep->maxpacket;
  44080. + len = data_per_desc % 4;
  44081. + if (len)
  44082. + data_per_desc += 4 - len;
  44083. +
  44084. + sts.b_iso_out.rxbytes = data_per_desc;
  44085. + dma_desc->buf = dma_ad;
  44086. + dma_desc->status.d32 = sts.d32;
  44087. +
  44088. + offset += data_per_desc;
  44089. + dma_desc++;
  44090. + dma_ad += data_per_desc;
  44091. + }
  44092. + }
  44093. +
  44094. + for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
  44095. + uint32_t len = (j + 1) * dwc_ep->maxpacket;
  44096. + if (len > dwc_ep->data_per_frame)
  44097. + data_per_desc =
  44098. + dwc_ep->data_per_frame -
  44099. + j * dwc_ep->maxpacket;
  44100. + else
  44101. + data_per_desc = dwc_ep->maxpacket;
  44102. + len = data_per_desc % 4;
  44103. + if (len)
  44104. + data_per_desc += 4 - len;
  44105. + sts.b_iso_out.rxbytes = data_per_desc;
  44106. + dma_desc->buf = dma_ad;
  44107. + dma_desc->status.d32 = sts.d32;
  44108. +
  44109. + offset += data_per_desc;
  44110. + dma_desc++;
  44111. + dma_ad += data_per_desc;
  44112. + }
  44113. +
  44114. + sts.b_iso_out.ioc = 1;
  44115. + len = (j + 1) * dwc_ep->maxpacket;
  44116. + if (len > dwc_ep->data_per_frame)
  44117. + data_per_desc =
  44118. + dwc_ep->data_per_frame - j * dwc_ep->maxpacket;
  44119. + else
  44120. + data_per_desc = dwc_ep->maxpacket;
  44121. + len = data_per_desc % 4;
  44122. + if (len)
  44123. + data_per_desc += 4 - len;
  44124. + sts.b_iso_out.rxbytes = data_per_desc;
  44125. +
  44126. + dma_desc->buf = dma_ad;
  44127. + dma_desc->status.d32 = sts.d32;
  44128. + dma_desc++;
  44129. +
  44130. + /** Buffer 1 descriptors setup */
  44131. + sts.b_iso_out.ioc = 0;
  44132. + dma_ad = dwc_ep->dma_addr1;
  44133. +
  44134. + offset = 0;
  44135. + for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
  44136. + i += dwc_ep->pkt_per_frm) {
  44137. + for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
  44138. + uint32_t len = (j + 1) * dwc_ep->maxpacket;
  44139. + if (len > dwc_ep->data_per_frame)
  44140. + data_per_desc =
  44141. + dwc_ep->data_per_frame -
  44142. + j * dwc_ep->maxpacket;
  44143. + else
  44144. + data_per_desc = dwc_ep->maxpacket;
  44145. + len = data_per_desc % 4;
  44146. + if (len)
  44147. + data_per_desc += 4 - len;
  44148. +
  44149. + data_per_desc =
  44150. + sts.b_iso_out.rxbytes = data_per_desc;
  44151. + dma_desc->buf = dma_ad;
  44152. + dma_desc->status.d32 = sts.d32;
  44153. +
  44154. + offset += data_per_desc;
  44155. + dma_desc++;
  44156. + dma_ad += data_per_desc;
  44157. + }
  44158. + }
  44159. + for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
  44160. + data_per_desc =
  44161. + ((j + 1) * dwc_ep->maxpacket >
  44162. + dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
  44163. + j * dwc_ep->maxpacket : dwc_ep->maxpacket;
  44164. + data_per_desc +=
  44165. + (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
  44166. + sts.b_iso_out.rxbytes = data_per_desc;
  44167. + dma_desc->buf = dma_ad;
  44168. + dma_desc->status.d32 = sts.d32;
  44169. +
  44170. + offset += data_per_desc;
  44171. + dma_desc++;
  44172. + dma_ad += data_per_desc;
  44173. + }
  44174. +
  44175. + sts.b_iso_out.ioc = 1;
  44176. + sts.b_iso_out.l = 1;
  44177. + data_per_desc =
  44178. + ((j + 1) * dwc_ep->maxpacket >
  44179. + dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
  44180. + j * dwc_ep->maxpacket : dwc_ep->maxpacket;
  44181. + data_per_desc +=
  44182. + (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
  44183. + sts.b_iso_out.rxbytes = data_per_desc;
  44184. +
  44185. + dma_desc->buf = dma_ad;
  44186. + dma_desc->status.d32 = sts.d32;
  44187. +
  44188. + dwc_ep->next_frame = 0;
  44189. +
  44190. + /** Write dma_ad into DOEPDMA register */
  44191. + DWC_WRITE_REG32(&(out_regs->doepdma),
  44192. + (uint32_t) dwc_ep->iso_dma_desc_addr);
  44193. +
  44194. + }
  44195. + /** ISO IN EP */
  44196. + else {
  44197. + dev_dma_desc_sts_t sts = {.d32 = 0 };
  44198. + dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr;
  44199. + dma_addr_t dma_ad;
  44200. + dwc_otg_dev_in_ep_regs_t *in_regs =
  44201. + core_if->dev_if->in_ep_regs[dwc_ep->num];
  44202. + unsigned int frmnumber;
  44203. + fifosize_data_t txfifosize, rxfifosize;
  44204. +
  44205. + txfifosize.d32 =
  44206. + DWC_READ_REG32(&core_if->dev_if->in_ep_regs[dwc_ep->num]->
  44207. + dtxfsts);
  44208. + rxfifosize.d32 =
  44209. + DWC_READ_REG32(&core_if->core_global_regs->grxfsiz);
  44210. +
  44211. + addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
  44212. +
  44213. + dma_ad = dwc_ep->dma_addr0;
  44214. +
  44215. + dsts.d32 =
  44216. + DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
  44217. +
  44218. + sts.b_iso_in.bs = BS_HOST_READY;
  44219. + sts.b_iso_in.txsts = 0;
  44220. + sts.b_iso_in.sp =
  44221. + (dwc_ep->data_per_frame % dwc_ep->maxpacket) ? 1 : 0;
  44222. + sts.b_iso_in.ioc = 0;
  44223. + sts.b_iso_in.pid = dwc_ep->pkt_per_frm;
  44224. +
  44225. + frmnumber = dwc_ep->next_frame;
  44226. +
  44227. + sts.b_iso_in.framenum = frmnumber;
  44228. + sts.b_iso_in.txbytes = dwc_ep->data_per_frame;
  44229. + sts.b_iso_in.l = 0;
  44230. +
  44231. + /** Buffer 0 descriptors setup */
  44232. + for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
  44233. + dma_desc->buf = dma_ad;
  44234. + dma_desc->status.d32 = sts.d32;
  44235. + dma_desc++;
  44236. +
  44237. + dma_ad += dwc_ep->data_per_frame;
  44238. + sts.b_iso_in.framenum += dwc_ep->bInterval;
  44239. + }
  44240. +
  44241. + sts.b_iso_in.ioc = 1;
  44242. + dma_desc->buf = dma_ad;
  44243. + dma_desc->status.d32 = sts.d32;
  44244. + ++dma_desc;
  44245. +
  44246. + /** Buffer 1 descriptors setup */
  44247. + sts.b_iso_in.ioc = 0;
  44248. + dma_ad = dwc_ep->dma_addr1;
  44249. +
  44250. + for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
  44251. + i += dwc_ep->pkt_per_frm) {
  44252. + dma_desc->buf = dma_ad;
  44253. + dma_desc->status.d32 = sts.d32;
  44254. + dma_desc++;
  44255. +
  44256. + dma_ad += dwc_ep->data_per_frame;
  44257. + sts.b_iso_in.framenum += dwc_ep->bInterval;
  44258. +
  44259. + sts.b_iso_in.ioc = 0;
  44260. + }
  44261. + sts.b_iso_in.ioc = 1;
  44262. + sts.b_iso_in.l = 1;
  44263. +
  44264. + dma_desc->buf = dma_ad;
  44265. + dma_desc->status.d32 = sts.d32;
  44266. +
  44267. + dwc_ep->next_frame = sts.b_iso_in.framenum + dwc_ep->bInterval;
  44268. +
  44269. + /** Write dma_ad into diepdma register */
  44270. + DWC_WRITE_REG32(&(in_regs->diepdma),
  44271. + (uint32_t) dwc_ep->iso_dma_desc_addr);
  44272. + }
  44273. + /** Enable endpoint, clear nak */
  44274. + depctl.d32 = 0;
  44275. + depctl.b.epena = 1;
  44276. + depctl.b.usbactep = 1;
  44277. + depctl.b.cnak = 1;
  44278. +
  44279. + DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
  44280. + depctl.d32 = DWC_READ_REG32(addr);
  44281. +}
  44282. +
  44283. +/**
  44284. + * This function initializes a descriptor chain for Isochronous transfer
  44285. + *
  44286. + * @param core_if Programming view of DWC_otg controller.
  44287. + * @param ep The EP to start the transfer on.
  44288. + *
  44289. + */
  44290. +void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if,
  44291. + dwc_ep_t * ep)
  44292. +{
  44293. + depctl_data_t depctl = {.d32 = 0 };
  44294. + volatile uint32_t *addr;
  44295. +
  44296. + if (ep->is_in) {
  44297. + addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
  44298. + } else {
  44299. + addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
  44300. + }
  44301. +
  44302. + if (core_if->dma_enable == 0 || core_if->dma_desc_enable != 0) {
  44303. + return;
  44304. + } else {
  44305. + deptsiz_data_t deptsiz = {.d32 = 0 };
  44306. +
  44307. + ep->xfer_len =
  44308. + ep->data_per_frame * ep->buf_proc_intrvl / ep->bInterval;
  44309. + ep->pkt_cnt =
  44310. + (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
  44311. + ep->xfer_count = 0;
  44312. + ep->xfer_buff =
  44313. + (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;
  44314. + ep->dma_addr =
  44315. + (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;
  44316. +
  44317. + if (ep->is_in) {
  44318. + /* Program the transfer size and packet count
  44319. + * as follows: xfersize = N * maxpacket +
  44320. + * short_packet pktcnt = N + (short_packet
  44321. + * exist ? 1 : 0)
  44322. + */
  44323. + deptsiz.b.mc = ep->pkt_per_frm;
  44324. + deptsiz.b.xfersize = ep->xfer_len;
  44325. + deptsiz.b.pktcnt =
  44326. + (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;
  44327. + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
  44328. + dieptsiz, deptsiz.d32);
  44329. +
  44330. + /* Write the DMA register */
  44331. + DWC_WRITE_REG32(&
  44332. + (core_if->dev_if->in_ep_regs[ep->num]->
  44333. + diepdma), (uint32_t) ep->dma_addr);
  44334. +
  44335. + } else {
  44336. + deptsiz.b.pktcnt =
  44337. + (ep->xfer_len + (ep->maxpacket - 1)) /
  44338. + ep->maxpacket;
  44339. + deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
  44340. +
  44341. + DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->
  44342. + doeptsiz, deptsiz.d32);
  44343. +
  44344. + /* Write the DMA register */
  44345. + DWC_WRITE_REG32(&
  44346. + (core_if->dev_if->out_ep_regs[ep->num]->
  44347. + doepdma), (uint32_t) ep->dma_addr);
  44348. +
  44349. + }
  44350. + /** Enable endpoint, clear nak */
  44351. + depctl.d32 = 0;
  44352. + depctl.b.epena = 1;
  44353. + depctl.b.cnak = 1;
  44354. +
  44355. + DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
  44356. + }
  44357. +}
  44358. +
  44359. +/**
  44360. + * This function does the setup for a data transfer for an EP and
  44361. + * starts the transfer. For an IN transfer, the packets will be
  44362. + * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers,
  44363. + * the packets are unloaded from the Rx FIFO in the ISR.
  44364. + *
  44365. + * @param core_if Programming view of DWC_otg controller.
  44366. + * @param ep The EP to start the transfer on.
  44367. + */
  44368. +
  44369. +static void dwc_otg_iso_ep_start_transfer(dwc_otg_core_if_t * core_if,
  44370. + dwc_ep_t * ep)
  44371. +{
  44372. + if (core_if->dma_enable) {
  44373. + if (core_if->dma_desc_enable) {
  44374. + if (ep->is_in) {
  44375. + ep->desc_cnt = ep->pkt_cnt / ep->pkt_per_frm;
  44376. + } else {
  44377. + ep->desc_cnt = ep->pkt_cnt;
  44378. + }
  44379. + dwc_otg_iso_ep_start_ddma_transfer(core_if, ep);
  44380. + } else {
  44381. + if (core_if->pti_enh_enable) {
  44382. + dwc_otg_iso_ep_start_buf_transfer(core_if, ep);
  44383. + } else {
  44384. + ep->cur_pkt_addr =
  44385. + (ep->proc_buf_num) ? ep->xfer_buff1 : ep->
  44386. + xfer_buff0;
  44387. + ep->cur_pkt_dma_addr =
  44388. + (ep->proc_buf_num) ? ep->dma_addr1 : ep->
  44389. + dma_addr0;
  44390. + dwc_otg_iso_ep_start_frm_transfer(core_if, ep);
  44391. + }
  44392. + }
  44393. + } else {
  44394. + ep->cur_pkt_addr =
  44395. + (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0;
  44396. + ep->cur_pkt_dma_addr =
  44397. + (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0;
  44398. + dwc_otg_iso_ep_start_frm_transfer(core_if, ep);
  44399. + }
  44400. +}
  44401. +
  44402. +/**
  44403. + * This function stops transfer for an EP and
  44404. + * resets the ep's variables.
  44405. + *
  44406. + * @param core_if Programming view of DWC_otg controller.
  44407. + * @param ep The EP to start the transfer on.
  44408. + */
  44409. +
  44410. +void dwc_otg_iso_ep_stop_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
  44411. +{
  44412. + depctl_data_t depctl = {.d32 = 0 };
  44413. + volatile uint32_t *addr;
  44414. +
  44415. + if (ep->is_in == 1) {
  44416. + addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl;
  44417. + } else {
  44418. + addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl;
  44419. + }
  44420. +
  44421. + /* disable the ep */
  44422. + depctl.d32 = DWC_READ_REG32(addr);
  44423. +
  44424. + depctl.b.epdis = 1;
  44425. + depctl.b.snak = 1;
  44426. +
  44427. + DWC_WRITE_REG32(addr, depctl.d32);
  44428. +
  44429. + if (core_if->dma_desc_enable &&
  44430. + ep->iso_desc_addr && ep->iso_dma_desc_addr) {
  44431. + dwc_otg_ep_free_desc_chain(ep->iso_desc_addr,
  44432. + ep->iso_dma_desc_addr,
  44433. + ep->desc_cnt * 2);
  44434. + }
  44435. +
  44436. + /* reset varibales */
  44437. + ep->dma_addr0 = 0;
  44438. + ep->dma_addr1 = 0;
  44439. + ep->xfer_buff0 = 0;
  44440. + ep->xfer_buff1 = 0;
  44441. + ep->data_per_frame = 0;
  44442. + ep->data_pattern_frame = 0;
  44443. + ep->sync_frame = 0;
  44444. + ep->buf_proc_intrvl = 0;
  44445. + ep->bInterval = 0;
  44446. + ep->proc_buf_num = 0;
  44447. + ep->pkt_per_frm = 0;
  44448. + ep->pkt_per_frm = 0;
  44449. + ep->desc_cnt = 0;
  44450. + ep->iso_desc_addr = 0;
  44451. + ep->iso_dma_desc_addr = 0;
  44452. +}
  44453. +
  44454. +int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle,
  44455. + uint8_t * buf0, uint8_t * buf1, dwc_dma_t dma0,
  44456. + dwc_dma_t dma1, int sync_frame, int dp_frame,
  44457. + int data_per_frame, int start_frame,
  44458. + int buf_proc_intrvl, void *req_handle,
  44459. + int atomic_alloc)
  44460. +{
  44461. + dwc_otg_pcd_ep_t *ep;
  44462. + dwc_irqflags_t flags = 0;
  44463. + dwc_ep_t *dwc_ep;
  44464. + int32_t frm_data;
  44465. + dsts_data_t dsts;
  44466. + dwc_otg_core_if_t *core_if;
  44467. +
  44468. + ep = get_ep_from_handle(pcd, ep_handle);
  44469. +
  44470. + if (!ep || !ep->desc || ep->dwc_ep.num == 0) {
  44471. + DWC_WARN("bad ep\n");
  44472. + return -DWC_E_INVALID;
  44473. + }
  44474. +
  44475. + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
  44476. + core_if = GET_CORE_IF(pcd);
  44477. + dwc_ep = &ep->dwc_ep;
  44478. +
  44479. + if (ep->iso_req_handle) {
  44480. + DWC_WARN("ISO request in progress\n");
  44481. + }
  44482. +
  44483. + dwc_ep->dma_addr0 = dma0;
  44484. + dwc_ep->dma_addr1 = dma1;
  44485. +
  44486. + dwc_ep->xfer_buff0 = buf0;
  44487. + dwc_ep->xfer_buff1 = buf1;
  44488. +
  44489. + dwc_ep->data_per_frame = data_per_frame;
  44490. +
  44491. + /** @todo - pattern data support is to be implemented in the future */
  44492. + dwc_ep->data_pattern_frame = dp_frame;
  44493. + dwc_ep->sync_frame = sync_frame;
  44494. +
  44495. + dwc_ep->buf_proc_intrvl = buf_proc_intrvl;
  44496. +
  44497. + dwc_ep->bInterval = 1 << (ep->desc->bInterval - 1);
  44498. +
  44499. + dwc_ep->proc_buf_num = 0;
  44500. +
  44501. + dwc_ep->pkt_per_frm = 0;
  44502. + frm_data = ep->dwc_ep.data_per_frame;
  44503. + while (frm_data > 0) {
  44504. + dwc_ep->pkt_per_frm++;
  44505. + frm_data -= ep->dwc_ep.maxpacket;
  44506. + }
  44507. +
  44508. + dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
  44509. +
  44510. + if (start_frame == -1) {
  44511. + dwc_ep->next_frame = dsts.b.soffn + 1;
  44512. + if (dwc_ep->bInterval != 1) {
  44513. + dwc_ep->next_frame =
  44514. + dwc_ep->next_frame + (dwc_ep->bInterval - 1 -
  44515. + dwc_ep->next_frame %
  44516. + dwc_ep->bInterval);
  44517. + }
  44518. + } else {
  44519. + dwc_ep->next_frame = start_frame;
  44520. + }
  44521. +
  44522. + if (!core_if->pti_enh_enable) {
  44523. + dwc_ep->pkt_cnt =
  44524. + dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
  44525. + dwc_ep->bInterval;
  44526. + } else {
  44527. + dwc_ep->pkt_cnt =
  44528. + (dwc_ep->data_per_frame *
  44529. + (dwc_ep->buf_proc_intrvl / dwc_ep->bInterval)
  44530. + - 1 + dwc_ep->maxpacket) / dwc_ep->maxpacket;
  44531. + }
  44532. +
  44533. + if (core_if->dma_desc_enable) {
  44534. + dwc_ep->desc_cnt =
  44535. + dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm /
  44536. + dwc_ep->bInterval;
  44537. + }
  44538. +
  44539. + if (atomic_alloc) {
  44540. + dwc_ep->pkt_info =
  44541. + DWC_ALLOC_ATOMIC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
  44542. + } else {
  44543. + dwc_ep->pkt_info =
  44544. + DWC_ALLOC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
  44545. + }
  44546. + if (!dwc_ep->pkt_info) {
  44547. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  44548. + return -DWC_E_NO_MEMORY;
  44549. + }
  44550. + if (core_if->pti_enh_enable) {
  44551. + dwc_memset(dwc_ep->pkt_info, 0,
  44552. + sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt);
  44553. + }
  44554. +
  44555. + dwc_ep->cur_pkt = 0;
  44556. + ep->iso_req_handle = req_handle;
  44557. +
  44558. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  44559. + dwc_otg_iso_ep_start_transfer(core_if, dwc_ep);
  44560. + return 0;
  44561. +}
  44562. +
  44563. +int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle,
  44564. + void *req_handle)
  44565. +{
  44566. + dwc_irqflags_t flags = 0;
  44567. + dwc_otg_pcd_ep_t *ep;
  44568. + dwc_ep_t *dwc_ep;
  44569. +
  44570. + ep = get_ep_from_handle(pcd, ep_handle);
  44571. + if (!ep || !ep->desc || ep->dwc_ep.num == 0) {
  44572. + DWC_WARN("bad ep\n");
  44573. + return -DWC_E_INVALID;
  44574. + }
  44575. + dwc_ep = &ep->dwc_ep;
  44576. +
  44577. + dwc_otg_iso_ep_stop_transfer(GET_CORE_IF(pcd), dwc_ep);
  44578. +
  44579. + DWC_FREE(dwc_ep->pkt_info);
  44580. + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
  44581. + if (ep->iso_req_handle != req_handle) {
  44582. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  44583. + return -DWC_E_INVALID;
  44584. + }
  44585. +
  44586. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  44587. +
  44588. + ep->iso_req_handle = 0;
  44589. + return 0;
  44590. +}
  44591. +
  44592. +/**
  44593. + * This function is used for perodical data exchnage between PCD and gadget drivers.
  44594. + * for Isochronous EPs
  44595. + *
  44596. + * - Every time a sync period completes this function is called to
  44597. + * perform data exchange between PCD and gadget
  44598. + */
  44599. +void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep,
  44600. + void *req_handle)
  44601. +{
  44602. + int i;
  44603. + dwc_ep_t *dwc_ep;
  44604. +
  44605. + dwc_ep = &ep->dwc_ep;
  44606. +
  44607. + DWC_SPINUNLOCK(ep->pcd->lock);
  44608. + pcd->fops->isoc_complete(pcd, ep->priv, ep->iso_req_handle,
  44609. + dwc_ep->proc_buf_num ^ 0x1);
  44610. + DWC_SPINLOCK(ep->pcd->lock);
  44611. +
  44612. + for (i = 0; i < dwc_ep->pkt_cnt; ++i) {
  44613. + dwc_ep->pkt_info[i].status = 0;
  44614. + dwc_ep->pkt_info[i].offset = 0;
  44615. + dwc_ep->pkt_info[i].length = 0;
  44616. + }
  44617. +}
  44618. +
  44619. +int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, void *ep_handle,
  44620. + void *iso_req_handle)
  44621. +{
  44622. + dwc_otg_pcd_ep_t *ep;
  44623. + dwc_ep_t *dwc_ep;
  44624. +
  44625. + ep = get_ep_from_handle(pcd, ep_handle);
  44626. + if (!ep->desc || ep->dwc_ep.num == 0) {
  44627. + DWC_WARN("bad ep\n");
  44628. + return -DWC_E_INVALID;
  44629. + }
  44630. + dwc_ep = &ep->dwc_ep;
  44631. +
  44632. + return dwc_ep->pkt_cnt;
  44633. +}
  44634. +
  44635. +void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, void *ep_handle,
  44636. + void *iso_req_handle, int packet,
  44637. + int *status, int *actual, int *offset)
  44638. +{
  44639. + dwc_otg_pcd_ep_t *ep;
  44640. + dwc_ep_t *dwc_ep;
  44641. +
  44642. + ep = get_ep_from_handle(pcd, ep_handle);
  44643. + if (!ep)
  44644. + DWC_WARN("bad ep\n");
  44645. +
  44646. + dwc_ep = &ep->dwc_ep;
  44647. +
  44648. + *status = dwc_ep->pkt_info[packet].status;
  44649. + *actual = dwc_ep->pkt_info[packet].length;
  44650. + *offset = dwc_ep->pkt_info[packet].offset;
  44651. +}
  44652. +
  44653. +#endif /* DWC_EN_ISOC */
  44654. +
  44655. +static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep,
  44656. + uint32_t is_in, uint32_t ep_num)
  44657. +{
  44658. + /* Init EP structure */
  44659. + pcd_ep->desc = 0;
  44660. + pcd_ep->pcd = pcd;
  44661. + pcd_ep->stopped = 1;
  44662. + pcd_ep->queue_sof = 0;
  44663. +
  44664. + /* Init DWC ep structure */
  44665. + pcd_ep->dwc_ep.is_in = is_in;
  44666. + pcd_ep->dwc_ep.num = ep_num;
  44667. + pcd_ep->dwc_ep.active = 0;
  44668. + pcd_ep->dwc_ep.tx_fifo_num = 0;
  44669. + /* Control until ep is actvated */
  44670. + pcd_ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
  44671. + pcd_ep->dwc_ep.maxpacket = MAX_PACKET_SIZE;
  44672. + pcd_ep->dwc_ep.dma_addr = 0;
  44673. + pcd_ep->dwc_ep.start_xfer_buff = 0;
  44674. + pcd_ep->dwc_ep.xfer_buff = 0;
  44675. + pcd_ep->dwc_ep.xfer_len = 0;
  44676. + pcd_ep->dwc_ep.xfer_count = 0;
  44677. + pcd_ep->dwc_ep.sent_zlp = 0;
  44678. + pcd_ep->dwc_ep.total_len = 0;
  44679. + pcd_ep->dwc_ep.desc_addr = 0;
  44680. + pcd_ep->dwc_ep.dma_desc_addr = 0;
  44681. + DWC_CIRCLEQ_INIT(&pcd_ep->queue);
  44682. +}
  44683. +
  44684. +/**
  44685. + * Initialize ep's
  44686. + */
  44687. +static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd)
  44688. +{
  44689. + int i;
  44690. + uint32_t hwcfg1;
  44691. + dwc_otg_pcd_ep_t *ep;
  44692. + int in_ep_cntr, out_ep_cntr;
  44693. + uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps;
  44694. + uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps;
  44695. +
  44696. + /**
  44697. + * Initialize the EP0 structure.
  44698. + */
  44699. + ep = &pcd->ep0;
  44700. + dwc_otg_pcd_init_ep(pcd, ep, 0, 0);
  44701. +
  44702. + in_ep_cntr = 0;
  44703. + hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3;
  44704. + for (i = 1; in_ep_cntr < num_in_eps; i++) {
  44705. + if ((hwcfg1 & 0x1) == 0) {
  44706. + dwc_otg_pcd_ep_t *ep = &pcd->in_ep[in_ep_cntr];
  44707. + in_ep_cntr++;
  44708. + /**
  44709. + * @todo NGS: Add direction to EP, based on contents
  44710. + * of HWCFG1. Need a copy of HWCFG1 in pcd structure?
  44711. + * sprintf(";r
  44712. + */
  44713. + dwc_otg_pcd_init_ep(pcd, ep, 1 /* IN */ , i);
  44714. +
  44715. + DWC_CIRCLEQ_INIT(&ep->queue);
  44716. + }
  44717. + hwcfg1 >>= 2;
  44718. + }
  44719. +
  44720. + out_ep_cntr = 0;
  44721. + hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2;
  44722. + for (i = 1; out_ep_cntr < num_out_eps; i++) {
  44723. + if ((hwcfg1 & 0x1) == 0) {
  44724. + dwc_otg_pcd_ep_t *ep = &pcd->out_ep[out_ep_cntr];
  44725. + out_ep_cntr++;
  44726. + /**
  44727. + * @todo NGS: Add direction to EP, based on contents
  44728. + * of HWCFG1. Need a copy of HWCFG1 in pcd structure?
  44729. + * sprintf(";r
  44730. + */
  44731. + dwc_otg_pcd_init_ep(pcd, ep, 0 /* OUT */ , i);
  44732. + DWC_CIRCLEQ_INIT(&ep->queue);
  44733. + }
  44734. + hwcfg1 >>= 2;
  44735. + }
  44736. +
  44737. + pcd->ep0state = EP0_DISCONNECT;
  44738. + pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE;
  44739. + pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL;
  44740. +}
  44741. +
  44742. +/**
  44743. + * This function is called when the SRP timer expires. The SRP should
  44744. + * complete within 6 seconds.
  44745. + */
  44746. +static void srp_timeout(void *ptr)
  44747. +{
  44748. + gotgctl_data_t gotgctl;
  44749. + dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr;
  44750. + volatile uint32_t *addr = &core_if->core_global_regs->gotgctl;
  44751. +
  44752. + gotgctl.d32 = DWC_READ_REG32(addr);
  44753. +
  44754. + core_if->srp_timer_started = 0;
  44755. +
  44756. + if (core_if->adp_enable) {
  44757. + if (gotgctl.b.bsesvld == 0) {
  44758. + gpwrdn_data_t gpwrdn = {.d32 = 0 };
  44759. + DWC_PRINTF("SRP Timeout BSESSVLD = 0\n");
  44760. + /* Power off the core */
  44761. + if (core_if->power_down == 2) {
  44762. + gpwrdn.b.pwrdnswtch = 1;
  44763. + DWC_MODIFY_REG32(&core_if->
  44764. + core_global_regs->gpwrdn,
  44765. + gpwrdn.d32, 0);
  44766. + }
  44767. +
  44768. + gpwrdn.d32 = 0;
  44769. + gpwrdn.b.pmuintsel = 1;
  44770. + gpwrdn.b.pmuactv = 1;
  44771. + DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0,
  44772. + gpwrdn.d32);
  44773. + dwc_otg_adp_probe_start(core_if);
  44774. + } else {
  44775. + DWC_PRINTF("SRP Timeout BSESSVLD = 1\n");
  44776. + core_if->op_state = B_PERIPHERAL;
  44777. + dwc_otg_core_init(core_if);
  44778. + dwc_otg_enable_global_interrupts(core_if);
  44779. + cil_pcd_start(core_if);
  44780. + }
  44781. + }
  44782. +
  44783. + if ((core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) &&
  44784. + (core_if->core_params->i2c_enable)) {
  44785. + DWC_PRINTF("SRP Timeout\n");
  44786. +
  44787. + if ((core_if->srp_success) && (gotgctl.b.bsesvld)) {
  44788. + if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) {
  44789. + core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p);
  44790. + }
  44791. +
  44792. + /* Clear Session Request */
  44793. + gotgctl.d32 = 0;
  44794. + gotgctl.b.sesreq = 1;
  44795. + DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl,
  44796. + gotgctl.d32, 0);
  44797. +
  44798. + core_if->srp_success = 0;
  44799. + } else {
  44800. + __DWC_ERROR("Device not connected/responding\n");
  44801. + gotgctl.b.sesreq = 0;
  44802. + DWC_WRITE_REG32(addr, gotgctl.d32);
  44803. + }
  44804. + } else if (gotgctl.b.sesreq) {
  44805. + DWC_PRINTF("SRP Timeout\n");
  44806. +
  44807. + __DWC_ERROR("Device not connected/responding\n");
  44808. + gotgctl.b.sesreq = 0;
  44809. + DWC_WRITE_REG32(addr, gotgctl.d32);
  44810. + } else {
  44811. + DWC_PRINTF(" SRP GOTGCTL=%0x\n", gotgctl.d32);
  44812. + }
  44813. +}
  44814. +
  44815. +/**
  44816. + * Tasklet
  44817. + *
  44818. + */
  44819. +extern void start_next_request(dwc_otg_pcd_ep_t * ep);
  44820. +
  44821. +static void start_xfer_tasklet_func(void *data)
  44822. +{
  44823. + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;
  44824. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  44825. +
  44826. + int i;
  44827. + depctl_data_t diepctl;
  44828. +
  44829. + DWC_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n");
  44830. +
  44831. + diepctl.d32 = DWC_READ_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl);
  44832. +
  44833. + if (pcd->ep0.queue_sof) {
  44834. + pcd->ep0.queue_sof = 0;
  44835. + start_next_request(&pcd->ep0);
  44836. + // break;
  44837. + }
  44838. +
  44839. + for (i = 0; i < core_if->dev_if->num_in_eps; i++) {
  44840. + depctl_data_t diepctl;
  44841. + diepctl.d32 =
  44842. + DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl);
  44843. +
  44844. + if (pcd->in_ep[i].queue_sof) {
  44845. + pcd->in_ep[i].queue_sof = 0;
  44846. + start_next_request(&pcd->in_ep[i]);
  44847. + // break;
  44848. + }
  44849. + }
  44850. +
  44851. + return;
  44852. +}
  44853. +
  44854. +/**
  44855. + * This function initialized the PCD portion of the driver.
  44856. + *
  44857. + */
  44858. +dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if)
  44859. +{
  44860. + dwc_otg_pcd_t *pcd = NULL;
  44861. + dwc_otg_dev_if_t *dev_if;
  44862. + int i;
  44863. +
  44864. + /*
  44865. + * Allocate PCD structure
  44866. + */
  44867. + pcd = DWC_ALLOC(sizeof(dwc_otg_pcd_t));
  44868. +
  44869. + if (pcd == NULL) {
  44870. + return NULL;
  44871. + }
  44872. +
  44873. +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_SPINLOCK))
  44874. + DWC_SPINLOCK_ALLOC_LINUX_DEBUG(pcd->lock);
  44875. +#else
  44876. + pcd->lock = DWC_SPINLOCK_ALLOC();
  44877. +#endif
  44878. + DWC_DEBUGPL(DBG_HCDV, "Init of PCD %p given core_if %p\n",
  44879. + pcd, core_if);//GRAYG
  44880. + if (!pcd->lock) {
  44881. + DWC_ERROR("Could not allocate lock for pcd");
  44882. + DWC_FREE(pcd);
  44883. + return NULL;
  44884. + }
  44885. + /* Set core_if's lock pointer to hcd->lock */
  44886. + core_if->lock = pcd->lock;
  44887. + pcd->core_if = core_if;
  44888. +
  44889. + dev_if = core_if->dev_if;
  44890. + dev_if->isoc_ep = NULL;
  44891. +
  44892. + if (core_if->hwcfg4.b.ded_fifo_en) {
  44893. + DWC_PRINTF("Dedicated Tx FIFOs mode\n");
  44894. + } else {
  44895. + DWC_PRINTF("Shared Tx FIFO mode\n");
  44896. + }
  44897. +
  44898. + /*
  44899. + * Initialized the Core for Device mode here if there is nod ADP support.
  44900. + * Otherwise it will be done later in dwc_otg_adp_start routine.
  44901. + */
  44902. + if (dwc_otg_is_device_mode(core_if) /*&& !core_if->adp_enable*/) {
  44903. + dwc_otg_core_dev_init(core_if);
  44904. + }
  44905. +
  44906. + /*
  44907. + * Register the PCD Callbacks.
  44908. + */
  44909. + dwc_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd);
  44910. +
  44911. + /*
  44912. + * Initialize the DMA buffer for SETUP packets
  44913. + */
  44914. + if (GET_CORE_IF(pcd)->dma_enable) {
  44915. + pcd->setup_pkt =
  44916. + DWC_DMA_ALLOC(sizeof(*pcd->setup_pkt) * 5,
  44917. + &pcd->setup_pkt_dma_handle);
  44918. + if (pcd->setup_pkt == NULL) {
  44919. + DWC_FREE(pcd);
  44920. + return NULL;
  44921. + }
  44922. +
  44923. + pcd->status_buf =
  44924. + DWC_DMA_ALLOC(sizeof(uint16_t),
  44925. + &pcd->status_buf_dma_handle);
  44926. + if (pcd->status_buf == NULL) {
  44927. + DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5,
  44928. + pcd->setup_pkt, pcd->setup_pkt_dma_handle);
  44929. + DWC_FREE(pcd);
  44930. + return NULL;
  44931. + }
  44932. +
  44933. + if (GET_CORE_IF(pcd)->dma_desc_enable) {
  44934. + dev_if->setup_desc_addr[0] =
  44935. + dwc_otg_ep_alloc_desc_chain
  44936. + (&dev_if->dma_setup_desc_addr[0], 1);
  44937. + dev_if->setup_desc_addr[1] =
  44938. + dwc_otg_ep_alloc_desc_chain
  44939. + (&dev_if->dma_setup_desc_addr[1], 1);
  44940. + dev_if->in_desc_addr =
  44941. + dwc_otg_ep_alloc_desc_chain
  44942. + (&dev_if->dma_in_desc_addr, 1);
  44943. + dev_if->out_desc_addr =
  44944. + dwc_otg_ep_alloc_desc_chain
  44945. + (&dev_if->dma_out_desc_addr, 1);
  44946. + pcd->data_terminated = 0;
  44947. +
  44948. + if (dev_if->setup_desc_addr[0] == 0
  44949. + || dev_if->setup_desc_addr[1] == 0
  44950. + || dev_if->in_desc_addr == 0
  44951. + || dev_if->out_desc_addr == 0) {
  44952. +
  44953. + if (dev_if->out_desc_addr)
  44954. + dwc_otg_ep_free_desc_chain
  44955. + (dev_if->out_desc_addr,
  44956. + dev_if->dma_out_desc_addr, 1);
  44957. + if (dev_if->in_desc_addr)
  44958. + dwc_otg_ep_free_desc_chain
  44959. + (dev_if->in_desc_addr,
  44960. + dev_if->dma_in_desc_addr, 1);
  44961. + if (dev_if->setup_desc_addr[1])
  44962. + dwc_otg_ep_free_desc_chain
  44963. + (dev_if->setup_desc_addr[1],
  44964. + dev_if->dma_setup_desc_addr[1], 1);
  44965. + if (dev_if->setup_desc_addr[0])
  44966. + dwc_otg_ep_free_desc_chain
  44967. + (dev_if->setup_desc_addr[0],
  44968. + dev_if->dma_setup_desc_addr[0], 1);
  44969. +
  44970. + DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5,
  44971. + pcd->setup_pkt,
  44972. + pcd->setup_pkt_dma_handle);
  44973. + DWC_DMA_FREE(sizeof(*pcd->status_buf),
  44974. + pcd->status_buf,
  44975. + pcd->status_buf_dma_handle);
  44976. +
  44977. + DWC_FREE(pcd);
  44978. +
  44979. + return NULL;
  44980. + }
  44981. + }
  44982. + } else {
  44983. + pcd->setup_pkt = DWC_ALLOC(sizeof(*pcd->setup_pkt) * 5);
  44984. + if (pcd->setup_pkt == NULL) {
  44985. + DWC_FREE(pcd);
  44986. + return NULL;
  44987. + }
  44988. +
  44989. + pcd->status_buf = DWC_ALLOC(sizeof(uint16_t));
  44990. + if (pcd->status_buf == NULL) {
  44991. + DWC_FREE(pcd->setup_pkt);
  44992. + DWC_FREE(pcd);
  44993. + return NULL;
  44994. + }
  44995. + }
  44996. +
  44997. + dwc_otg_pcd_reinit(pcd);
  44998. +
  44999. + /* Allocate the cfi object for the PCD */
  45000. +#ifdef DWC_UTE_CFI
  45001. + pcd->cfi = DWC_ALLOC(sizeof(cfiobject_t));
  45002. + if (NULL == pcd->cfi)
  45003. + goto fail;
  45004. + if (init_cfi(pcd->cfi)) {
  45005. + CFI_INFO("%s: Failed to init the CFI object\n", __func__);
  45006. + goto fail;
  45007. + }
  45008. +#endif
  45009. +
  45010. + /* Initialize tasklets */
  45011. + pcd->start_xfer_tasklet = DWC_TASK_ALLOC("xfer_tasklet",
  45012. + start_xfer_tasklet_func, pcd);
  45013. + pcd->test_mode_tasklet = DWC_TASK_ALLOC("test_mode_tasklet",
  45014. + do_test_mode, pcd);
  45015. +
  45016. + /* Initialize SRP timer */
  45017. + core_if->srp_timer = DWC_TIMER_ALLOC("SRP TIMER", srp_timeout, core_if);
  45018. +
  45019. + if (core_if->core_params->dev_out_nak) {
  45020. + /**
  45021. + * Initialize xfer timeout timer. Implemented for
  45022. + * 2.93a feature "Device DDMA OUT NAK Enhancement"
  45023. + */
  45024. + for(i = 0; i < MAX_EPS_CHANNELS; i++) {
  45025. + pcd->core_if->ep_xfer_timer[i] =
  45026. + DWC_TIMER_ALLOC("ep timer", ep_xfer_timeout,
  45027. + &pcd->core_if->ep_xfer_info[i]);
  45028. + }
  45029. + }
  45030. +
  45031. + return pcd;
  45032. +#ifdef DWC_UTE_CFI
  45033. +fail:
  45034. +#endif
  45035. + if (pcd->setup_pkt)
  45036. + DWC_FREE(pcd->setup_pkt);
  45037. + if (pcd->status_buf)
  45038. + DWC_FREE(pcd->status_buf);
  45039. +#ifdef DWC_UTE_CFI
  45040. + if (pcd->cfi)
  45041. + DWC_FREE(pcd->cfi);
  45042. +#endif
  45043. + if (pcd)
  45044. + DWC_FREE(pcd);
  45045. + return NULL;
  45046. +
  45047. +}
  45048. +
  45049. +/**
  45050. + * Remove PCD specific data
  45051. + */
  45052. +void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd)
  45053. +{
  45054. + dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
  45055. + int i;
  45056. + if (pcd->core_if->core_params->dev_out_nak) {
  45057. + for (i = 0; i < MAX_EPS_CHANNELS; i++) {
  45058. + DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[i]);
  45059. + pcd->core_if->ep_xfer_info[i].state = 0;
  45060. + }
  45061. + }
  45062. +
  45063. + if (GET_CORE_IF(pcd)->dma_enable) {
  45064. + DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt,
  45065. + pcd->setup_pkt_dma_handle);
  45066. + DWC_DMA_FREE(sizeof(uint16_t), pcd->status_buf,
  45067. + pcd->status_buf_dma_handle);
  45068. + if (GET_CORE_IF(pcd)->dma_desc_enable) {
  45069. + dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0],
  45070. + dev_if->dma_setup_desc_addr
  45071. + [0], 1);
  45072. + dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1],
  45073. + dev_if->dma_setup_desc_addr
  45074. + [1], 1);
  45075. + dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr,
  45076. + dev_if->dma_in_desc_addr, 1);
  45077. + dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr,
  45078. + dev_if->dma_out_desc_addr,
  45079. + 1);
  45080. + }
  45081. + } else {
  45082. + DWC_FREE(pcd->setup_pkt);
  45083. + DWC_FREE(pcd->status_buf);
  45084. + }
  45085. + DWC_SPINLOCK_FREE(pcd->lock);
  45086. + /* Set core_if's lock pointer to NULL */
  45087. + pcd->core_if->lock = NULL;
  45088. +
  45089. + DWC_TASK_FREE(pcd->start_xfer_tasklet);
  45090. + DWC_TASK_FREE(pcd->test_mode_tasklet);
  45091. + if (pcd->core_if->core_params->dev_out_nak) {
  45092. + for (i = 0; i < MAX_EPS_CHANNELS; i++) {
  45093. + if (pcd->core_if->ep_xfer_timer[i]) {
  45094. + DWC_TIMER_FREE(pcd->core_if->ep_xfer_timer[i]);
  45095. + }
  45096. + }
  45097. + }
  45098. +
  45099. +/* Release the CFI object's dynamic memory */
  45100. +#ifdef DWC_UTE_CFI
  45101. + if (pcd->cfi->ops.release) {
  45102. + pcd->cfi->ops.release(pcd->cfi);
  45103. + }
  45104. +#endif
  45105. +
  45106. + DWC_FREE(pcd);
  45107. +}
  45108. +
  45109. +/**
  45110. + * Returns whether registered pcd is dual speed or not
  45111. + */
  45112. +uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd)
  45113. +{
  45114. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  45115. +
  45116. + if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) ||
  45117. + ((core_if->hwcfg2.b.hs_phy_type == 2) &&
  45118. + (core_if->hwcfg2.b.fs_phy_type == 1) &&
  45119. + (core_if->core_params->ulpi_fs_ls))) {
  45120. + return 0;
  45121. + }
  45122. +
  45123. + return 1;
  45124. +}
  45125. +
  45126. +/**
  45127. + * Returns whether registered pcd is OTG capable or not
  45128. + */
  45129. +uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd)
  45130. +{
  45131. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  45132. + gusbcfg_data_t usbcfg = {.d32 = 0 };
  45133. +
  45134. + usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg);
  45135. + if (!usbcfg.b.srpcap || !usbcfg.b.hnpcap) {
  45136. + return 0;
  45137. + }
  45138. +
  45139. + return 1;
  45140. +}
  45141. +
  45142. +/**
  45143. + * This function assigns periodic Tx FIFO to an periodic EP
  45144. + * in shared Tx FIFO mode
  45145. + */
  45146. +static uint32_t assign_tx_fifo(dwc_otg_core_if_t * core_if)
  45147. +{
  45148. + uint32_t TxMsk = 1;
  45149. + int i;
  45150. +
  45151. + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++i) {
  45152. + if ((TxMsk & core_if->tx_msk) == 0) {
  45153. + core_if->tx_msk |= TxMsk;
  45154. + return i + 1;
  45155. + }
  45156. + TxMsk <<= 1;
  45157. + }
  45158. + return 0;
  45159. +}
  45160. +
  45161. +/**
  45162. + * This function assigns periodic Tx FIFO to an periodic EP
  45163. + * in shared Tx FIFO mode
  45164. + */
  45165. +static uint32_t assign_perio_tx_fifo(dwc_otg_core_if_t * core_if)
  45166. +{
  45167. + uint32_t PerTxMsk = 1;
  45168. + int i;
  45169. + for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; ++i) {
  45170. + if ((PerTxMsk & core_if->p_tx_msk) == 0) {
  45171. + core_if->p_tx_msk |= PerTxMsk;
  45172. + return i + 1;
  45173. + }
  45174. + PerTxMsk <<= 1;
  45175. + }
  45176. + return 0;
  45177. +}
  45178. +
  45179. +/**
  45180. + * This function releases periodic Tx FIFO
  45181. + * in shared Tx FIFO mode
  45182. + */
  45183. +static void release_perio_tx_fifo(dwc_otg_core_if_t * core_if,
  45184. + uint32_t fifo_num)
  45185. +{
  45186. + core_if->p_tx_msk =
  45187. + (core_if->p_tx_msk & (1 << (fifo_num - 1))) ^ core_if->p_tx_msk;
  45188. +}
  45189. +
  45190. +/**
  45191. + * This function releases periodic Tx FIFO
  45192. + * in shared Tx FIFO mode
  45193. + */
  45194. +static void release_tx_fifo(dwc_otg_core_if_t * core_if, uint32_t fifo_num)
  45195. +{
  45196. + core_if->tx_msk =
  45197. + (core_if->tx_msk & (1 << (fifo_num - 1))) ^ core_if->tx_msk;
  45198. +}
  45199. +
  45200. +/**
  45201. + * This function is being called from gadget
  45202. + * to enable PCD endpoint.
  45203. + */
  45204. +int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,
  45205. + const uint8_t * ep_desc, void *usb_ep)
  45206. +{
  45207. + int num, dir;
  45208. + dwc_otg_pcd_ep_t *ep = NULL;
  45209. + const usb_endpoint_descriptor_t *desc;
  45210. + dwc_irqflags_t flags;
  45211. + fifosize_data_t dptxfsiz = {.d32 = 0 };
  45212. + gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
  45213. + gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 };
  45214. + int retval = 0;
  45215. + int i, epcount;
  45216. +
  45217. + desc = (const usb_endpoint_descriptor_t *)ep_desc;
  45218. +
  45219. + if (!desc) {
  45220. + pcd->ep0.priv = usb_ep;
  45221. + ep = &pcd->ep0;
  45222. + retval = -DWC_E_INVALID;
  45223. + goto out;
  45224. + }
  45225. +
  45226. + num = UE_GET_ADDR(desc->bEndpointAddress);
  45227. + dir = UE_GET_DIR(desc->bEndpointAddress);
  45228. +
  45229. + if (!desc->wMaxPacketSize) {
  45230. + DWC_WARN("bad maxpacketsize\n");
  45231. + retval = -DWC_E_INVALID;
  45232. + goto out;
  45233. + }
  45234. +
  45235. + if (dir == UE_DIR_IN) {
  45236. + epcount = pcd->core_if->dev_if->num_in_eps;
  45237. + for (i = 0; i < epcount; i++) {
  45238. + if (num == pcd->in_ep[i].dwc_ep.num) {
  45239. + ep = &pcd->in_ep[i];
  45240. + break;
  45241. + }
  45242. + }
  45243. + } else {
  45244. + epcount = pcd->core_if->dev_if->num_out_eps;
  45245. + for (i = 0; i < epcount; i++) {
  45246. + if (num == pcd->out_ep[i].dwc_ep.num) {
  45247. + ep = &pcd->out_ep[i];
  45248. + break;
  45249. + }
  45250. + }
  45251. + }
  45252. +
  45253. + if (!ep) {
  45254. + DWC_WARN("bad address\n");
  45255. + retval = -DWC_E_INVALID;
  45256. + goto out;
  45257. + }
  45258. +
  45259. + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
  45260. +
  45261. + ep->desc = desc;
  45262. + ep->priv = usb_ep;
  45263. +
  45264. + /*
  45265. + * Activate the EP
  45266. + */
  45267. + ep->stopped = 0;
  45268. +
  45269. + ep->dwc_ep.is_in = (dir == UE_DIR_IN);
  45270. + ep->dwc_ep.maxpacket = UGETW(desc->wMaxPacketSize);
  45271. +
  45272. + ep->dwc_ep.type = desc->bmAttributes & UE_XFERTYPE;
  45273. +
  45274. + if (ep->dwc_ep.is_in) {
  45275. + if (!GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
  45276. + ep->dwc_ep.tx_fifo_num = 0;
  45277. +
  45278. + if (ep->dwc_ep.type == UE_ISOCHRONOUS) {
  45279. + /*
  45280. + * if ISOC EP then assign a Periodic Tx FIFO.
  45281. + */
  45282. + ep->dwc_ep.tx_fifo_num =
  45283. + assign_perio_tx_fifo(GET_CORE_IF(pcd));
  45284. + }
  45285. + } else {
  45286. + /*
  45287. + * if Dedicated FIFOs mode is on then assign a Tx FIFO.
  45288. + */
  45289. + ep->dwc_ep.tx_fifo_num =
  45290. + assign_tx_fifo(GET_CORE_IF(pcd));
  45291. + }
  45292. +
  45293. + /* Calculating EP info controller base address */
  45294. + if (ep->dwc_ep.tx_fifo_num
  45295. + && GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
  45296. + gdfifocfg.d32 =
  45297. + DWC_READ_REG32(&GET_CORE_IF(pcd)->
  45298. + core_global_regs->gdfifocfg);
  45299. + gdfifocfgbase.d32 = gdfifocfg.d32 >> 16;
  45300. + dptxfsiz.d32 =
  45301. + (DWC_READ_REG32
  45302. + (&GET_CORE_IF(pcd)->core_global_regs->
  45303. + dtxfsiz[ep->dwc_ep.tx_fifo_num - 1]) >> 16);
  45304. + gdfifocfg.b.epinfobase =
  45305. + gdfifocfgbase.d32 + dptxfsiz.d32;
  45306. + if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) {
  45307. + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->
  45308. + core_global_regs->gdfifocfg,
  45309. + gdfifocfg.d32);
  45310. + }
  45311. + }
  45312. + }
  45313. + /* Set initial data PID. */
  45314. + if (ep->dwc_ep.type == UE_BULK) {
  45315. + ep->dwc_ep.data_pid_start = 0;
  45316. + }
  45317. +
  45318. + /* Alloc DMA Descriptors */
  45319. + if (GET_CORE_IF(pcd)->dma_desc_enable) {
  45320. +#ifndef DWC_UTE_PER_IO
  45321. + if (ep->dwc_ep.type != UE_ISOCHRONOUS) {
  45322. +#endif
  45323. + ep->dwc_ep.desc_addr =
  45324. + dwc_otg_ep_alloc_desc_chain(&ep->
  45325. + dwc_ep.dma_desc_addr,
  45326. + MAX_DMA_DESC_CNT);
  45327. + if (!ep->dwc_ep.desc_addr) {
  45328. + DWC_WARN("%s, can't allocate DMA descriptor\n",
  45329. + __func__);
  45330. + retval = -DWC_E_SHUTDOWN;
  45331. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  45332. + goto out;
  45333. + }
  45334. +#ifndef DWC_UTE_PER_IO
  45335. + }
  45336. +#endif
  45337. + }
  45338. +
  45339. + DWC_DEBUGPL(DBG_PCD, "Activate %s: type=%d, mps=%d desc=%p\n",
  45340. + (ep->dwc_ep.is_in ? "IN" : "OUT"),
  45341. + ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc);
  45342. +#ifdef DWC_UTE_PER_IO
  45343. + ep->dwc_ep.xiso_bInterval = 1 << (ep->desc->bInterval - 1);
  45344. +#endif
  45345. + if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
  45346. + ep->dwc_ep.bInterval = 1 << (ep->desc->bInterval - 1);
  45347. + ep->dwc_ep.frame_num = 0xFFFFFFFF;
  45348. + }
  45349. +
  45350. + dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
  45351. +
  45352. +#ifdef DWC_UTE_CFI
  45353. + if (pcd->cfi->ops.ep_enable) {
  45354. + pcd->cfi->ops.ep_enable(pcd->cfi, pcd, ep);
  45355. + }
  45356. +#endif
  45357. +
  45358. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  45359. +
  45360. +out:
  45361. + return retval;
  45362. +}
  45363. +
  45364. +/**
  45365. + * This function is being called from gadget
  45366. + * to disable PCD endpoint.
  45367. + */
  45368. +int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle)
  45369. +{
  45370. + dwc_otg_pcd_ep_t *ep;
  45371. + dwc_irqflags_t flags;
  45372. + dwc_otg_dev_dma_desc_t *desc_addr;
  45373. + dwc_dma_t dma_desc_addr;
  45374. + gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 };
  45375. + gdfifocfg_data_t gdfifocfg = {.d32 = 0 };
  45376. + fifosize_data_t dptxfsiz = {.d32 = 0 };
  45377. +
  45378. + ep = get_ep_from_handle(pcd, ep_handle);
  45379. +
  45380. + if (!ep || !ep->desc) {
  45381. + DWC_DEBUGPL(DBG_PCD, "bad ep address\n");
  45382. + return -DWC_E_INVALID;
  45383. + }
  45384. +
  45385. + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
  45386. +
  45387. + dwc_otg_request_nuke(ep);
  45388. +
  45389. + dwc_otg_ep_deactivate(GET_CORE_IF(pcd), &ep->dwc_ep);
  45390. + if (pcd->core_if->core_params->dev_out_nak) {
  45391. + DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[ep->dwc_ep.num]);
  45392. + pcd->core_if->ep_xfer_info[ep->dwc_ep.num].state = 0;
  45393. + }
  45394. + ep->desc = NULL;
  45395. + ep->stopped = 1;
  45396. +
  45397. + gdfifocfg.d32 =
  45398. + DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg);
  45399. + gdfifocfgbase.d32 = gdfifocfg.d32 >> 16;
  45400. +
  45401. + if (ep->dwc_ep.is_in) {
  45402. + if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
  45403. + /* Flush the Tx FIFO */
  45404. + dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd),
  45405. + ep->dwc_ep.tx_fifo_num);
  45406. + }
  45407. + release_perio_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
  45408. + release_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num);
  45409. + if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) {
  45410. + /* Decreasing EPinfo Base Addr */
  45411. + dptxfsiz.d32 =
  45412. + (DWC_READ_REG32
  45413. + (&GET_CORE_IF(pcd)->
  45414. + core_global_regs->dtxfsiz[ep->dwc_ep.tx_fifo_num-1]) >> 16);
  45415. + gdfifocfg.b.epinfobase = gdfifocfgbase.d32 - dptxfsiz.d32;
  45416. + if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) {
  45417. + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg,
  45418. + gdfifocfg.d32);
  45419. + }
  45420. + }
  45421. + }
  45422. +
  45423. + /* Free DMA Descriptors */
  45424. + if (GET_CORE_IF(pcd)->dma_desc_enable) {
  45425. + if (ep->dwc_ep.type != UE_ISOCHRONOUS) {
  45426. + desc_addr = ep->dwc_ep.desc_addr;
  45427. + dma_desc_addr = ep->dwc_ep.dma_desc_addr;
  45428. +
  45429. + /* Cannot call dma_free_coherent() with IRQs disabled */
  45430. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  45431. + dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr,
  45432. + MAX_DMA_DESC_CNT);
  45433. +
  45434. + goto out_unlocked;
  45435. + }
  45436. + }
  45437. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  45438. +
  45439. +out_unlocked:
  45440. + DWC_DEBUGPL(DBG_PCD, "%d %s disabled\n", ep->dwc_ep.num,
  45441. + ep->dwc_ep.is_in ? "IN" : "OUT");
  45442. + return 0;
  45443. +
  45444. +}
  45445. +
  45446. +/******************************************************************************/
  45447. +#ifdef DWC_UTE_PER_IO
  45448. +
  45449. +/**
  45450. + * Free the request and its extended parts
  45451. + *
  45452. + */
  45453. +void dwc_pcd_xiso_ereq_free(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req)
  45454. +{
  45455. + DWC_FREE(req->ext_req.per_io_frame_descs);
  45456. + DWC_FREE(req);
  45457. +}
  45458. +
  45459. +/**
  45460. + * Start the next request in the endpoint's queue.
  45461. + *
  45462. + */
  45463. +int dwc_otg_pcd_xiso_start_next_request(dwc_otg_pcd_t * pcd,
  45464. + dwc_otg_pcd_ep_t * ep)
  45465. +{
  45466. + int i;
  45467. + dwc_otg_pcd_request_t *req = NULL;
  45468. + dwc_ep_t *dwcep = NULL;
  45469. + struct dwc_iso_xreq_port *ereq = NULL;
  45470. + struct dwc_iso_pkt_desc_port *ddesc_iso;
  45471. + uint16_t nat;
  45472. + depctl_data_t diepctl;
  45473. +
  45474. + dwcep = &ep->dwc_ep;
  45475. +
  45476. + if (dwcep->xiso_active_xfers > 0) {
  45477. +#if 0 //Disable this to decrease s/w overhead that is crucial for Isoc transfers
  45478. + DWC_WARN("There are currently active transfers for EP%d \
  45479. + (active=%d; queued=%d)", dwcep->num, dwcep->xiso_active_xfers,
  45480. + dwcep->xiso_queued_xfers);
  45481. +#endif
  45482. + return 0;
  45483. + }
  45484. +
  45485. + nat = UGETW(ep->desc->wMaxPacketSize);
  45486. + nat = (nat >> 11) & 0x03;
  45487. +
  45488. + if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
  45489. + req = DWC_CIRCLEQ_FIRST(&ep->queue);
  45490. + ereq = &req->ext_req;
  45491. + ep->stopped = 0;
  45492. +
  45493. + /* Get the frame number */
  45494. + dwcep->xiso_frame_num =
  45495. + dwc_otg_get_frame_number(GET_CORE_IF(pcd));
  45496. + DWC_DEBUG("FRM_NUM=%d", dwcep->xiso_frame_num);
  45497. +
  45498. + ddesc_iso = ereq->per_io_frame_descs;
  45499. +
  45500. + if (dwcep->is_in) {
  45501. + /* Setup DMA Descriptor chain for IN Isoc request */
  45502. + for (i = 0; i < ereq->pio_pkt_count; i++) {
  45503. + //if ((i % (nat + 1)) == 0)
  45504. + if ( i > 0 )
  45505. + dwcep->xiso_frame_num =
  45506. + (dwcep->xiso_bInterval +
  45507. + dwcep->xiso_frame_num) & 0x3FFF;
  45508. + dwcep->desc_addr[i].buf =
  45509. + req->dma + ddesc_iso[i].offset;
  45510. + dwcep->desc_addr[i].status.b_iso_in.txbytes =
  45511. + ddesc_iso[i].length;
  45512. + dwcep->desc_addr[i].status.b_iso_in.framenum =
  45513. + dwcep->xiso_frame_num;
  45514. + dwcep->desc_addr[i].status.b_iso_in.bs =
  45515. + BS_HOST_READY;
  45516. + dwcep->desc_addr[i].status.b_iso_in.txsts = 0;
  45517. + dwcep->desc_addr[i].status.b_iso_in.sp =
  45518. + (ddesc_iso[i].length %
  45519. + dwcep->maxpacket) ? 1 : 0;
  45520. + dwcep->desc_addr[i].status.b_iso_in.ioc = 0;
  45521. + dwcep->desc_addr[i].status.b_iso_in.pid = nat + 1;
  45522. + dwcep->desc_addr[i].status.b_iso_in.l = 0;
  45523. +
  45524. + /* Process the last descriptor */
  45525. + if (i == ereq->pio_pkt_count - 1) {
  45526. + dwcep->desc_addr[i].status.b_iso_in.ioc = 1;
  45527. + dwcep->desc_addr[i].status.b_iso_in.l = 1;
  45528. + }
  45529. + }
  45530. +
  45531. + /* Setup and start the transfer for this endpoint */
  45532. + dwcep->xiso_active_xfers++;
  45533. + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->dev_if->
  45534. + in_ep_regs[dwcep->num]->diepdma,
  45535. + dwcep->dma_desc_addr);
  45536. + diepctl.d32 = 0;
  45537. + diepctl.b.epena = 1;
  45538. + diepctl.b.cnak = 1;
  45539. + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if->
  45540. + in_ep_regs[dwcep->num]->diepctl, 0,
  45541. + diepctl.d32);
  45542. + } else {
  45543. + /* Setup DMA Descriptor chain for OUT Isoc request */
  45544. + for (i = 0; i < ereq->pio_pkt_count; i++) {
  45545. + //if ((i % (nat + 1)) == 0)
  45546. + dwcep->xiso_frame_num = (dwcep->xiso_bInterval +
  45547. + dwcep->xiso_frame_num) & 0x3FFF;
  45548. + dwcep->desc_addr[i].buf =
  45549. + req->dma + ddesc_iso[i].offset;
  45550. + dwcep->desc_addr[i].status.b_iso_out.rxbytes =
  45551. + ddesc_iso[i].length;
  45552. + dwcep->desc_addr[i].status.b_iso_out.framenum =
  45553. + dwcep->xiso_frame_num;
  45554. + dwcep->desc_addr[i].status.b_iso_out.bs =
  45555. + BS_HOST_READY;
  45556. + dwcep->desc_addr[i].status.b_iso_out.rxsts = 0;
  45557. + dwcep->desc_addr[i].status.b_iso_out.sp =
  45558. + (ddesc_iso[i].length %
  45559. + dwcep->maxpacket) ? 1 : 0;
  45560. + dwcep->desc_addr[i].status.b_iso_out.ioc = 0;
  45561. + dwcep->desc_addr[i].status.b_iso_out.pid = nat + 1;
  45562. + dwcep->desc_addr[i].status.b_iso_out.l = 0;
  45563. +
  45564. + /* Process the last descriptor */
  45565. + if (i == ereq->pio_pkt_count - 1) {
  45566. + dwcep->desc_addr[i].status.b_iso_out.ioc = 1;
  45567. + dwcep->desc_addr[i].status.b_iso_out.l = 1;
  45568. + }
  45569. + }
  45570. +
  45571. + /* Setup and start the transfer for this endpoint */
  45572. + dwcep->xiso_active_xfers++;
  45573. + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->
  45574. + dev_if->out_ep_regs[dwcep->num]->
  45575. + doepdma, dwcep->dma_desc_addr);
  45576. + diepctl.d32 = 0;
  45577. + diepctl.b.epena = 1;
  45578. + diepctl.b.cnak = 1;
  45579. + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->
  45580. + dev_if->out_ep_regs[dwcep->num]->
  45581. + doepctl, 0, diepctl.d32);
  45582. + }
  45583. +
  45584. + } else {
  45585. + ep->stopped = 1;
  45586. + }
  45587. +
  45588. + return 0;
  45589. +}
  45590. +
  45591. +/**
  45592. + * - Remove the request from the queue
  45593. + */
  45594. +void complete_xiso_ep(dwc_otg_pcd_ep_t * ep)
  45595. +{
  45596. + dwc_otg_pcd_request_t *req = NULL;
  45597. + struct dwc_iso_xreq_port *ereq = NULL;
  45598. + struct dwc_iso_pkt_desc_port *ddesc_iso = NULL;
  45599. + dwc_ep_t *dwcep = NULL;
  45600. + int i;
  45601. +
  45602. + //DWC_DEBUG();
  45603. + dwcep = &ep->dwc_ep;
  45604. +
  45605. + /* Get the first pending request from the queue */
  45606. + if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
  45607. + req = DWC_CIRCLEQ_FIRST(&ep->queue);
  45608. + if (!req) {
  45609. + DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
  45610. + return;
  45611. + }
  45612. + dwcep->xiso_active_xfers--;
  45613. + dwcep->xiso_queued_xfers--;
  45614. + /* Remove this request from the queue */
  45615. + DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry);
  45616. + } else {
  45617. + DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
  45618. + return;
  45619. + }
  45620. +
  45621. + ep->stopped = 1;
  45622. + ereq = &req->ext_req;
  45623. + ddesc_iso = ereq->per_io_frame_descs;
  45624. +
  45625. + if (dwcep->xiso_active_xfers < 0) {
  45626. + DWC_WARN("EP#%d (xiso_active_xfers=%d)", dwcep->num,
  45627. + dwcep->xiso_active_xfers);
  45628. + }
  45629. +
  45630. + /* Fill the Isoc descs of portable extended req from dma descriptors */
  45631. + for (i = 0; i < ereq->pio_pkt_count; i++) {
  45632. + if (dwcep->is_in) { /* IN endpoints */
  45633. + ddesc_iso[i].actual_length = ddesc_iso[i].length -
  45634. + dwcep->desc_addr[i].status.b_iso_in.txbytes;
  45635. + ddesc_iso[i].status =
  45636. + dwcep->desc_addr[i].status.b_iso_in.txsts;
  45637. + } else { /* OUT endpoints */
  45638. + ddesc_iso[i].actual_length = ddesc_iso[i].length -
  45639. + dwcep->desc_addr[i].status.b_iso_out.rxbytes;
  45640. + ddesc_iso[i].status =
  45641. + dwcep->desc_addr[i].status.b_iso_out.rxsts;
  45642. + }
  45643. + }
  45644. +
  45645. + DWC_SPINUNLOCK(ep->pcd->lock);
  45646. +
  45647. + /* Call the completion function in the non-portable logic */
  45648. + ep->pcd->fops->xisoc_complete(ep->pcd, ep->priv, req->priv, 0,
  45649. + &req->ext_req);
  45650. +
  45651. + DWC_SPINLOCK(ep->pcd->lock);
  45652. +
  45653. + /* Free the request - specific freeing needed for extended request object */
  45654. + dwc_pcd_xiso_ereq_free(ep, req);
  45655. +
  45656. + /* Start the next request */
  45657. + dwc_otg_pcd_xiso_start_next_request(ep->pcd, ep);
  45658. +
  45659. + return;
  45660. +}
  45661. +
  45662. +/**
  45663. + * Create and initialize the Isoc pkt descriptors of the extended request.
  45664. + *
  45665. + */
  45666. +static int dwc_otg_pcd_xiso_create_pkt_descs(dwc_otg_pcd_request_t * req,
  45667. + void *ereq_nonport,
  45668. + int atomic_alloc)
  45669. +{
  45670. + struct dwc_iso_xreq_port *ereq = NULL;
  45671. + struct dwc_iso_xreq_port *req_mapped = NULL;
  45672. + struct dwc_iso_pkt_desc_port *ipds = NULL; /* To be created in this function */
  45673. + uint32_t pkt_count;
  45674. + int i;
  45675. +
  45676. + ereq = &req->ext_req;
  45677. + req_mapped = (struct dwc_iso_xreq_port *)ereq_nonport;
  45678. + pkt_count = req_mapped->pio_pkt_count;
  45679. +
  45680. + /* Create the isoc descs */
  45681. + if (atomic_alloc) {
  45682. + ipds = DWC_ALLOC_ATOMIC(sizeof(*ipds) * pkt_count);
  45683. + } else {
  45684. + ipds = DWC_ALLOC(sizeof(*ipds) * pkt_count);
  45685. + }
  45686. +
  45687. + if (!ipds) {
  45688. + DWC_ERROR("Failed to allocate isoc descriptors");
  45689. + return -DWC_E_NO_MEMORY;
  45690. + }
  45691. +
  45692. + /* Initialize the extended request fields */
  45693. + ereq->per_io_frame_descs = ipds;
  45694. + ereq->error_count = 0;
  45695. + ereq->pio_alloc_pkt_count = pkt_count;
  45696. + ereq->pio_pkt_count = pkt_count;
  45697. + ereq->tr_sub_flags = req_mapped->tr_sub_flags;
  45698. +
  45699. + /* Init the Isoc descriptors */
  45700. + for (i = 0; i < pkt_count; i++) {
  45701. + ipds[i].length = req_mapped->per_io_frame_descs[i].length;
  45702. + ipds[i].offset = req_mapped->per_io_frame_descs[i].offset;
  45703. + ipds[i].status = req_mapped->per_io_frame_descs[i].status; /* 0 */
  45704. + ipds[i].actual_length =
  45705. + req_mapped->per_io_frame_descs[i].actual_length;
  45706. + }
  45707. +
  45708. + return 0;
  45709. +}
  45710. +
  45711. +static void prn_ext_request(struct dwc_iso_xreq_port *ereq)
  45712. +{
  45713. + struct dwc_iso_pkt_desc_port *xfd = NULL;
  45714. + int i;
  45715. +
  45716. + DWC_DEBUG("per_io_frame_descs=%p", ereq->per_io_frame_descs);
  45717. + DWC_DEBUG("tr_sub_flags=%d", ereq->tr_sub_flags);
  45718. + DWC_DEBUG("error_count=%d", ereq->error_count);
  45719. + DWC_DEBUG("pio_alloc_pkt_count=%d", ereq->pio_alloc_pkt_count);
  45720. + DWC_DEBUG("pio_pkt_count=%d", ereq->pio_pkt_count);
  45721. + DWC_DEBUG("res=%d", ereq->res);
  45722. +
  45723. + for (i = 0; i < ereq->pio_pkt_count; i++) {
  45724. + xfd = &ereq->per_io_frame_descs[0];
  45725. + DWC_DEBUG("FD #%d", i);
  45726. +
  45727. + DWC_DEBUG("xfd->actual_length=%d", xfd->actual_length);
  45728. + DWC_DEBUG("xfd->length=%d", xfd->length);
  45729. + DWC_DEBUG("xfd->offset=%d", xfd->offset);
  45730. + DWC_DEBUG("xfd->status=%d", xfd->status);
  45731. + }
  45732. +}
  45733. +
  45734. +/**
  45735. + *
  45736. + */
  45737. +int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
  45738. + uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen,
  45739. + int zero, void *req_handle, int atomic_alloc,
  45740. + void *ereq_nonport)
  45741. +{
  45742. + dwc_otg_pcd_request_t *req = NULL;
  45743. + dwc_otg_pcd_ep_t *ep;
  45744. + dwc_irqflags_t flags;
  45745. + int res;
  45746. +
  45747. + ep = get_ep_from_handle(pcd, ep_handle);
  45748. + if (!ep) {
  45749. + DWC_WARN("bad ep\n");
  45750. + return -DWC_E_INVALID;
  45751. + }
  45752. +
  45753. + /* We support this extension only for DDMA mode */
  45754. + if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
  45755. + if (!GET_CORE_IF(pcd)->dma_desc_enable)
  45756. + return -DWC_E_INVALID;
  45757. +
  45758. + /* Create a dwc_otg_pcd_request_t object */
  45759. + if (atomic_alloc) {
  45760. + req = DWC_ALLOC_ATOMIC(sizeof(*req));
  45761. + } else {
  45762. + req = DWC_ALLOC(sizeof(*req));
  45763. + }
  45764. +
  45765. + if (!req) {
  45766. + return -DWC_E_NO_MEMORY;
  45767. + }
  45768. +
  45769. + /* Create the Isoc descs for this request which shall be the exact match
  45770. + * of the structure sent to us from the non-portable logic */
  45771. + res =
  45772. + dwc_otg_pcd_xiso_create_pkt_descs(req, ereq_nonport, atomic_alloc);
  45773. + if (res) {
  45774. + DWC_WARN("Failed to init the Isoc descriptors");
  45775. + DWC_FREE(req);
  45776. + return res;
  45777. + }
  45778. +
  45779. + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
  45780. +
  45781. + DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry);
  45782. + req->buf = buf;
  45783. + req->dma = dma_buf;
  45784. + req->length = buflen;
  45785. + req->sent_zlp = zero;
  45786. + req->priv = req_handle;
  45787. +
  45788. + //DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
  45789. + ep->dwc_ep.dma_addr = dma_buf;
  45790. + ep->dwc_ep.start_xfer_buff = buf;
  45791. + ep->dwc_ep.xfer_buff = buf;
  45792. + ep->dwc_ep.xfer_len = 0;
  45793. + ep->dwc_ep.xfer_count = 0;
  45794. + ep->dwc_ep.sent_zlp = 0;
  45795. + ep->dwc_ep.total_len = buflen;
  45796. +
  45797. + /* Add this request to the tail */
  45798. + DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
  45799. + ep->dwc_ep.xiso_queued_xfers++;
  45800. +
  45801. +//DWC_DEBUG("CP_0");
  45802. +//DWC_DEBUG("req->ext_req.tr_sub_flags=%d", req->ext_req.tr_sub_flags);
  45803. +//prn_ext_request((struct dwc_iso_xreq_port *) ereq_nonport);
  45804. +//prn_ext_request(&req->ext_req);
  45805. +
  45806. + //DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  45807. +
  45808. + /* If the req->status == ASAP then check if there is any active transfer
  45809. + * for this endpoint. If no active transfers, then get the first entry
  45810. + * from the queue and start that transfer
  45811. + */
  45812. + if (req->ext_req.tr_sub_flags == DWC_EREQ_TF_ASAP) {
  45813. + res = dwc_otg_pcd_xiso_start_next_request(pcd, ep);
  45814. + if (res) {
  45815. + DWC_WARN("Failed to start the next Isoc transfer");
  45816. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  45817. + DWC_FREE(req);
  45818. + return res;
  45819. + }
  45820. + }
  45821. +
  45822. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  45823. + return 0;
  45824. +}
  45825. +
  45826. +#endif
  45827. +/* END ifdef DWC_UTE_PER_IO ***************************************************/
  45828. +int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
  45829. + uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen,
  45830. + int zero, void *req_handle, int atomic_alloc)
  45831. +{
  45832. + dwc_irqflags_t flags;
  45833. + dwc_otg_pcd_request_t *req;
  45834. + dwc_otg_pcd_ep_t *ep;
  45835. + uint32_t max_transfer;
  45836. +
  45837. + ep = get_ep_from_handle(pcd, ep_handle);
  45838. + if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) {
  45839. + DWC_WARN("bad ep\n");
  45840. + return -DWC_E_INVALID;
  45841. + }
  45842. +
  45843. + if (atomic_alloc) {
  45844. + req = DWC_ALLOC_ATOMIC(sizeof(*req));
  45845. + } else {
  45846. + req = DWC_ALLOC(sizeof(*req));
  45847. + }
  45848. +
  45849. + if (!req) {
  45850. + return -DWC_E_NO_MEMORY;
  45851. + }
  45852. + DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry);
  45853. + if (!GET_CORE_IF(pcd)->core_params->opt) {
  45854. + if (ep->dwc_ep.num != 0) {
  45855. + DWC_ERROR("queue req %p, len %d buf %p\n",
  45856. + req_handle, buflen, buf);
  45857. + }
  45858. + }
  45859. +
  45860. + req->buf = buf;
  45861. + req->dma = dma_buf;
  45862. + req->length = buflen;
  45863. + req->sent_zlp = zero;
  45864. + req->priv = req_handle;
  45865. + req->dw_align_buf = NULL;
  45866. + if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable
  45867. + && !GET_CORE_IF(pcd)->dma_desc_enable)
  45868. + req->dw_align_buf = DWC_DMA_ALLOC(buflen,
  45869. + &req->dw_align_buf_dma);
  45870. + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
  45871. +
  45872. + /*
  45873. + * After adding request to the queue for IN ISOC wait for In Token Received
  45874. + * when TX FIFO is empty interrupt and for OUT ISOC wait for OUT Token
  45875. + * Received when EP is disabled interrupt to obtain starting microframe
  45876. + * (odd/even) start transfer
  45877. + */
  45878. + if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
  45879. + if (req != 0) {
  45880. + depctl_data_t depctl = {.d32 =
  45881. + DWC_READ_REG32(&pcd->core_if->dev_if->
  45882. + in_ep_regs[ep->dwc_ep.num]->
  45883. + diepctl) };
  45884. + ++pcd->request_pending;
  45885. +
  45886. + DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
  45887. + if (ep->dwc_ep.is_in) {
  45888. + depctl.b.cnak = 1;
  45889. + DWC_WRITE_REG32(&pcd->core_if->dev_if->
  45890. + in_ep_regs[ep->dwc_ep.num]->
  45891. + diepctl, depctl.d32);
  45892. + }
  45893. +
  45894. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  45895. + }
  45896. + return 0;
  45897. + }
  45898. +
  45899. + /*
  45900. + * For EP0 IN without premature status, zlp is required?
  45901. + */
  45902. + if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) {
  45903. + DWC_DEBUGPL(DBG_PCDV, "%d-OUT ZLP\n", ep->dwc_ep.num);
  45904. + //_req->zero = 1;
  45905. + }
  45906. +
  45907. + /* Start the transfer */
  45908. + if (DWC_CIRCLEQ_EMPTY(&ep->queue) && !ep->stopped) {
  45909. + /* EP0 Transfer? */
  45910. + if (ep->dwc_ep.num == 0) {
  45911. + switch (pcd->ep0state) {
  45912. + case EP0_IN_DATA_PHASE:
  45913. + DWC_DEBUGPL(DBG_PCD,
  45914. + "%s ep0: EP0_IN_DATA_PHASE\n",
  45915. + __func__);
  45916. + break;
  45917. +
  45918. + case EP0_OUT_DATA_PHASE:
  45919. + DWC_DEBUGPL(DBG_PCD,
  45920. + "%s ep0: EP0_OUT_DATA_PHASE\n",
  45921. + __func__);
  45922. + if (pcd->request_config) {
  45923. + /* Complete STATUS PHASE */
  45924. + ep->dwc_ep.is_in = 1;
  45925. + pcd->ep0state = EP0_IN_STATUS_PHASE;
  45926. + }
  45927. + break;
  45928. +
  45929. + case EP0_IN_STATUS_PHASE:
  45930. + DWC_DEBUGPL(DBG_PCD,
  45931. + "%s ep0: EP0_IN_STATUS_PHASE\n",
  45932. + __func__);
  45933. + break;
  45934. +
  45935. + default:
  45936. + DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n",
  45937. + pcd->ep0state);
  45938. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  45939. + return -DWC_E_SHUTDOWN;
  45940. + }
  45941. +
  45942. + ep->dwc_ep.dma_addr = dma_buf;
  45943. + ep->dwc_ep.start_xfer_buff = buf;
  45944. + ep->dwc_ep.xfer_buff = buf;
  45945. + ep->dwc_ep.xfer_len = buflen;
  45946. + ep->dwc_ep.xfer_count = 0;
  45947. + ep->dwc_ep.sent_zlp = 0;
  45948. + ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
  45949. +
  45950. + if (zero) {
  45951. + if ((ep->dwc_ep.xfer_len %
  45952. + ep->dwc_ep.maxpacket == 0)
  45953. + && (ep->dwc_ep.xfer_len != 0)) {
  45954. + ep->dwc_ep.sent_zlp = 1;
  45955. + }
  45956. +
  45957. + }
  45958. +
  45959. + dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd),
  45960. + &ep->dwc_ep);
  45961. + } // non-ep0 endpoints
  45962. + else {
  45963. +#ifdef DWC_UTE_CFI
  45964. + if (ep->dwc_ep.buff_mode != BM_STANDARD) {
  45965. + /* store the request length */
  45966. + ep->dwc_ep.cfi_req_len = buflen;
  45967. + pcd->cfi->ops.build_descriptors(pcd->cfi, pcd,
  45968. + ep, req);
  45969. + } else {
  45970. +#endif
  45971. + max_transfer =
  45972. + GET_CORE_IF(ep->pcd)->core_params->
  45973. + max_transfer_size;
  45974. +
  45975. + /* Setup and start the Transfer */
  45976. + if (req->dw_align_buf){
  45977. + if (ep->dwc_ep.is_in)
  45978. + dwc_memcpy(req->dw_align_buf,
  45979. + buf, buflen);
  45980. + ep->dwc_ep.dma_addr =
  45981. + req->dw_align_buf_dma;
  45982. + ep->dwc_ep.start_xfer_buff =
  45983. + req->dw_align_buf;
  45984. + ep->dwc_ep.xfer_buff =
  45985. + req->dw_align_buf;
  45986. + } else {
  45987. + ep->dwc_ep.dma_addr = dma_buf;
  45988. + ep->dwc_ep.start_xfer_buff = buf;
  45989. + ep->dwc_ep.xfer_buff = buf;
  45990. + }
  45991. + ep->dwc_ep.xfer_len = 0;
  45992. + ep->dwc_ep.xfer_count = 0;
  45993. + ep->dwc_ep.sent_zlp = 0;
  45994. + ep->dwc_ep.total_len = buflen;
  45995. +
  45996. + ep->dwc_ep.maxxfer = max_transfer;
  45997. + if (GET_CORE_IF(pcd)->dma_desc_enable) {
  45998. + uint32_t out_max_xfer =
  45999. + DDMA_MAX_TRANSFER_SIZE -
  46000. + (DDMA_MAX_TRANSFER_SIZE % 4);
  46001. + if (ep->dwc_ep.is_in) {
  46002. + if (ep->dwc_ep.maxxfer >
  46003. + DDMA_MAX_TRANSFER_SIZE) {
  46004. + ep->dwc_ep.maxxfer =
  46005. + DDMA_MAX_TRANSFER_SIZE;
  46006. + }
  46007. + } else {
  46008. + if (ep->dwc_ep.maxxfer >
  46009. + out_max_xfer) {
  46010. + ep->dwc_ep.maxxfer =
  46011. + out_max_xfer;
  46012. + }
  46013. + }
  46014. + }
  46015. + if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {
  46016. + ep->dwc_ep.maxxfer -=
  46017. + (ep->dwc_ep.maxxfer %
  46018. + ep->dwc_ep.maxpacket);
  46019. + }
  46020. +
  46021. + if (zero) {
  46022. + if ((ep->dwc_ep.total_len %
  46023. + ep->dwc_ep.maxpacket == 0)
  46024. + && (ep->dwc_ep.total_len != 0)) {
  46025. + ep->dwc_ep.sent_zlp = 1;
  46026. + }
  46027. + }
  46028. +#ifdef DWC_UTE_CFI
  46029. + }
  46030. +#endif
  46031. + dwc_otg_ep_start_transfer(GET_CORE_IF(pcd),
  46032. + &ep->dwc_ep);
  46033. + }
  46034. + }
  46035. +
  46036. + if (req != 0) {
  46037. + ++pcd->request_pending;
  46038. + DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry);
  46039. + if (ep->dwc_ep.is_in && ep->stopped
  46040. + && !(GET_CORE_IF(pcd)->dma_enable)) {
  46041. + /** @todo NGS Create a function for this. */
  46042. + diepmsk_data_t diepmsk = {.d32 = 0 };
  46043. + diepmsk.b.intktxfemp = 1;
  46044. + if (GET_CORE_IF(pcd)->multiproc_int_enable) {
  46045. + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->
  46046. + dev_if->dev_global_regs->diepeachintmsk
  46047. + [ep->dwc_ep.num], 0,
  46048. + diepmsk.d32);
  46049. + } else {
  46050. + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->
  46051. + dev_if->dev_global_regs->
  46052. + diepmsk, 0, diepmsk.d32);
  46053. + }
  46054. +
  46055. + }
  46056. + }
  46057. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  46058. +
  46059. + return 0;
  46060. +}
  46061. +
  46062. +int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle,
  46063. + void *req_handle)
  46064. +{
  46065. + dwc_irqflags_t flags;
  46066. + dwc_otg_pcd_request_t *req;
  46067. + dwc_otg_pcd_ep_t *ep;
  46068. +
  46069. + ep = get_ep_from_handle(pcd, ep_handle);
  46070. + if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) {
  46071. + DWC_WARN("bad argument\n");
  46072. + return -DWC_E_INVALID;
  46073. + }
  46074. +
  46075. + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
  46076. +
  46077. + /* make sure it's actually queued on this endpoint */
  46078. + DWC_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) {
  46079. + if (req->priv == (void *)req_handle) {
  46080. + break;
  46081. + }
  46082. + }
  46083. +
  46084. + if (req->priv != (void *)req_handle) {
  46085. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  46086. + return -DWC_E_INVALID;
  46087. + }
  46088. +
  46089. + if (!DWC_CIRCLEQ_EMPTY_ENTRY(req, queue_entry)) {
  46090. + dwc_otg_request_done(ep, req, -DWC_E_RESTART);
  46091. + } else {
  46092. + req = NULL;
  46093. + }
  46094. +
  46095. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  46096. +
  46097. + return req ? 0 : -DWC_E_SHUTDOWN;
  46098. +
  46099. +}
  46100. +
  46101. +/**
  46102. + * dwc_otg_pcd_ep_wedge - sets the halt feature and ignores clear requests
  46103. + *
  46104. + * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)
  46105. + * requests. If the gadget driver clears the halt status, it will
  46106. + * automatically unwedge the endpoint.
  46107. + *
  46108. + * Returns zero on success, else negative DWC error code.
  46109. + */
  46110. +int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle)
  46111. +{
  46112. + dwc_otg_pcd_ep_t *ep;
  46113. + dwc_irqflags_t flags;
  46114. + int retval = 0;
  46115. +
  46116. + ep = get_ep_from_handle(pcd, ep_handle);
  46117. +
  46118. + if ((!ep->desc && ep != &pcd->ep0) ||
  46119. + (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) {
  46120. + DWC_WARN("%s, bad ep\n", __func__);
  46121. + return -DWC_E_INVALID;
  46122. + }
  46123. +
  46124. + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
  46125. + if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
  46126. + DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num,
  46127. + ep->dwc_ep.is_in ? "IN" : "OUT");
  46128. + retval = -DWC_E_AGAIN;
  46129. + } else {
  46130. + /* This code needs to be reviewed */
  46131. + if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) {
  46132. + dtxfsts_data_t txstatus;
  46133. + fifosize_data_t txfifosize;
  46134. +
  46135. + txfifosize.d32 =
  46136. + DWC_READ_REG32(&GET_CORE_IF(pcd)->
  46137. + core_global_regs->dtxfsiz[ep->dwc_ep.
  46138. + tx_fifo_num]);
  46139. + txstatus.d32 =
  46140. + DWC_READ_REG32(&GET_CORE_IF(pcd)->
  46141. + dev_if->in_ep_regs[ep->dwc_ep.num]->
  46142. + dtxfsts);
  46143. +
  46144. + if (txstatus.b.txfspcavail < txfifosize.b.depth) {
  46145. + DWC_WARN("%s() Data In Tx Fifo\n", __func__);
  46146. + retval = -DWC_E_AGAIN;
  46147. + } else {
  46148. + if (ep->dwc_ep.num == 0) {
  46149. + pcd->ep0state = EP0_STALL;
  46150. + }
  46151. +
  46152. + ep->stopped = 1;
  46153. + dwc_otg_ep_set_stall(GET_CORE_IF(pcd),
  46154. + &ep->dwc_ep);
  46155. + }
  46156. + } else {
  46157. + if (ep->dwc_ep.num == 0) {
  46158. + pcd->ep0state = EP0_STALL;
  46159. + }
  46160. +
  46161. + ep->stopped = 1;
  46162. + dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
  46163. + }
  46164. + }
  46165. +
  46166. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  46167. +
  46168. + return retval;
  46169. +}
  46170. +
  46171. +int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value)
  46172. +{
  46173. + dwc_otg_pcd_ep_t *ep;
  46174. + dwc_irqflags_t flags;
  46175. + int retval = 0;
  46176. +
  46177. + ep = get_ep_from_handle(pcd, ep_handle);
  46178. +
  46179. + if (!ep || (!ep->desc && ep != &pcd->ep0) ||
  46180. + (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) {
  46181. + DWC_WARN("%s, bad ep\n", __func__);
  46182. + return -DWC_E_INVALID;
  46183. + }
  46184. +
  46185. + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
  46186. + if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
  46187. + DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num,
  46188. + ep->dwc_ep.is_in ? "IN" : "OUT");
  46189. + retval = -DWC_E_AGAIN;
  46190. + } else if (value == 0) {
  46191. + dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
  46192. + } else if (value == 1) {
  46193. + if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) {
  46194. + dtxfsts_data_t txstatus;
  46195. + fifosize_data_t txfifosize;
  46196. +
  46197. + txfifosize.d32 =
  46198. + DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->
  46199. + dtxfsiz[ep->dwc_ep.tx_fifo_num]);
  46200. + txstatus.d32 =
  46201. + DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
  46202. + in_ep_regs[ep->dwc_ep.num]->dtxfsts);
  46203. +
  46204. + if (txstatus.b.txfspcavail < txfifosize.b.depth) {
  46205. + DWC_WARN("%s() Data In Tx Fifo\n", __func__);
  46206. + retval = -DWC_E_AGAIN;
  46207. + } else {
  46208. + if (ep->dwc_ep.num == 0) {
  46209. + pcd->ep0state = EP0_STALL;
  46210. + }
  46211. +
  46212. + ep->stopped = 1;
  46213. + dwc_otg_ep_set_stall(GET_CORE_IF(pcd),
  46214. + &ep->dwc_ep);
  46215. + }
  46216. + } else {
  46217. + if (ep->dwc_ep.num == 0) {
  46218. + pcd->ep0state = EP0_STALL;
  46219. + }
  46220. +
  46221. + ep->stopped = 1;
  46222. + dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
  46223. + }
  46224. + } else if (value == 2) {
  46225. + ep->dwc_ep.stall_clear_flag = 0;
  46226. + } else if (value == 3) {
  46227. + ep->dwc_ep.stall_clear_flag = 1;
  46228. + }
  46229. +
  46230. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  46231. +
  46232. + return retval;
  46233. +}
  46234. +
  46235. +/**
  46236. + * This function initiates remote wakeup of the host from suspend state.
  46237. + */
  46238. +void dwc_otg_pcd_rem_wkup_from_suspend(dwc_otg_pcd_t * pcd, int set)
  46239. +{
  46240. + dctl_data_t dctl = { 0 };
  46241. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  46242. + dsts_data_t dsts;
  46243. +
  46244. + dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
  46245. + if (!dsts.b.suspsts) {
  46246. + DWC_WARN("Remote wakeup while is not in suspend state\n");
  46247. + }
  46248. + /* Check if DEVICE_REMOTE_WAKEUP feature enabled */
  46249. + if (pcd->remote_wakeup_enable) {
  46250. + if (set) {
  46251. +
  46252. + if (core_if->adp_enable) {
  46253. + gpwrdn_data_t gpwrdn;
  46254. +
  46255. + dwc_otg_adp_probe_stop(core_if);
  46256. +
  46257. + /* Mask SRP detected interrupt from Power Down Logic */
  46258. + gpwrdn.d32 = 0;
  46259. + gpwrdn.b.srp_det_msk = 1;
  46260. + DWC_MODIFY_REG32(&core_if->
  46261. + core_global_regs->gpwrdn,
  46262. + gpwrdn.d32, 0);
  46263. +
  46264. + /* Disable Power Down Logic */
  46265. + gpwrdn.d32 = 0;
  46266. + gpwrdn.b.pmuactv = 1;
  46267. + DWC_MODIFY_REG32(&core_if->
  46268. + core_global_regs->gpwrdn,
  46269. + gpwrdn.d32, 0);
  46270. +
  46271. + /*
  46272. + * Initialize the Core for Device mode.
  46273. + */
  46274. + core_if->op_state = B_PERIPHERAL;
  46275. + dwc_otg_core_init(core_if);
  46276. + dwc_otg_enable_global_interrupts(core_if);
  46277. + cil_pcd_start(core_if);
  46278. +
  46279. + dwc_otg_initiate_srp(core_if);
  46280. + }
  46281. +
  46282. + dctl.b.rmtwkupsig = 1;
  46283. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
  46284. + dctl, 0, dctl.d32);
  46285. + DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");
  46286. +
  46287. + dwc_mdelay(2);
  46288. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
  46289. + dctl, dctl.d32, 0);
  46290. + DWC_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n");
  46291. + }
  46292. + } else {
  46293. + DWC_DEBUGPL(DBG_PCD, "Remote Wakeup is disabled\n");
  46294. + }
  46295. +}
  46296. +
  46297. +#ifdef CONFIG_USB_DWC_OTG_LPM
  46298. +/**
  46299. + * This function initiates remote wakeup of the host from L1 sleep state.
  46300. + */
  46301. +void dwc_otg_pcd_rem_wkup_from_sleep(dwc_otg_pcd_t * pcd, int set)
  46302. +{
  46303. + glpmcfg_data_t lpmcfg;
  46304. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  46305. +
  46306. + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
  46307. +
  46308. + /* Check if we are in L1 state */
  46309. + if (!lpmcfg.b.prt_sleep_sts) {
  46310. + DWC_DEBUGPL(DBG_PCD, "Device is not in sleep state\n");
  46311. + return;
  46312. + }
  46313. +
  46314. + /* Check if host allows remote wakeup */
  46315. + if (!lpmcfg.b.rem_wkup_en) {
  46316. + DWC_DEBUGPL(DBG_PCD, "Host does not allow remote wakeup\n");
  46317. + return;
  46318. + }
  46319. +
  46320. + /* Check if Resume OK */
  46321. + if (!lpmcfg.b.sleep_state_resumeok) {
  46322. + DWC_DEBUGPL(DBG_PCD, "Sleep state resume is not OK\n");
  46323. + return;
  46324. + }
  46325. +
  46326. + lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg);
  46327. + lpmcfg.b.en_utmi_sleep = 0;
  46328. + lpmcfg.b.hird_thres &= (~(1 << 4));
  46329. + DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
  46330. +
  46331. + if (set) {
  46332. + dctl_data_t dctl = {.d32 = 0 };
  46333. + dctl.b.rmtwkupsig = 1;
  46334. + /* Set RmtWkUpSig bit to start remote wakup signaling.
  46335. + * Hardware will automatically clear this bit.
  46336. + */
  46337. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl,
  46338. + 0, dctl.d32);
  46339. + DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n");
  46340. + }
  46341. +
  46342. +}
  46343. +#endif
  46344. +
  46345. +/**
  46346. + * Performs remote wakeup.
  46347. + */
  46348. +void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set)
  46349. +{
  46350. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  46351. + dwc_irqflags_t flags;
  46352. + if (dwc_otg_is_device_mode(core_if)) {
  46353. + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
  46354. +#ifdef CONFIG_USB_DWC_OTG_LPM
  46355. + if (core_if->lx_state == DWC_OTG_L1) {
  46356. + dwc_otg_pcd_rem_wkup_from_sleep(pcd, set);
  46357. + } else {
  46358. +#endif
  46359. + dwc_otg_pcd_rem_wkup_from_suspend(pcd, set);
  46360. +#ifdef CONFIG_USB_DWC_OTG_LPM
  46361. + }
  46362. +#endif
  46363. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  46364. + }
  46365. + return;
  46366. +}
  46367. +
  46368. +void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs)
  46369. +{
  46370. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  46371. + dctl_data_t dctl = { 0 };
  46372. +
  46373. + if (dwc_otg_is_device_mode(core_if)) {
  46374. + dctl.b.sftdiscon = 1;
  46375. + DWC_PRINTF("Soft disconnect for %d useconds\n",no_of_usecs);
  46376. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32);
  46377. + dwc_udelay(no_of_usecs);
  46378. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32,0);
  46379. +
  46380. + } else{
  46381. + DWC_PRINTF("NOT SUPPORTED IN HOST MODE\n");
  46382. + }
  46383. + return;
  46384. +
  46385. +}
  46386. +
  46387. +int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd)
  46388. +{
  46389. + dsts_data_t dsts;
  46390. + gotgctl_data_t gotgctl;
  46391. +
  46392. + /*
  46393. + * This function starts the Protocol if no session is in progress. If
  46394. + * a session is already in progress, but the device is suspended,
  46395. + * remote wakeup signaling is started.
  46396. + */
  46397. +
  46398. + /* Check if valid session */
  46399. + gotgctl.d32 =
  46400. + DWC_READ_REG32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl));
  46401. + if (gotgctl.b.bsesvld) {
  46402. + /* Check if suspend state */
  46403. + dsts.d32 =
  46404. + DWC_READ_REG32(&
  46405. + (GET_CORE_IF(pcd)->dev_if->
  46406. + dev_global_regs->dsts));
  46407. + if (dsts.b.suspsts) {
  46408. + dwc_otg_pcd_remote_wakeup(pcd, 1);
  46409. + }
  46410. + } else {
  46411. + dwc_otg_pcd_initiate_srp(pcd);
  46412. + }
  46413. +
  46414. + return 0;
  46415. +
  46416. +}
  46417. +
  46418. +/**
  46419. + * Start the SRP timer to detect when the SRP does not complete within
  46420. + * 6 seconds.
  46421. + *
  46422. + * @param pcd the pcd structure.
  46423. + */
  46424. +void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd)
  46425. +{
  46426. + dwc_irqflags_t flags;
  46427. + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags);
  46428. + dwc_otg_initiate_srp(GET_CORE_IF(pcd));
  46429. + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags);
  46430. +}
  46431. +
  46432. +int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd)
  46433. +{
  46434. + return dwc_otg_get_frame_number(GET_CORE_IF(pcd));
  46435. +}
  46436. +
  46437. +int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd)
  46438. +{
  46439. + return GET_CORE_IF(pcd)->core_params->lpm_enable;
  46440. +}
  46441. +
  46442. +uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd)
  46443. +{
  46444. + return pcd->b_hnp_enable;
  46445. +}
  46446. +
  46447. +uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd)
  46448. +{
  46449. + return pcd->a_hnp_support;
  46450. +}
  46451. +
  46452. +uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd)
  46453. +{
  46454. + return pcd->a_alt_hnp_support;
  46455. +}
  46456. +
  46457. +int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd)
  46458. +{
  46459. + return pcd->remote_wakeup_enable;
  46460. +}
  46461. +
  46462. +#endif /* DWC_HOST_ONLY */
  46463. --- /dev/null
  46464. +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h
  46465. @@ -0,0 +1,266 @@
  46466. +/* ==========================================================================
  46467. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $
  46468. + * $Revision: #48 $
  46469. + * $Date: 2012/08/10 $
  46470. + * $Change: 2047372 $
  46471. + *
  46472. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  46473. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  46474. + * otherwise expressly agreed to in writing between Synopsys and you.
  46475. + *
  46476. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  46477. + * any End User Software License Agreement or Agreement for Licensed Product
  46478. + * with Synopsys or any supplement thereto. You are permitted to use and
  46479. + * redistribute this Software in source and binary forms, with or without
  46480. + * modification, provided that redistributions of source code must retain this
  46481. + * notice. You may not view, use, disclose, copy or distribute this file or
  46482. + * any information contained herein except pursuant to this license grant from
  46483. + * Synopsys. If you do not agree with this notice, including the disclaimer
  46484. + * below, then you are not authorized to use the Software.
  46485. + *
  46486. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  46487. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  46488. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  46489. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  46490. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  46491. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  46492. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  46493. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  46494. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  46495. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  46496. + * DAMAGE.
  46497. + * ========================================================================== */
  46498. +#ifndef DWC_HOST_ONLY
  46499. +#if !defined(__DWC_PCD_H__)
  46500. +#define __DWC_PCD_H__
  46501. +
  46502. +#include "dwc_otg_os_dep.h"
  46503. +#include "usb.h"
  46504. +#include "dwc_otg_cil.h"
  46505. +#include "dwc_otg_pcd_if.h"
  46506. +struct cfiobject;
  46507. +
  46508. +/**
  46509. + * @file
  46510. + *
  46511. + * This file contains the structures, constants, and interfaces for
  46512. + * the Perpherial Contoller Driver (PCD).
  46513. + *
  46514. + * The Peripheral Controller Driver (PCD) for Linux will implement the
  46515. + * Gadget API, so that the existing Gadget drivers can be used. For
  46516. + * the Mass Storage Function driver the File-backed USB Storage Gadget
  46517. + * (FBS) driver will be used. The FBS driver supports the
  46518. + * Control-Bulk (CB), Control-Bulk-Interrupt (CBI), and Bulk-Only
  46519. + * transports.
  46520. + *
  46521. + */
  46522. +
  46523. +/** Invalid DMA Address */
  46524. +#define DWC_DMA_ADDR_INVALID (~(dwc_dma_t)0)
  46525. +
  46526. +/** Max Transfer size for any EP */
  46527. +#define DDMA_MAX_TRANSFER_SIZE 65535
  46528. +
  46529. +/**
  46530. + * Get the pointer to the core_if from the pcd pointer.
  46531. + */
  46532. +#define GET_CORE_IF( _pcd ) (_pcd->core_if)
  46533. +
  46534. +/**
  46535. + * States of EP0.
  46536. + */
  46537. +typedef enum ep0_state {
  46538. + EP0_DISCONNECT, /* no host */
  46539. + EP0_IDLE,
  46540. + EP0_IN_DATA_PHASE,
  46541. + EP0_OUT_DATA_PHASE,
  46542. + EP0_IN_STATUS_PHASE,
  46543. + EP0_OUT_STATUS_PHASE,
  46544. + EP0_STALL,
  46545. +} ep0state_e;
  46546. +
  46547. +/** Fordward declaration.*/
  46548. +struct dwc_otg_pcd;
  46549. +
  46550. +/** DWC_otg iso request structure.
  46551. + *
  46552. + */
  46553. +typedef struct usb_iso_request dwc_otg_pcd_iso_request_t;
  46554. +
  46555. +#ifdef DWC_UTE_PER_IO
  46556. +
  46557. +/**
  46558. + * This shall be the exact analogy of the same type structure defined in the
  46559. + * usb_gadget.h. Each descriptor contains
  46560. + */
  46561. +struct dwc_iso_pkt_desc_port {
  46562. + uint32_t offset;
  46563. + uint32_t length; /* expected length */
  46564. + uint32_t actual_length;
  46565. + uint32_t status;
  46566. +};
  46567. +
  46568. +struct dwc_iso_xreq_port {
  46569. + /** transfer/submission flag */
  46570. + uint32_t tr_sub_flags;
  46571. + /** Start the request ASAP */
  46572. +#define DWC_EREQ_TF_ASAP 0x00000002
  46573. + /** Just enqueue the request w/o initiating a transfer */
  46574. +#define DWC_EREQ_TF_ENQUEUE 0x00000004
  46575. +
  46576. + /**
  46577. + * count of ISO packets attached to this request - shall
  46578. + * not exceed the pio_alloc_pkt_count
  46579. + */
  46580. + uint32_t pio_pkt_count;
  46581. + /** count of ISO packets allocated for this request */
  46582. + uint32_t pio_alloc_pkt_count;
  46583. + /** number of ISO packet errors */
  46584. + uint32_t error_count;
  46585. + /** reserved for future extension */
  46586. + uint32_t res;
  46587. + /** Will be allocated and freed in the UTE gadget and based on the CFC value */
  46588. + struct dwc_iso_pkt_desc_port *per_io_frame_descs;
  46589. +};
  46590. +#endif
  46591. +/** DWC_otg request structure.
  46592. + * This structure is a list of requests.
  46593. + */
  46594. +typedef struct dwc_otg_pcd_request {
  46595. + void *priv;
  46596. + void *buf;
  46597. + dwc_dma_t dma;
  46598. + uint32_t length;
  46599. + uint32_t actual;
  46600. + unsigned sent_zlp:1;
  46601. + /**
  46602. + * Used instead of original buffer if
  46603. + * it(physical address) is not dword-aligned.
  46604. + **/
  46605. + uint8_t *dw_align_buf;
  46606. + dwc_dma_t dw_align_buf_dma;
  46607. +
  46608. + DWC_CIRCLEQ_ENTRY(dwc_otg_pcd_request) queue_entry;
  46609. +#ifdef DWC_UTE_PER_IO
  46610. + struct dwc_iso_xreq_port ext_req;
  46611. + //void *priv_ereq_nport; /* */
  46612. +#endif
  46613. +} dwc_otg_pcd_request_t;
  46614. +
  46615. +DWC_CIRCLEQ_HEAD(req_list, dwc_otg_pcd_request);
  46616. +
  46617. +/** PCD EP structure.
  46618. + * This structure describes an EP, there is an array of EPs in the PCD
  46619. + * structure.
  46620. + */
  46621. +typedef struct dwc_otg_pcd_ep {
  46622. + /** USB EP Descriptor */
  46623. + const usb_endpoint_descriptor_t *desc;
  46624. +
  46625. + /** queue of dwc_otg_pcd_requests. */
  46626. + struct req_list queue;
  46627. + unsigned stopped:1;
  46628. + unsigned disabling:1;
  46629. + unsigned dma:1;
  46630. + unsigned queue_sof:1;
  46631. +
  46632. +#ifdef DWC_EN_ISOC
  46633. + /** ISOC req handle passed */
  46634. + void *iso_req_handle;
  46635. +#endif //_EN_ISOC_
  46636. +
  46637. + /** DWC_otg ep data. */
  46638. + dwc_ep_t dwc_ep;
  46639. +
  46640. + /** Pointer to PCD */
  46641. + struct dwc_otg_pcd *pcd;
  46642. +
  46643. + void *priv;
  46644. +} dwc_otg_pcd_ep_t;
  46645. +
  46646. +/** DWC_otg PCD Structure.
  46647. + * This structure encapsulates the data for the dwc_otg PCD.
  46648. + */
  46649. +struct dwc_otg_pcd {
  46650. + const struct dwc_otg_pcd_function_ops *fops;
  46651. + /** The DWC otg device pointer */
  46652. + struct dwc_otg_device *otg_dev;
  46653. + /** Core Interface */
  46654. + dwc_otg_core_if_t *core_if;
  46655. + /** State of EP0 */
  46656. + ep0state_e ep0state;
  46657. + /** EP0 Request is pending */
  46658. + unsigned ep0_pending:1;
  46659. + /** Indicates when SET CONFIGURATION Request is in process */
  46660. + unsigned request_config:1;
  46661. + /** The state of the Remote Wakeup Enable. */
  46662. + unsigned remote_wakeup_enable:1;
  46663. + /** The state of the B-Device HNP Enable. */
  46664. + unsigned b_hnp_enable:1;
  46665. + /** The state of A-Device HNP Support. */
  46666. + unsigned a_hnp_support:1;
  46667. + /** The state of the A-Device Alt HNP support. */
  46668. + unsigned a_alt_hnp_support:1;
  46669. + /** Count of pending Requests */
  46670. + unsigned request_pending;
  46671. +
  46672. + /** SETUP packet for EP0
  46673. + * This structure is allocated as a DMA buffer on PCD initialization
  46674. + * with enough space for up to 3 setup packets.
  46675. + */
  46676. + union {
  46677. + usb_device_request_t req;
  46678. + uint32_t d32[2];
  46679. + } *setup_pkt;
  46680. +
  46681. + dwc_dma_t setup_pkt_dma_handle;
  46682. +
  46683. + /* Additional buffer and flag for CTRL_WR premature case */
  46684. + uint8_t *backup_buf;
  46685. + unsigned data_terminated;
  46686. +
  46687. + /** 2-byte dma buffer used to return status from GET_STATUS */
  46688. + uint16_t *status_buf;
  46689. + dwc_dma_t status_buf_dma_handle;
  46690. +
  46691. + /** EP0 */
  46692. + dwc_otg_pcd_ep_t ep0;
  46693. +
  46694. + /** Array of IN EPs. */
  46695. + dwc_otg_pcd_ep_t in_ep[MAX_EPS_CHANNELS - 1];
  46696. + /** Array of OUT EPs. */
  46697. + dwc_otg_pcd_ep_t out_ep[MAX_EPS_CHANNELS - 1];
  46698. + /** number of valid EPs in the above array. */
  46699. +// unsigned num_eps : 4;
  46700. + dwc_spinlock_t *lock;
  46701. +
  46702. + /** Tasklet to defer starting of TEST mode transmissions until
  46703. + * Status Phase has been completed.
  46704. + */
  46705. + dwc_tasklet_t *test_mode_tasklet;
  46706. +
  46707. + /** Tasklet to delay starting of xfer in DMA mode */
  46708. + dwc_tasklet_t *start_xfer_tasklet;
  46709. +
  46710. + /** The test mode to enter when the tasklet is executed. */
  46711. + unsigned test_mode;
  46712. + /** The cfi_api structure that implements most of the CFI API
  46713. + * and OTG specific core configuration functionality
  46714. + */
  46715. +#ifdef DWC_UTE_CFI
  46716. + struct cfiobject *cfi;
  46717. +#endif
  46718. +
  46719. +};
  46720. +
  46721. +//FIXME this functions should be static, and this prototypes should be removed
  46722. +extern void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep);
  46723. +extern void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep,
  46724. + dwc_otg_pcd_request_t * req, int32_t status);
  46725. +
  46726. +void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep,
  46727. + void *req_handle);
  46728. +
  46729. +extern void do_test_mode(void *data);
  46730. +#endif
  46731. +#endif /* DWC_HOST_ONLY */
  46732. --- /dev/null
  46733. +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
  46734. @@ -0,0 +1,360 @@
  46735. +/* ==========================================================================
  46736. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $
  46737. + * $Revision: #11 $
  46738. + * $Date: 2011/10/26 $
  46739. + * $Change: 1873028 $
  46740. + *
  46741. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  46742. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  46743. + * otherwise expressly agreed to in writing between Synopsys and you.
  46744. + *
  46745. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  46746. + * any End User Software License Agreement or Agreement for Licensed Product
  46747. + * with Synopsys or any supplement thereto. You are permitted to use and
  46748. + * redistribute this Software in source and binary forms, with or without
  46749. + * modification, provided that redistributions of source code must retain this
  46750. + * notice. You may not view, use, disclose, copy or distribute this file or
  46751. + * any information contained herein except pursuant to this license grant from
  46752. + * Synopsys. If you do not agree with this notice, including the disclaimer
  46753. + * below, then you are not authorized to use the Software.
  46754. + *
  46755. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  46756. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  46757. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  46758. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  46759. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  46760. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  46761. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  46762. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  46763. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  46764. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  46765. + * DAMAGE.
  46766. + * ========================================================================== */
  46767. +#ifndef DWC_HOST_ONLY
  46768. +
  46769. +#if !defined(__DWC_PCD_IF_H__)
  46770. +#define __DWC_PCD_IF_H__
  46771. +
  46772. +//#include "dwc_os.h"
  46773. +#include "dwc_otg_core_if.h"
  46774. +
  46775. +/** @file
  46776. + * This file defines DWC_OTG PCD Core API.
  46777. + */
  46778. +
  46779. +struct dwc_otg_pcd;
  46780. +typedef struct dwc_otg_pcd dwc_otg_pcd_t;
  46781. +
  46782. +/** Maxpacket size for EP0 */
  46783. +#define MAX_EP0_SIZE 64
  46784. +/** Maxpacket size for any EP */
  46785. +#define MAX_PACKET_SIZE 1024
  46786. +
  46787. +/** @name Function Driver Callbacks */
  46788. +/** @{ */
  46789. +
  46790. +/** This function will be called whenever a previously queued request has
  46791. + * completed. The status value will be set to -DWC_E_SHUTDOWN to indicated a
  46792. + * failed or aborted transfer, or -DWC_E_RESTART to indicate the device was reset,
  46793. + * or -DWC_E_TIMEOUT to indicate it timed out, or -DWC_E_INVALID to indicate invalid
  46794. + * parameters. */
  46795. +typedef int (*dwc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
  46796. + void *req_handle, int32_t status,
  46797. + uint32_t actual);
  46798. +/**
  46799. + * This function will be called whenever a previousle queued ISOC request has
  46800. + * completed. Count of ISOC packets could be read using dwc_otg_pcd_get_iso_packet_count
  46801. + * function.
  46802. + * The status of each ISOC packet could be read using dwc_otg_pcd_get_iso_packet_*
  46803. + * functions.
  46804. + */
  46805. +typedef int (*dwc_isoc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
  46806. + void *req_handle, int proc_buf_num);
  46807. +/** This function should handle any SETUP request that cannot be handled by the
  46808. + * PCD Core. This includes most GET_DESCRIPTORs, SET_CONFIGS, Any
  46809. + * class-specific requests, etc. The function must non-blocking.
  46810. + *
  46811. + * Returns 0 on success.
  46812. + * Returns -DWC_E_NOT_SUPPORTED if the request is not supported.
  46813. + * Returns -DWC_E_INVALID if the setup request had invalid parameters or bytes.
  46814. + * Returns -DWC_E_SHUTDOWN on any other error. */
  46815. +typedef int (*dwc_setup_cb_t) (dwc_otg_pcd_t * pcd, uint8_t * bytes);
  46816. +/** This is called whenever the device has been disconnected. The function
  46817. + * driver should take appropriate action to clean up all pending requests in the
  46818. + * PCD Core, remove all endpoints (except ep0), and initialize back to reset
  46819. + * state. */
  46820. +typedef int (*dwc_disconnect_cb_t) (dwc_otg_pcd_t * pcd);
  46821. +/** This function is called when device has been connected. */
  46822. +typedef int (*dwc_connect_cb_t) (dwc_otg_pcd_t * pcd, int speed);
  46823. +/** This function is called when device has been suspended */
  46824. +typedef int (*dwc_suspend_cb_t) (dwc_otg_pcd_t * pcd);
  46825. +/** This function is called when device has received LPM tokens, i.e.
  46826. + * device has been sent to sleep state. */
  46827. +typedef int (*dwc_sleep_cb_t) (dwc_otg_pcd_t * pcd);
  46828. +/** This function is called when device has been resumed
  46829. + * from suspend(L2) or L1 sleep state. */
  46830. +typedef int (*dwc_resume_cb_t) (dwc_otg_pcd_t * pcd);
  46831. +/** This function is called whenever hnp params has been changed.
  46832. + * User can call get_b_hnp_enable, get_a_hnp_support, get_a_alt_hnp_support functions
  46833. + * to get hnp parameters. */
  46834. +typedef int (*dwc_hnp_params_changed_cb_t) (dwc_otg_pcd_t * pcd);
  46835. +/** This function is called whenever USB RESET is detected. */
  46836. +typedef int (*dwc_reset_cb_t) (dwc_otg_pcd_t * pcd);
  46837. +
  46838. +typedef int (*cfi_setup_cb_t) (dwc_otg_pcd_t * pcd, void *ctrl_req_bytes);
  46839. +
  46840. +/**
  46841. + *
  46842. + * @param ep_handle Void pointer to the usb_ep structure
  46843. + * @param ereq_port Pointer to the extended request structure created in the
  46844. + * portable part.
  46845. + */
  46846. +typedef int (*xiso_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle,
  46847. + void *req_handle, int32_t status,
  46848. + void *ereq_port);
  46849. +/** Function Driver Ops Data Structure */
  46850. +struct dwc_otg_pcd_function_ops {
  46851. + dwc_connect_cb_t connect;
  46852. + dwc_disconnect_cb_t disconnect;
  46853. + dwc_setup_cb_t setup;
  46854. + dwc_completion_cb_t complete;
  46855. + dwc_isoc_completion_cb_t isoc_complete;
  46856. + dwc_suspend_cb_t suspend;
  46857. + dwc_sleep_cb_t sleep;
  46858. + dwc_resume_cb_t resume;
  46859. + dwc_reset_cb_t reset;
  46860. + dwc_hnp_params_changed_cb_t hnp_changed;
  46861. + cfi_setup_cb_t cfi_setup;
  46862. +#ifdef DWC_UTE_PER_IO
  46863. + xiso_completion_cb_t xisoc_complete;
  46864. +#endif
  46865. +};
  46866. +/** @} */
  46867. +
  46868. +/** @name Function Driver Functions */
  46869. +/** @{ */
  46870. +
  46871. +/** Call this function to get pointer on dwc_otg_pcd_t,
  46872. + * this pointer will be used for all PCD API functions.
  46873. + *
  46874. + * @param core_if The DWC_OTG Core
  46875. + */
  46876. +extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if);
  46877. +
  46878. +/** Frees PCD allocated by dwc_otg_pcd_init
  46879. + *
  46880. + * @param pcd The PCD
  46881. + */
  46882. +extern void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd);
  46883. +
  46884. +/** Call this to bind the function driver to the PCD Core.
  46885. + *
  46886. + * @param pcd Pointer on dwc_otg_pcd_t returned by dwc_otg_pcd_init function.
  46887. + * @param fops The Function Driver Ops data structure containing pointers to all callbacks.
  46888. + */
  46889. +extern void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd,
  46890. + const struct dwc_otg_pcd_function_ops *fops);
  46891. +
  46892. +/** Enables an endpoint for use. This function enables an endpoint in
  46893. + * the PCD. The endpoint is described by the ep_desc which has the
  46894. + * same format as a USB ep descriptor. The ep_handle parameter is used to refer
  46895. + * to the endpoint from other API functions and in callbacks. Normally this
  46896. + * should be called after a SET_CONFIGURATION/SET_INTERFACE to configure the
  46897. + * core for that interface.
  46898. + *
  46899. + * Returns -DWC_E_INVALID if invalid parameters were passed.
  46900. + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
  46901. + * Returns 0 on success.
  46902. + *
  46903. + * @param pcd The PCD
  46904. + * @param ep_desc Endpoint descriptor
  46905. + * @param usb_ep Handle on endpoint, that will be used to identify endpoint.
  46906. + */
  46907. +extern int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd,
  46908. + const uint8_t * ep_desc, void *usb_ep);
  46909. +
  46910. +/** Disable the endpoint referenced by ep_handle.
  46911. + *
  46912. + * Returns -DWC_E_INVALID if invalid parameters were passed.
  46913. + * Returns -DWC_E_SHUTDOWN if any other error occurred.
  46914. + * Returns 0 on success. */
  46915. +extern int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle);
  46916. +
  46917. +/** Queue a data transfer request on the endpoint referenced by ep_handle.
  46918. + * After the transfer is completes, the complete callback will be called with
  46919. + * the request status.
  46920. + *
  46921. + * @param pcd The PCD
  46922. + * @param ep_handle The handle of the endpoint
  46923. + * @param buf The buffer for the data
  46924. + * @param dma_buf The DMA buffer for the data
  46925. + * @param buflen The length of the data transfer
  46926. + * @param zero Specifies whether to send zero length last packet.
  46927. + * @param req_handle Set this handle to any value to use to reference this
  46928. + * request in the ep_dequeue function or from the complete callback
  46929. + * @param atomic_alloc If driver need to perform atomic allocations
  46930. + * for internal data structures.
  46931. + *
  46932. + * Returns -DWC_E_INVALID if invalid parameters were passed.
  46933. + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
  46934. + * Returns 0 on success. */
  46935. +extern int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
  46936. + uint8_t * buf, dwc_dma_t dma_buf,
  46937. + uint32_t buflen, int zero, void *req_handle,
  46938. + int atomic_alloc);
  46939. +#ifdef DWC_UTE_PER_IO
  46940. +/**
  46941. + *
  46942. + * @param ereq_nonport Pointer to the extended request part of the
  46943. + * usb_request structure defined in usb_gadget.h file.
  46944. + */
  46945. +extern int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle,
  46946. + uint8_t * buf, dwc_dma_t dma_buf,
  46947. + uint32_t buflen, int zero,
  46948. + void *req_handle, int atomic_alloc,
  46949. + void *ereq_nonport);
  46950. +
  46951. +#endif
  46952. +
  46953. +/** De-queue the specified data transfer that has not yet completed.
  46954. + *
  46955. + * Returns -DWC_E_INVALID if invalid parameters were passed.
  46956. + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
  46957. + * Returns 0 on success. */
  46958. +extern int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle,
  46959. + void *req_handle);
  46960. +
  46961. +/** Halt (STALL) an endpoint or clear it.
  46962. + *
  46963. + * Returns -DWC_E_INVALID if invalid parameters were passed.
  46964. + * Returns -DWC_E_SHUTDOWN if any other error ocurred.
  46965. + * Returns -DWC_E_AGAIN if the STALL cannot be sent and must be tried again later
  46966. + * Returns 0 on success. */
  46967. +extern int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value);
  46968. +
  46969. +/** This function */
  46970. +extern int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle);
  46971. +
  46972. +/** This function should be called on every hardware interrupt */
  46973. +extern int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd);
  46974. +
  46975. +/** This function returns current frame number */
  46976. +extern int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd);
  46977. +
  46978. +/**
  46979. + * Start isochronous transfers on the endpoint referenced by ep_handle.
  46980. + * For isochronous transfers duble buffering is used.
  46981. + * After processing each of buffers comlete callback will be called with
  46982. + * status for each transaction.
  46983. + *
  46984. + * @param pcd The PCD
  46985. + * @param ep_handle The handle of the endpoint
  46986. + * @param buf0 The virtual address of first data buffer
  46987. + * @param buf1 The virtual address of second data buffer
  46988. + * @param dma0 The DMA address of first data buffer
  46989. + * @param dma1 The DMA address of second data buffer
  46990. + * @param sync_frame Data pattern frame number
  46991. + * @param dp_frame Data size for pattern frame
  46992. + * @param data_per_frame Data size for regular frame
  46993. + * @param start_frame Frame number to start transfers, if -1 then start transfers ASAP.
  46994. + * @param buf_proc_intrvl Interval of ISOC Buffer processing
  46995. + * @param req_handle Handle of ISOC request
  46996. + * @param atomic_alloc Specefies whether to perform atomic allocation for
  46997. + * internal data structures.
  46998. + *
  46999. + * Returns -DWC_E_NO_MEMORY if there is no enough memory.
  47000. + * Returns -DWC_E_INVALID if incorrect arguments are passed to the function.
  47001. + * Returns -DW_E_SHUTDOWN for any other error.
  47002. + * Returns 0 on success
  47003. + */
  47004. +extern int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle,
  47005. + uint8_t * buf0, uint8_t * buf1,
  47006. + dwc_dma_t dma0, dwc_dma_t dma1,
  47007. + int sync_frame, int dp_frame,
  47008. + int data_per_frame, int start_frame,
  47009. + int buf_proc_intrvl, void *req_handle,
  47010. + int atomic_alloc);
  47011. +
  47012. +/** Stop ISOC transfers on endpoint referenced by ep_handle.
  47013. + *
  47014. + * @param pcd The PCD
  47015. + * @param ep_handle The handle of the endpoint
  47016. + * @param req_handle Handle of ISOC request
  47017. + *
  47018. + * Returns -DWC_E_INVALID if incorrect arguments are passed to the function
  47019. + * Returns 0 on success
  47020. + */
  47021. +int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle,
  47022. + void *req_handle);
  47023. +
  47024. +/** Get ISOC packet status.
  47025. + *
  47026. + * @param pcd The PCD
  47027. + * @param ep_handle The handle of the endpoint
  47028. + * @param iso_req_handle Isochronoush request handle
  47029. + * @param packet Number of packet
  47030. + * @param status Out parameter for returning status
  47031. + * @param actual Out parameter for returning actual length
  47032. + * @param offset Out parameter for returning offset
  47033. + *
  47034. + */
  47035. +extern void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd,
  47036. + void *ep_handle,
  47037. + void *iso_req_handle, int packet,
  47038. + int *status, int *actual,
  47039. + int *offset);
  47040. +
  47041. +/** Get ISOC packet count.
  47042. + *
  47043. + * @param pcd The PCD
  47044. + * @param ep_handle The handle of the endpoint
  47045. + * @param iso_req_handle
  47046. + */
  47047. +extern int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd,
  47048. + void *ep_handle,
  47049. + void *iso_req_handle);
  47050. +
  47051. +/** This function starts the SRP Protocol if no session is in progress. If
  47052. + * a session is already in progress, but the device is suspended,
  47053. + * remote wakeup signaling is started.
  47054. + */
  47055. +extern int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd);
  47056. +
  47057. +/** This function returns 1 if LPM support is enabled, and 0 otherwise. */
  47058. +extern int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd);
  47059. +
  47060. +/** This function returns 1 if remote wakeup is allowed and 0, otherwise. */
  47061. +extern int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd);
  47062. +
  47063. +/** Initiate SRP */
  47064. +extern void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd);
  47065. +
  47066. +/** Starts remote wakeup signaling. */
  47067. +extern void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set);
  47068. +
  47069. +/** Starts micorsecond soft disconnect. */
  47070. +extern void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs);
  47071. +/** This function returns whether device is dualspeed.*/
  47072. +extern uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd);
  47073. +
  47074. +/** This function returns whether device is otg. */
  47075. +extern uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd);
  47076. +
  47077. +/** These functions allow to get hnp parameters */
  47078. +extern uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd);
  47079. +extern uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd);
  47080. +extern uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd);
  47081. +
  47082. +/** CFI specific Interface functions */
  47083. +/** Allocate a cfi buffer */
  47084. +extern uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep,
  47085. + dwc_dma_t * addr, size_t buflen,
  47086. + int flags);
  47087. +
  47088. +/******************************************************************************/
  47089. +
  47090. +/** @} */
  47091. +
  47092. +#endif /* __DWC_PCD_IF_H__ */
  47093. +
  47094. +#endif /* DWC_HOST_ONLY */
  47095. --- /dev/null
  47096. +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
  47097. @@ -0,0 +1,5147 @@
  47098. +/* ==========================================================================
  47099. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $
  47100. + * $Revision: #116 $
  47101. + * $Date: 2012/08/10 $
  47102. + * $Change: 2047372 $
  47103. + *
  47104. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  47105. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  47106. + * otherwise expressly agreed to in writing between Synopsys and you.
  47107. + *
  47108. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  47109. + * any End User Software License Agreement or Agreement for Licensed Product
  47110. + * with Synopsys or any supplement thereto. You are permitted to use and
  47111. + * redistribute this Software in source and binary forms, with or without
  47112. + * modification, provided that redistributions of source code must retain this
  47113. + * notice. You may not view, use, disclose, copy or distribute this file or
  47114. + * any information contained herein except pursuant to this license grant from
  47115. + * Synopsys. If you do not agree with this notice, including the disclaimer
  47116. + * below, then you are not authorized to use the Software.
  47117. + *
  47118. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  47119. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  47120. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  47121. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  47122. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  47123. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  47124. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  47125. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  47126. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  47127. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  47128. + * DAMAGE.
  47129. + * ========================================================================== */
  47130. +#ifndef DWC_HOST_ONLY
  47131. +
  47132. +#include "dwc_otg_pcd.h"
  47133. +
  47134. +#ifdef DWC_UTE_CFI
  47135. +#include "dwc_otg_cfi.h"
  47136. +#endif
  47137. +
  47138. +#ifdef DWC_UTE_PER_IO
  47139. +extern void complete_xiso_ep(dwc_otg_pcd_ep_t * ep);
  47140. +#endif
  47141. +//#define PRINT_CFI_DMA_DESCS
  47142. +
  47143. +#define DEBUG_EP0
  47144. +
  47145. +/**
  47146. + * This function updates OTG.
  47147. + */
  47148. +static void dwc_otg_pcd_update_otg(dwc_otg_pcd_t * pcd, const unsigned reset)
  47149. +{
  47150. +
  47151. + if (reset) {
  47152. + pcd->b_hnp_enable = 0;
  47153. + pcd->a_hnp_support = 0;
  47154. + pcd->a_alt_hnp_support = 0;
  47155. + }
  47156. +
  47157. + if (pcd->fops->hnp_changed) {
  47158. + pcd->fops->hnp_changed(pcd);
  47159. + }
  47160. +}
  47161. +
  47162. +/** @file
  47163. + * This file contains the implementation of the PCD Interrupt handlers.
  47164. + *
  47165. + * The PCD handles the device interrupts. Many conditions can cause a
  47166. + * device interrupt. When an interrupt occurs, the device interrupt
  47167. + * service routine determines the cause of the interrupt and
  47168. + * dispatches handling to the appropriate function. These interrupt
  47169. + * handling functions are described below.
  47170. + * All interrupt registers are processed from LSB to MSB.
  47171. + */
  47172. +
  47173. +/**
  47174. + * This function prints the ep0 state for debug purposes.
  47175. + */
  47176. +static inline void print_ep0_state(dwc_otg_pcd_t * pcd)
  47177. +{
  47178. +#ifdef DEBUG
  47179. + char str[40];
  47180. +
  47181. + switch (pcd->ep0state) {
  47182. + case EP0_DISCONNECT:
  47183. + dwc_strcpy(str, "EP0_DISCONNECT");
  47184. + break;
  47185. + case EP0_IDLE:
  47186. + dwc_strcpy(str, "EP0_IDLE");
  47187. + break;
  47188. + case EP0_IN_DATA_PHASE:
  47189. + dwc_strcpy(str, "EP0_IN_DATA_PHASE");
  47190. + break;
  47191. + case EP0_OUT_DATA_PHASE:
  47192. + dwc_strcpy(str, "EP0_OUT_DATA_PHASE");
  47193. + break;
  47194. + case EP0_IN_STATUS_PHASE:
  47195. + dwc_strcpy(str, "EP0_IN_STATUS_PHASE");
  47196. + break;
  47197. + case EP0_OUT_STATUS_PHASE:
  47198. + dwc_strcpy(str, "EP0_OUT_STATUS_PHASE");
  47199. + break;
  47200. + case EP0_STALL:
  47201. + dwc_strcpy(str, "EP0_STALL");
  47202. + break;
  47203. + default:
  47204. + dwc_strcpy(str, "EP0_INVALID");
  47205. + }
  47206. +
  47207. + DWC_DEBUGPL(DBG_ANY, "%s(%d)\n", str, pcd->ep0state);
  47208. +#endif
  47209. +}
  47210. +
  47211. +/**
  47212. + * This function calculate the size of the payload in the memory
  47213. + * for out endpoints and prints size for debug purposes(used in
  47214. + * 2.93a DevOutNak feature).
  47215. + */
  47216. +static inline void print_memory_payload(dwc_otg_pcd_t * pcd, dwc_ep_t * ep)
  47217. +{
  47218. +#ifdef DEBUG
  47219. + deptsiz_data_t deptsiz_init = {.d32 = 0 };
  47220. + deptsiz_data_t deptsiz_updt = {.d32 = 0 };
  47221. + int pack_num;
  47222. + unsigned payload;
  47223. +
  47224. + deptsiz_init.d32 = pcd->core_if->start_doeptsiz_val[ep->num];
  47225. + deptsiz_updt.d32 =
  47226. + DWC_READ_REG32(&pcd->core_if->dev_if->
  47227. + out_ep_regs[ep->num]->doeptsiz);
  47228. + /* Payload will be */
  47229. + payload = deptsiz_init.b.xfersize - deptsiz_updt.b.xfersize;
  47230. + /* Packet count is decremented every time a packet
  47231. + * is written to the RxFIFO not in to the external memory
  47232. + * So, if payload == 0, then it means no packet was sent to ext memory*/
  47233. + pack_num = (!payload) ? 0 : (deptsiz_init.b.pktcnt - deptsiz_updt.b.pktcnt);
  47234. + DWC_DEBUGPL(DBG_PCDV,
  47235. + "Payload for EP%d-%s\n",
  47236. + ep->num, (ep->is_in ? "IN" : "OUT"));
  47237. + DWC_DEBUGPL(DBG_PCDV,
  47238. + "Number of transfered bytes = 0x%08x\n", payload);
  47239. + DWC_DEBUGPL(DBG_PCDV,
  47240. + "Number of transfered packets = %d\n", pack_num);
  47241. +#endif
  47242. +}
  47243. +
  47244. +
  47245. +#ifdef DWC_UTE_CFI
  47246. +static inline void print_desc(struct dwc_otg_dma_desc *ddesc,
  47247. + const uint8_t * epname, int descnum)
  47248. +{
  47249. + CFI_INFO
  47250. + ("%s DMA_DESC(%d) buf=0x%08x bytes=0x%04x; sp=0x%x; l=0x%x; sts=0x%02x; bs=0x%02x\n",
  47251. + epname, descnum, ddesc->buf, ddesc->status.b.bytes,
  47252. + ddesc->status.b.sp, ddesc->status.b.l, ddesc->status.b.sts,
  47253. + ddesc->status.b.bs);
  47254. +}
  47255. +#endif
  47256. +
  47257. +/**
  47258. + * This function returns pointer to in ep struct with number ep_num
  47259. + */
  47260. +static inline dwc_otg_pcd_ep_t *get_in_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
  47261. +{
  47262. + int i;
  47263. + int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
  47264. + if (ep_num == 0) {
  47265. + return &pcd->ep0;
  47266. + } else {
  47267. + for (i = 0; i < num_in_eps; ++i) {
  47268. + if (pcd->in_ep[i].dwc_ep.num == ep_num)
  47269. + return &pcd->in_ep[i];
  47270. + }
  47271. + return 0;
  47272. + }
  47273. +}
  47274. +
  47275. +/**
  47276. + * This function returns pointer to out ep struct with number ep_num
  47277. + */
  47278. +static inline dwc_otg_pcd_ep_t *get_out_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num)
  47279. +{
  47280. + int i;
  47281. + int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
  47282. + if (ep_num == 0) {
  47283. + return &pcd->ep0;
  47284. + } else {
  47285. + for (i = 0; i < num_out_eps; ++i) {
  47286. + if (pcd->out_ep[i].dwc_ep.num == ep_num)
  47287. + return &pcd->out_ep[i];
  47288. + }
  47289. + return 0;
  47290. + }
  47291. +}
  47292. +
  47293. +/**
  47294. + * This functions gets a pointer to an EP from the wIndex address
  47295. + * value of the control request.
  47296. + */
  47297. +dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex)
  47298. +{
  47299. + dwc_otg_pcd_ep_t *ep;
  47300. + uint32_t ep_num = UE_GET_ADDR(wIndex);
  47301. +
  47302. + if (ep_num == 0) {
  47303. + ep = &pcd->ep0;
  47304. + } else if (UE_GET_DIR(wIndex) == UE_DIR_IN) { /* in ep */
  47305. + ep = &pcd->in_ep[ep_num - 1];
  47306. + } else {
  47307. + ep = &pcd->out_ep[ep_num - 1];
  47308. + }
  47309. +
  47310. + return ep;
  47311. +}
  47312. +
  47313. +/**
  47314. + * This function checks the EP request queue, if the queue is not
  47315. + * empty the next request is started.
  47316. + */
  47317. +void start_next_request(dwc_otg_pcd_ep_t * ep)
  47318. +{
  47319. + dwc_otg_pcd_request_t *req = 0;
  47320. + uint32_t max_transfer =
  47321. + GET_CORE_IF(ep->pcd)->core_params->max_transfer_size;
  47322. +
  47323. +#ifdef DWC_UTE_CFI
  47324. + struct dwc_otg_pcd *pcd;
  47325. + pcd = ep->pcd;
  47326. +#endif
  47327. +
  47328. + if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
  47329. + req = DWC_CIRCLEQ_FIRST(&ep->queue);
  47330. +
  47331. +#ifdef DWC_UTE_CFI
  47332. + if (ep->dwc_ep.buff_mode != BM_STANDARD) {
  47333. + ep->dwc_ep.cfi_req_len = req->length;
  47334. + pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ep, req);
  47335. + } else {
  47336. +#endif
  47337. + /* Setup and start the Transfer */
  47338. + if (req->dw_align_buf) {
  47339. + ep->dwc_ep.dma_addr = req->dw_align_buf_dma;
  47340. + ep->dwc_ep.start_xfer_buff = req->dw_align_buf;
  47341. + ep->dwc_ep.xfer_buff = req->dw_align_buf;
  47342. + } else {
  47343. + ep->dwc_ep.dma_addr = req->dma;
  47344. + ep->dwc_ep.start_xfer_buff = req->buf;
  47345. + ep->dwc_ep.xfer_buff = req->buf;
  47346. + }
  47347. + ep->dwc_ep.sent_zlp = 0;
  47348. + ep->dwc_ep.total_len = req->length;
  47349. + ep->dwc_ep.xfer_len = 0;
  47350. + ep->dwc_ep.xfer_count = 0;
  47351. +
  47352. + ep->dwc_ep.maxxfer = max_transfer;
  47353. + if (GET_CORE_IF(ep->pcd)->dma_desc_enable) {
  47354. + uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE
  47355. + - (DDMA_MAX_TRANSFER_SIZE % 4);
  47356. + if (ep->dwc_ep.is_in) {
  47357. + if (ep->dwc_ep.maxxfer >
  47358. + DDMA_MAX_TRANSFER_SIZE) {
  47359. + ep->dwc_ep.maxxfer =
  47360. + DDMA_MAX_TRANSFER_SIZE;
  47361. + }
  47362. + } else {
  47363. + if (ep->dwc_ep.maxxfer > out_max_xfer) {
  47364. + ep->dwc_ep.maxxfer =
  47365. + out_max_xfer;
  47366. + }
  47367. + }
  47368. + }
  47369. + if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) {
  47370. + ep->dwc_ep.maxxfer -=
  47371. + (ep->dwc_ep.maxxfer % ep->dwc_ep.maxpacket);
  47372. + }
  47373. + if (req->sent_zlp) {
  47374. + if ((ep->dwc_ep.total_len %
  47375. + ep->dwc_ep.maxpacket == 0)
  47376. + && (ep->dwc_ep.total_len != 0)) {
  47377. + ep->dwc_ep.sent_zlp = 1;
  47378. + }
  47379. +
  47380. + }
  47381. +#ifdef DWC_UTE_CFI
  47382. + }
  47383. +#endif
  47384. + dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep);
  47385. + } else if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
  47386. + DWC_PRINTF("There are no more ISOC requests \n");
  47387. + ep->dwc_ep.frame_num = 0xFFFFFFFF;
  47388. + }
  47389. +}
  47390. +
  47391. +/**
  47392. + * This function handles the SOF Interrupts. At this time the SOF
  47393. + * Interrupt is disabled.
  47394. + */
  47395. +int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t * pcd)
  47396. +{
  47397. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  47398. +
  47399. + gintsts_data_t gintsts;
  47400. +
  47401. + DWC_DEBUGPL(DBG_PCD, "SOF\n");
  47402. +
  47403. + /* Clear interrupt */
  47404. + gintsts.d32 = 0;
  47405. + gintsts.b.sofintr = 1;
  47406. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
  47407. +
  47408. + return 1;
  47409. +}
  47410. +
  47411. +/**
  47412. + * This function handles the Rx Status Queue Level Interrupt, which
  47413. + * indicates that there is a least one packet in the Rx FIFO. The
  47414. + * packets are moved from the FIFO to memory, where they will be
  47415. + * processed when the Endpoint Interrupt Register indicates Transfer
  47416. + * Complete or SETUP Phase Done.
  47417. + *
  47418. + * Repeat the following until the Rx Status Queue is empty:
  47419. + * -# Read the Receive Status Pop Register (GRXSTSP) to get Packet
  47420. + * info
  47421. + * -# If Receive FIFO is empty then skip to step Clear the interrupt
  47422. + * and exit
  47423. + * -# If SETUP Packet call dwc_otg_read_setup_packet to copy the
  47424. + * SETUP data to the buffer
  47425. + * -# If OUT Data Packet call dwc_otg_read_packet to copy the data
  47426. + * to the destination buffer
  47427. + */
  47428. +int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t * pcd)
  47429. +{
  47430. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  47431. + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
  47432. + gintmsk_data_t gintmask = {.d32 = 0 };
  47433. + device_grxsts_data_t status;
  47434. + dwc_otg_pcd_ep_t *ep;
  47435. + gintsts_data_t gintsts;
  47436. +#ifdef DEBUG
  47437. + static char *dpid_str[] = { "D0", "D2", "D1", "MDATA" };
  47438. +#endif
  47439. +
  47440. + //DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd);
  47441. + /* Disable the Rx Status Queue Level interrupt */
  47442. + gintmask.b.rxstsqlvl = 1;
  47443. + DWC_MODIFY_REG32(&global_regs->gintmsk, gintmask.d32, 0);
  47444. +
  47445. + /* Get the Status from the top of the FIFO */
  47446. + status.d32 = DWC_READ_REG32(&global_regs->grxstsp);
  47447. +
  47448. + DWC_DEBUGPL(DBG_PCD, "EP:%d BCnt:%d DPID:%s "
  47449. + "pktsts:%x Frame:%d(0x%0x)\n",
  47450. + status.b.epnum, status.b.bcnt,
  47451. + dpid_str[status.b.dpid],
  47452. + status.b.pktsts, status.b.fn, status.b.fn);
  47453. + /* Get pointer to EP structure */
  47454. + ep = get_out_ep(pcd, status.b.epnum);
  47455. +
  47456. + switch (status.b.pktsts) {
  47457. + case DWC_DSTS_GOUT_NAK:
  47458. + DWC_DEBUGPL(DBG_PCDV, "Global OUT NAK\n");
  47459. + break;
  47460. + case DWC_STS_DATA_UPDT:
  47461. + DWC_DEBUGPL(DBG_PCDV, "OUT Data Packet\n");
  47462. + if (status.b.bcnt && ep->dwc_ep.xfer_buff) {
  47463. + /** @todo NGS Check for buffer overflow? */
  47464. + dwc_otg_read_packet(core_if,
  47465. + ep->dwc_ep.xfer_buff,
  47466. + status.b.bcnt);
  47467. + ep->dwc_ep.xfer_count += status.b.bcnt;
  47468. + ep->dwc_ep.xfer_buff += status.b.bcnt;
  47469. + }
  47470. + break;
  47471. + case DWC_STS_XFER_COMP:
  47472. + DWC_DEBUGPL(DBG_PCDV, "OUT Complete\n");
  47473. + break;
  47474. + case DWC_DSTS_SETUP_COMP:
  47475. +#ifdef DEBUG_EP0
  47476. + DWC_DEBUGPL(DBG_PCDV, "Setup Complete\n");
  47477. +#endif
  47478. + break;
  47479. + case DWC_DSTS_SETUP_UPDT:
  47480. + dwc_otg_read_setup_packet(core_if, pcd->setup_pkt->d32);
  47481. +#ifdef DEBUG_EP0
  47482. + DWC_DEBUGPL(DBG_PCD,
  47483. + "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n",
  47484. + pcd->setup_pkt->req.bmRequestType,
  47485. + pcd->setup_pkt->req.bRequest,
  47486. + UGETW(pcd->setup_pkt->req.wValue),
  47487. + UGETW(pcd->setup_pkt->req.wIndex),
  47488. + UGETW(pcd->setup_pkt->req.wLength));
  47489. +#endif
  47490. + ep->dwc_ep.xfer_count += status.b.bcnt;
  47491. + break;
  47492. + default:
  47493. + DWC_DEBUGPL(DBG_PCDV, "Invalid Packet Status (0x%0x)\n",
  47494. + status.b.pktsts);
  47495. + break;
  47496. + }
  47497. +
  47498. + /* Enable the Rx Status Queue Level interrupt */
  47499. + DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmask.d32);
  47500. + /* Clear interrupt */
  47501. + gintsts.d32 = 0;
  47502. + gintsts.b.rxstsqlvl = 1;
  47503. + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
  47504. +
  47505. + //DWC_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__);
  47506. + return 1;
  47507. +}
  47508. +
  47509. +/**
  47510. + * This function examines the Device IN Token Learning Queue to
  47511. + * determine the EP number of the last IN token received. This
  47512. + * implementation is for the Mass Storage device where there are only
  47513. + * 2 IN EPs (Control-IN and BULK-IN).
  47514. + *
  47515. + * The EP numbers for the first six IN Tokens are in DTKNQR1 and there
  47516. + * are 8 EP Numbers in each of the other possible DTKNQ Registers.
  47517. + *
  47518. + * @param core_if Programming view of DWC_otg controller.
  47519. + *
  47520. + */
  47521. +static inline int get_ep_of_last_in_token(dwc_otg_core_if_t * core_if)
  47522. +{
  47523. + dwc_otg_device_global_regs_t *dev_global_regs =
  47524. + core_if->dev_if->dev_global_regs;
  47525. + const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth;
  47526. + /* Number of Token Queue Registers */
  47527. + const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;
  47528. + dtknq1_data_t dtknqr1;
  47529. + uint32_t in_tkn_epnums[4];
  47530. + int ndx = 0;
  47531. + int i = 0;
  47532. + volatile uint32_t *addr = &dev_global_regs->dtknqr1;
  47533. + int epnum = 0;
  47534. +
  47535. + //DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);
  47536. +
  47537. + /* Read the DTKNQ Registers */
  47538. + for (i = 0; i < DTKNQ_REG_CNT; i++) {
  47539. + in_tkn_epnums[i] = DWC_READ_REG32(addr);
  47540. + DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1,
  47541. + in_tkn_epnums[i]);
  47542. + if (addr == &dev_global_regs->dvbusdis) {
  47543. + addr = &dev_global_regs->dtknqr3_dthrctl;
  47544. + } else {
  47545. + ++addr;
  47546. + }
  47547. +
  47548. + }
  47549. +
  47550. + /* Copy the DTKNQR1 data to the bit field. */
  47551. + dtknqr1.d32 = in_tkn_epnums[0];
  47552. + /* Get the EP numbers */
  47553. + in_tkn_epnums[0] = dtknqr1.b.epnums0_5;
  47554. + ndx = dtknqr1.b.intknwptr - 1;
  47555. +
  47556. + //DWC_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx);
  47557. + if (ndx == -1) {
  47558. + /** @todo Find a simpler way to calculate the max
  47559. + * queue position.*/
  47560. + int cnt = TOKEN_Q_DEPTH;
  47561. + if (TOKEN_Q_DEPTH <= 6) {
  47562. + cnt = TOKEN_Q_DEPTH - 1;
  47563. + } else if (TOKEN_Q_DEPTH <= 14) {
  47564. + cnt = TOKEN_Q_DEPTH - 7;
  47565. + } else if (TOKEN_Q_DEPTH <= 22) {
  47566. + cnt = TOKEN_Q_DEPTH - 15;
  47567. + } else {
  47568. + cnt = TOKEN_Q_DEPTH - 23;
  47569. + }
  47570. + epnum = (in_tkn_epnums[DTKNQ_REG_CNT - 1] >> (cnt * 4)) & 0xF;
  47571. + } else {
  47572. + if (ndx <= 5) {
  47573. + epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF;
  47574. + } else if (ndx <= 13) {
  47575. + ndx -= 6;
  47576. + epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF;
  47577. + } else if (ndx <= 21) {
  47578. + ndx -= 14;
  47579. + epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF;
  47580. + } else if (ndx <= 29) {
  47581. + ndx -= 22;
  47582. + epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF;
  47583. + }
  47584. + }
  47585. + //DWC_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum);
  47586. + return epnum;
  47587. +}
  47588. +
  47589. +/**
  47590. + * This interrupt occurs when the non-periodic Tx FIFO is half-empty.
  47591. + * The active request is checked for the next packet to be loaded into
  47592. + * the non-periodic Tx FIFO.
  47593. + */
  47594. +int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t * pcd)
  47595. +{
  47596. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  47597. + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
  47598. + dwc_otg_dev_in_ep_regs_t *ep_regs;
  47599. + gnptxsts_data_t txstatus = {.d32 = 0 };
  47600. + gintsts_data_t gintsts;
  47601. +
  47602. + int epnum = 0;
  47603. + dwc_otg_pcd_ep_t *ep = 0;
  47604. + uint32_t len = 0;
  47605. + int dwords;
  47606. +
  47607. + /* Get the epnum from the IN Token Learning Queue. */
  47608. + epnum = get_ep_of_last_in_token(core_if);
  47609. + ep = get_in_ep(pcd, epnum);
  47610. +
  47611. + DWC_DEBUGPL(DBG_PCD, "NP TxFifo Empty: %d \n", epnum);
  47612. +
  47613. + ep_regs = core_if->dev_if->in_ep_regs[epnum];
  47614. +
  47615. + len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
  47616. + if (len > ep->dwc_ep.maxpacket) {
  47617. + len = ep->dwc_ep.maxpacket;
  47618. + }
  47619. + dwords = (len + 3) / 4;
  47620. +
  47621. + /* While there is space in the queue and space in the FIFO and
  47622. + * More data to tranfer, Write packets to the Tx FIFO */
  47623. + txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
  47624. + DWC_DEBUGPL(DBG_PCDV, "b4 GNPTXSTS=0x%08x\n", txstatus.d32);
  47625. +
  47626. + while (txstatus.b.nptxqspcavail > 0 &&
  47627. + txstatus.b.nptxfspcavail > dwords &&
  47628. + ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len) {
  47629. + /* Write the FIFO */
  47630. + dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
  47631. + len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
  47632. +
  47633. + if (len > ep->dwc_ep.maxpacket) {
  47634. + len = ep->dwc_ep.maxpacket;
  47635. + }
  47636. +
  47637. + dwords = (len + 3) / 4;
  47638. + txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts);
  47639. + DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", txstatus.d32);
  47640. + }
  47641. +
  47642. + DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n",
  47643. + DWC_READ_REG32(&global_regs->gnptxsts));
  47644. +
  47645. + /* Clear interrupt */
  47646. + gintsts.d32 = 0;
  47647. + gintsts.b.nptxfempty = 1;
  47648. + DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32);
  47649. +
  47650. + return 1;
  47651. +}
  47652. +
  47653. +/**
  47654. + * This function is called when dedicated Tx FIFO Empty interrupt occurs.
  47655. + * The active request is checked for the next packet to be loaded into
  47656. + * apropriate Tx FIFO.
  47657. + */
  47658. +static int32_t write_empty_tx_fifo(dwc_otg_pcd_t * pcd, uint32_t epnum)
  47659. +{
  47660. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  47661. + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
  47662. + dwc_otg_dev_in_ep_regs_t *ep_regs;
  47663. + dtxfsts_data_t txstatus = {.d32 = 0 };
  47664. + dwc_otg_pcd_ep_t *ep = 0;
  47665. + uint32_t len = 0;
  47666. + int dwords;
  47667. +
  47668. + ep = get_in_ep(pcd, epnum);
  47669. +
  47670. + DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum);
  47671. +
  47672. + ep_regs = core_if->dev_if->in_ep_regs[epnum];
  47673. +
  47674. + len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
  47675. +
  47676. + if (len > ep->dwc_ep.maxpacket) {
  47677. + len = ep->dwc_ep.maxpacket;
  47678. + }
  47679. +
  47680. + dwords = (len + 3) / 4;
  47681. +
  47682. + /* While there is space in the queue and space in the FIFO and
  47683. + * More data to tranfer, Write packets to the Tx FIFO */
  47684. + txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
  47685. + DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32);
  47686. +
  47687. + while (txstatus.b.txfspcavail > dwords &&
  47688. + ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len &&
  47689. + ep->dwc_ep.xfer_len != 0) {
  47690. + /* Write the FIFO */
  47691. + dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0);
  47692. +
  47693. + len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count;
  47694. + if (len > ep->dwc_ep.maxpacket) {
  47695. + len = ep->dwc_ep.maxpacket;
  47696. + }
  47697. +
  47698. + dwords = (len + 3) / 4;
  47699. + txstatus.d32 =
  47700. + DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts);
  47701. + DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum,
  47702. + txstatus.d32);
  47703. + }
  47704. +
  47705. + DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum,
  47706. + DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts));
  47707. +
  47708. + return 1;
  47709. +}
  47710. +
  47711. +/**
  47712. + * This function is called when the Device is disconnected. It stops
  47713. + * any active requests and informs the Gadget driver of the
  47714. + * disconnect.
  47715. + */
  47716. +void dwc_otg_pcd_stop(dwc_otg_pcd_t * pcd)
  47717. +{
  47718. + int i, num_in_eps, num_out_eps;
  47719. + dwc_otg_pcd_ep_t *ep;
  47720. +
  47721. + gintmsk_data_t intr_mask = {.d32 = 0 };
  47722. +
  47723. + DWC_SPINLOCK(pcd->lock);
  47724. +
  47725. + num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps;
  47726. + num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps;
  47727. +
  47728. + DWC_DEBUGPL(DBG_PCDV, "%s() \n", __func__);
  47729. + /* don't disconnect drivers more than once */
  47730. + if (pcd->ep0state == EP0_DISCONNECT) {
  47731. + DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__);
  47732. + DWC_SPINUNLOCK(pcd->lock);
  47733. + return;
  47734. + }
  47735. + pcd->ep0state = EP0_DISCONNECT;
  47736. +
  47737. + /* Reset the OTG state. */
  47738. + dwc_otg_pcd_update_otg(pcd, 1);
  47739. +
  47740. + /* Disable the NP Tx Fifo Empty Interrupt. */
  47741. + intr_mask.b.nptxfempty = 1;
  47742. + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
  47743. + intr_mask.d32, 0);
  47744. +
  47745. + /* Flush the FIFOs */
  47746. + /**@todo NGS Flush Periodic FIFOs */
  47747. + dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), 0x10);
  47748. + dwc_otg_flush_rx_fifo(GET_CORE_IF(pcd));
  47749. +
  47750. + /* prevent new request submissions, kill any outstanding requests */
  47751. + ep = &pcd->ep0;
  47752. + dwc_otg_request_nuke(ep);
  47753. + /* prevent new request submissions, kill any outstanding requests */
  47754. + for (i = 0; i < num_in_eps; i++) {
  47755. + dwc_otg_pcd_ep_t *ep = &pcd->in_ep[i];
  47756. + dwc_otg_request_nuke(ep);
  47757. + }
  47758. + /* prevent new request submissions, kill any outstanding requests */
  47759. + for (i = 0; i < num_out_eps; i++) {
  47760. + dwc_otg_pcd_ep_t *ep = &pcd->out_ep[i];
  47761. + dwc_otg_request_nuke(ep);
  47762. + }
  47763. +
  47764. + /* report disconnect; the driver is already quiesced */
  47765. + if (pcd->fops->disconnect) {
  47766. + DWC_SPINUNLOCK(pcd->lock);
  47767. + pcd->fops->disconnect(pcd);
  47768. + DWC_SPINLOCK(pcd->lock);
  47769. + }
  47770. + DWC_SPINUNLOCK(pcd->lock);
  47771. +}
  47772. +
  47773. +/**
  47774. + * This interrupt indicates that ...
  47775. + */
  47776. +int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t * pcd)
  47777. +{
  47778. + gintmsk_data_t intr_mask = {.d32 = 0 };
  47779. + gintsts_data_t gintsts;
  47780. +
  47781. + DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "i2cintr");
  47782. + intr_mask.b.i2cintr = 1;
  47783. + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
  47784. + intr_mask.d32, 0);
  47785. +
  47786. + /* Clear interrupt */
  47787. + gintsts.d32 = 0;
  47788. + gintsts.b.i2cintr = 1;
  47789. + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
  47790. + gintsts.d32);
  47791. + return 1;
  47792. +}
  47793. +
  47794. +/**
  47795. + * This interrupt indicates that ...
  47796. + */
  47797. +int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t * pcd)
  47798. +{
  47799. + gintsts_data_t gintsts;
  47800. +#if defined(VERBOSE)
  47801. + DWC_PRINTF("Early Suspend Detected\n");
  47802. +#endif
  47803. +
  47804. + /* Clear interrupt */
  47805. + gintsts.d32 = 0;
  47806. + gintsts.b.erlysuspend = 1;
  47807. + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
  47808. + gintsts.d32);
  47809. + return 1;
  47810. +}
  47811. +
  47812. +/**
  47813. + * This function configures EPO to receive SETUP packets.
  47814. + *
  47815. + * @todo NGS: Update the comments from the HW FS.
  47816. + *
  47817. + * -# Program the following fields in the endpoint specific registers
  47818. + * for Control OUT EP 0, in order to receive a setup packet
  47819. + * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
  47820. + * setup packets)
  47821. + * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
  47822. + * to back setup packets)
  47823. + * - In DMA mode, DOEPDMA0 Register with a memory address to
  47824. + * store any setup packets received
  47825. + *
  47826. + * @param core_if Programming view of DWC_otg controller.
  47827. + * @param pcd Programming view of the PCD.
  47828. + */
  47829. +static inline void ep0_out_start(dwc_otg_core_if_t * core_if,
  47830. + dwc_otg_pcd_t * pcd)
  47831. +{
  47832. + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
  47833. + deptsiz0_data_t doeptsize0 = {.d32 = 0 };
  47834. + dwc_otg_dev_dma_desc_t *dma_desc;
  47835. + depctl_data_t doepctl = {.d32 = 0 };
  47836. +
  47837. +#ifdef VERBOSE
  47838. + DWC_DEBUGPL(DBG_PCDV, "%s() doepctl0=%0x\n", __func__,
  47839. + DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
  47840. +#endif
  47841. + if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
  47842. + doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl);
  47843. + if (doepctl.b.epena) {
  47844. + return;
  47845. + }
  47846. + }
  47847. +
  47848. + doeptsize0.b.supcnt = 3;
  47849. + doeptsize0.b.pktcnt = 1;
  47850. + doeptsize0.b.xfersize = 8 * 3;
  47851. +
  47852. + if (core_if->dma_enable) {
  47853. + if (!core_if->dma_desc_enable) {
  47854. + /** put here as for Hermes mode deptisz register should not be written */
  47855. + DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz,
  47856. + doeptsize0.d32);
  47857. +
  47858. + /** @todo dma needs to handle multiple setup packets (up to 3) */
  47859. + DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma,
  47860. + pcd->setup_pkt_dma_handle);
  47861. + } else {
  47862. + dev_if->setup_desc_index =
  47863. + (dev_if->setup_desc_index + 1) & 1;
  47864. + dma_desc =
  47865. + dev_if->setup_desc_addr[dev_if->setup_desc_index];
  47866. +
  47867. + /** DMA Descriptor Setup */
  47868. + dma_desc->status.b.bs = BS_HOST_BUSY;
  47869. + if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
  47870. + dma_desc->status.b.sr = 0;
  47871. + dma_desc->status.b.mtrf = 0;
  47872. + }
  47873. + dma_desc->status.b.l = 1;
  47874. + dma_desc->status.b.ioc = 1;
  47875. + dma_desc->status.b.bytes = pcd->ep0.dwc_ep.maxpacket;
  47876. + dma_desc->buf = pcd->setup_pkt_dma_handle;
  47877. + dma_desc->status.b.sts = 0;
  47878. + dma_desc->status.b.bs = BS_HOST_READY;
  47879. +
  47880. + /** DOEPDMA0 Register write */
  47881. + DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma,
  47882. + dev_if->dma_setup_desc_addr
  47883. + [dev_if->setup_desc_index]);
  47884. + }
  47885. +
  47886. + } else {
  47887. + /** put here as for Hermes mode deptisz register should not be written */
  47888. + DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz,
  47889. + doeptsize0.d32);
  47890. + }
  47891. +
  47892. + /** DOEPCTL0 Register write cnak will be set after setup interrupt */
  47893. + doepctl.d32 = 0;
  47894. + doepctl.b.epena = 1;
  47895. + if (core_if->snpsid <= OTG_CORE_REV_2_94a) {
  47896. + doepctl.b.cnak = 1;
  47897. + DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32);
  47898. + } else {
  47899. + DWC_MODIFY_REG32(&dev_if->out_ep_regs[0]->doepctl, 0, doepctl.d32);
  47900. + }
  47901. +
  47902. +#ifdef VERBOSE
  47903. + DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n",
  47904. + DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl));
  47905. + DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n",
  47906. + DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl));
  47907. +#endif
  47908. +}
  47909. +
  47910. +/**
  47911. + * This interrupt occurs when a USB Reset is detected. When the USB
  47912. + * Reset Interrupt occurs the device state is set to DEFAULT and the
  47913. + * EP0 state is set to IDLE.
  47914. + * -# Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1)
  47915. + * -# Unmask the following interrupt bits
  47916. + * - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint)
  47917. + * - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint)
  47918. + * - DOEPMSK.SETUP = 1
  47919. + * - DOEPMSK.XferCompl = 1
  47920. + * - DIEPMSK.XferCompl = 1
  47921. + * - DIEPMSK.TimeOut = 1
  47922. + * -# Program the following fields in the endpoint specific registers
  47923. + * for Control OUT EP 0, in order to receive a setup packet
  47924. + * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back
  47925. + * setup packets)
  47926. + * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back
  47927. + * to back setup packets)
  47928. + * - In DMA mode, DOEPDMA0 Register with a memory address to
  47929. + * store any setup packets received
  47930. + * At this point, all the required initialization, except for enabling
  47931. + * the control 0 OUT endpoint is done, for receiving SETUP packets.
  47932. + */
  47933. +int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd)
  47934. +{
  47935. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  47936. + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
  47937. + depctl_data_t doepctl = {.d32 = 0 };
  47938. + depctl_data_t diepctl = {.d32 = 0 };
  47939. + daint_data_t daintmsk = {.d32 = 0 };
  47940. + doepmsk_data_t doepmsk = {.d32 = 0 };
  47941. + diepmsk_data_t diepmsk = {.d32 = 0 };
  47942. + dcfg_data_t dcfg = {.d32 = 0 };
  47943. + grstctl_t resetctl = {.d32 = 0 };
  47944. + dctl_data_t dctl = {.d32 = 0 };
  47945. + int i = 0;
  47946. + gintsts_data_t gintsts;
  47947. + pcgcctl_data_t power = {.d32 = 0 };
  47948. +
  47949. + power.d32 = DWC_READ_REG32(core_if->pcgcctl);
  47950. + if (power.b.stoppclk) {
  47951. + power.d32 = 0;
  47952. + power.b.stoppclk = 1;
  47953. + DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
  47954. +
  47955. + power.b.pwrclmp = 1;
  47956. + DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
  47957. +
  47958. + power.b.rstpdwnmodule = 1;
  47959. + DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0);
  47960. + }
  47961. +
  47962. + core_if->lx_state = DWC_OTG_L0;
  47963. +
  47964. + DWC_PRINTF("USB RESET\n");
  47965. +#ifdef DWC_EN_ISOC
  47966. + for (i = 1; i < 16; ++i) {
  47967. + dwc_otg_pcd_ep_t *ep;
  47968. + dwc_ep_t *dwc_ep;
  47969. + ep = get_in_ep(pcd, i);
  47970. + if (ep != 0) {
  47971. + dwc_ep = &ep->dwc_ep;
  47972. + dwc_ep->next_frame = 0xffffffff;
  47973. + }
  47974. + }
  47975. +#endif /* DWC_EN_ISOC */
  47976. +
  47977. + /* reset the HNP settings */
  47978. + dwc_otg_pcd_update_otg(pcd, 1);
  47979. +
  47980. + /* Clear the Remote Wakeup Signalling */
  47981. + dctl.b.rmtwkupsig = 1;
  47982. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0);
  47983. +
  47984. + /* Set NAK for all OUT EPs */
  47985. + doepctl.b.snak = 1;
  47986. + for (i = 0; i <= dev_if->num_out_eps; i++) {
  47987. + DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
  47988. + }
  47989. +
  47990. + /* Flush the NP Tx FIFO */
  47991. + dwc_otg_flush_tx_fifo(core_if, 0x10);
  47992. + /* Flush the Learning Queue */
  47993. + resetctl.b.intknqflsh = 1;
  47994. + DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
  47995. +
  47996. + if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) {
  47997. + core_if->start_predict = 0;
  47998. + for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) {
  47999. + core_if->nextep_seq[i] = 0xff; // 0xff - EP not active
  48000. + }
  48001. + core_if->nextep_seq[0] = 0;
  48002. + core_if->first_in_nextep_seq = 0;
  48003. + diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl);
  48004. + diepctl.b.nextep = 0;
  48005. + DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32);
  48006. +
  48007. + /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */
  48008. + dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
  48009. + dcfg.b.epmscnt = 2;
  48010. + DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
  48011. +
  48012. + DWC_DEBUGPL(DBG_PCDV,
  48013. + "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
  48014. + __func__, core_if->first_in_nextep_seq);
  48015. + for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
  48016. + DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]);
  48017. + }
  48018. + }
  48019. +
  48020. + if (core_if->multiproc_int_enable) {
  48021. + daintmsk.b.inep0 = 1;
  48022. + daintmsk.b.outep0 = 1;
  48023. + DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk,
  48024. + daintmsk.d32);
  48025. +
  48026. + doepmsk.b.setup = 1;
  48027. + doepmsk.b.xfercompl = 1;
  48028. + doepmsk.b.ahberr = 1;
  48029. + doepmsk.b.epdisabled = 1;
  48030. +
  48031. + if ((core_if->dma_desc_enable) ||
  48032. + (core_if->dma_enable
  48033. + && core_if->snpsid >= OTG_CORE_REV_3_00a)) {
  48034. + doepmsk.b.stsphsercvd = 1;
  48035. + }
  48036. + if (core_if->dma_desc_enable)
  48037. + doepmsk.b.bna = 1;
  48038. +/*
  48039. + doepmsk.b.babble = 1;
  48040. + doepmsk.b.nyet = 1;
  48041. +
  48042. + if (core_if->dma_enable) {
  48043. + doepmsk.b.nak = 1;
  48044. + }
  48045. +*/
  48046. + DWC_WRITE_REG32(&dev_if->dev_global_regs->doepeachintmsk[0],
  48047. + doepmsk.d32);
  48048. +
  48049. + diepmsk.b.xfercompl = 1;
  48050. + diepmsk.b.timeout = 1;
  48051. + diepmsk.b.epdisabled = 1;
  48052. + diepmsk.b.ahberr = 1;
  48053. + diepmsk.b.intknepmis = 1;
  48054. + if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
  48055. + diepmsk.b.intknepmis = 0;
  48056. +
  48057. +/* if (core_if->dma_desc_enable) {
  48058. + diepmsk.b.bna = 1;
  48059. + }
  48060. +*/
  48061. +/*
  48062. + if (core_if->dma_enable) {
  48063. + diepmsk.b.nak = 1;
  48064. + }
  48065. +*/
  48066. + DWC_WRITE_REG32(&dev_if->dev_global_regs->diepeachintmsk[0],
  48067. + diepmsk.d32);
  48068. + } else {
  48069. + daintmsk.b.inep0 = 1;
  48070. + daintmsk.b.outep0 = 1;
  48071. + DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk,
  48072. + daintmsk.d32);
  48073. +
  48074. + doepmsk.b.setup = 1;
  48075. + doepmsk.b.xfercompl = 1;
  48076. + doepmsk.b.ahberr = 1;
  48077. + doepmsk.b.epdisabled = 1;
  48078. +
  48079. + if ((core_if->dma_desc_enable) ||
  48080. + (core_if->dma_enable
  48081. + && core_if->snpsid >= OTG_CORE_REV_3_00a)) {
  48082. + doepmsk.b.stsphsercvd = 1;
  48083. + }
  48084. + if (core_if->dma_desc_enable)
  48085. + doepmsk.b.bna = 1;
  48086. + DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32);
  48087. +
  48088. + diepmsk.b.xfercompl = 1;
  48089. + diepmsk.b.timeout = 1;
  48090. + diepmsk.b.epdisabled = 1;
  48091. + diepmsk.b.ahberr = 1;
  48092. + if (!core_if->en_multiple_tx_fifo && core_if->dma_enable)
  48093. + diepmsk.b.intknepmis = 0;
  48094. +/*
  48095. + if (core_if->dma_desc_enable) {
  48096. + diepmsk.b.bna = 1;
  48097. + }
  48098. +*/
  48099. +
  48100. + DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32);
  48101. + }
  48102. +
  48103. + /* Reset Device Address */
  48104. + dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
  48105. + dcfg.b.devaddr = 0;
  48106. + DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
  48107. +
  48108. + /* setup EP0 to receive SETUP packets */
  48109. + if (core_if->snpsid <= OTG_CORE_REV_2_94a)
  48110. + ep0_out_start(core_if, pcd);
  48111. +
  48112. + /* Clear interrupt */
  48113. + gintsts.d32 = 0;
  48114. + gintsts.b.usbreset = 1;
  48115. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
  48116. +
  48117. + return 1;
  48118. +}
  48119. +
  48120. +/**
  48121. + * Get the device speed from the device status register and convert it
  48122. + * to USB speed constant.
  48123. + *
  48124. + * @param core_if Programming view of DWC_otg controller.
  48125. + */
  48126. +static int get_device_speed(dwc_otg_core_if_t * core_if)
  48127. +{
  48128. + dsts_data_t dsts;
  48129. + int speed = 0;
  48130. + dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts);
  48131. +
  48132. + switch (dsts.b.enumspd) {
  48133. + case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
  48134. + speed = USB_SPEED_HIGH;
  48135. + break;
  48136. + case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
  48137. + case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ:
  48138. + speed = USB_SPEED_FULL;
  48139. + break;
  48140. +
  48141. + case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ:
  48142. + speed = USB_SPEED_LOW;
  48143. + break;
  48144. + }
  48145. +
  48146. + return speed;
  48147. +}
  48148. +
  48149. +/**
  48150. + * Read the device status register and set the device speed in the
  48151. + * data structure.
  48152. + * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate.
  48153. + */
  48154. +int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd)
  48155. +{
  48156. + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
  48157. + gintsts_data_t gintsts;
  48158. + gusbcfg_data_t gusbcfg;
  48159. + dwc_otg_core_global_regs_t *global_regs =
  48160. + GET_CORE_IF(pcd)->core_global_regs;
  48161. + uint8_t utmi16b, utmi8b;
  48162. + int speed;
  48163. + DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n");
  48164. +
  48165. + if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) {
  48166. + utmi16b = 6; //vahrama old value was 6;
  48167. + utmi8b = 9;
  48168. + } else {
  48169. + utmi16b = 4;
  48170. + utmi8b = 8;
  48171. + }
  48172. + dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep);
  48173. + if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) {
  48174. + ep0_out_start(GET_CORE_IF(pcd), pcd);
  48175. + }
  48176. +
  48177. +#ifdef DEBUG_EP0
  48178. + print_ep0_state(pcd);
  48179. +#endif
  48180. +
  48181. + if (pcd->ep0state == EP0_DISCONNECT) {
  48182. + pcd->ep0state = EP0_IDLE;
  48183. + } else if (pcd->ep0state == EP0_STALL) {
  48184. + pcd->ep0state = EP0_IDLE;
  48185. + }
  48186. +
  48187. + pcd->ep0state = EP0_IDLE;
  48188. +
  48189. + ep0->stopped = 0;
  48190. +
  48191. + speed = get_device_speed(GET_CORE_IF(pcd));
  48192. + pcd->fops->connect(pcd, speed);
  48193. +
  48194. + /* Set USB turnaround time based on device speed and PHY interface. */
  48195. + gusbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
  48196. + if (speed == USB_SPEED_HIGH) {
  48197. + if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
  48198. + DWC_HWCFG2_HS_PHY_TYPE_ULPI) {
  48199. + /* ULPI interface */
  48200. + gusbcfg.b.usbtrdtim = 9;
  48201. + }
  48202. + if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
  48203. + DWC_HWCFG2_HS_PHY_TYPE_UTMI) {
  48204. + /* UTMI+ interface */
  48205. + if (GET_CORE_IF(pcd)->hwcfg4.b.utmi_phy_data_width == 0) {
  48206. + gusbcfg.b.usbtrdtim = utmi8b;
  48207. + } else if (GET_CORE_IF(pcd)->hwcfg4.
  48208. + b.utmi_phy_data_width == 1) {
  48209. + gusbcfg.b.usbtrdtim = utmi16b;
  48210. + } else if (GET_CORE_IF(pcd)->
  48211. + core_params->phy_utmi_width == 8) {
  48212. + gusbcfg.b.usbtrdtim = utmi8b;
  48213. + } else {
  48214. + gusbcfg.b.usbtrdtim = utmi16b;
  48215. + }
  48216. + }
  48217. + if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type ==
  48218. + DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) {
  48219. + /* UTMI+ OR ULPI interface */
  48220. + if (gusbcfg.b.ulpi_utmi_sel == 1) {
  48221. + /* ULPI interface */
  48222. + gusbcfg.b.usbtrdtim = 9;
  48223. + } else {
  48224. + /* UTMI+ interface */
  48225. + if (GET_CORE_IF(pcd)->
  48226. + core_params->phy_utmi_width == 16) {
  48227. + gusbcfg.b.usbtrdtim = utmi16b;
  48228. + } else {
  48229. + gusbcfg.b.usbtrdtim = utmi8b;
  48230. + }
  48231. + }
  48232. + }
  48233. + } else {
  48234. + /* Full or low speed */
  48235. + gusbcfg.b.usbtrdtim = 9;
  48236. + }
  48237. + DWC_WRITE_REG32(&global_regs->gusbcfg, gusbcfg.d32);
  48238. +
  48239. + /* Clear interrupt */
  48240. + gintsts.d32 = 0;
  48241. + gintsts.b.enumdone = 1;
  48242. + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
  48243. + gintsts.d32);
  48244. + return 1;
  48245. +}
  48246. +
  48247. +/**
  48248. + * This interrupt indicates that the ISO OUT Packet was dropped due to
  48249. + * Rx FIFO full or Rx Status Queue Full. If this interrupt occurs
  48250. + * read all the data from the Rx FIFO.
  48251. + */
  48252. +int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t * pcd)
  48253. +{
  48254. + gintmsk_data_t intr_mask = {.d32 = 0 };
  48255. + gintsts_data_t gintsts;
  48256. +
  48257. + DWC_WARN("INTERRUPT Handler not implemented for %s\n",
  48258. + "ISOC Out Dropped");
  48259. +
  48260. + intr_mask.b.isooutdrop = 1;
  48261. + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
  48262. + intr_mask.d32, 0);
  48263. +
  48264. + /* Clear interrupt */
  48265. + gintsts.d32 = 0;
  48266. + gintsts.b.isooutdrop = 1;
  48267. + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
  48268. + gintsts.d32);
  48269. +
  48270. + return 1;
  48271. +}
  48272. +
  48273. +/**
  48274. + * This interrupt indicates the end of the portion of the micro-frame
  48275. + * for periodic transactions. If there is a periodic transaction for
  48276. + * the next frame, load the packets into the EP periodic Tx FIFO.
  48277. + */
  48278. +int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t * pcd)
  48279. +{
  48280. + gintmsk_data_t intr_mask = {.d32 = 0 };
  48281. + gintsts_data_t gintsts;
  48282. + DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "EOP");
  48283. +
  48284. + intr_mask.b.eopframe = 1;
  48285. + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
  48286. + intr_mask.d32, 0);
  48287. +
  48288. + /* Clear interrupt */
  48289. + gintsts.d32 = 0;
  48290. + gintsts.b.eopframe = 1;
  48291. + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
  48292. + gintsts.d32);
  48293. +
  48294. + return 1;
  48295. +}
  48296. +
  48297. +/**
  48298. + * This interrupt indicates that EP of the packet on the top of the
  48299. + * non-periodic Tx FIFO does not match EP of the IN Token received.
  48300. + *
  48301. + * The "Device IN Token Queue" Registers are read to determine the
  48302. + * order the IN Tokens have been received. The non-periodic Tx FIFO
  48303. + * is flushed, so it can be reloaded in the order seen in the IN Token
  48304. + * Queue.
  48305. + */
  48306. +int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_pcd_t * pcd)
  48307. +{
  48308. + gintsts_data_t gintsts;
  48309. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  48310. + dctl_data_t dctl;
  48311. + gintmsk_data_t intr_mask = {.d32 = 0 };
  48312. +
  48313. + if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) {
  48314. + core_if->start_predict = 1;
  48315. +
  48316. + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if);
  48317. +
  48318. + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
  48319. + if (!gintsts.b.ginnakeff) {
  48320. + /* Disable EP Mismatch interrupt */
  48321. + intr_mask.d32 = 0;
  48322. + intr_mask.b.epmismatch = 1;
  48323. + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32, 0);
  48324. + /* Enable the Global IN NAK Effective Interrupt */
  48325. + intr_mask.d32 = 0;
  48326. + intr_mask.b.ginnakeff = 1;
  48327. + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32);
  48328. + /* Set the global non-periodic IN NAK handshake */
  48329. + dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
  48330. + dctl.b.sgnpinnak = 1;
  48331. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
  48332. + } else {
  48333. + DWC_PRINTF("gintsts.b.ginnakeff = 1! dctl.b.sgnpinnak not set\n");
  48334. + }
  48335. + /* Disabling of all EP's will be done in dwc_otg_pcd_handle_in_nak_effective()
  48336. + * handler after Global IN NAK Effective interrupt will be asserted */
  48337. + }
  48338. + /* Clear interrupt */
  48339. + gintsts.d32 = 0;
  48340. + gintsts.b.epmismatch = 1;
  48341. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
  48342. +
  48343. + return 1;
  48344. +}
  48345. +
  48346. +/**
  48347. + * This interrupt is valid only in DMA mode. This interrupt indicates that the
  48348. + * core has stopped fetching data for IN endpoints due to the unavailability of
  48349. + * TxFIFO space or Request Queue space. This interrupt is used by the
  48350. + * application for an endpoint mismatch algorithm.
  48351. + *
  48352. + * @param pcd The PCD
  48353. + */
  48354. +int32_t dwc_otg_pcd_handle_ep_fetsusp_intr(dwc_otg_pcd_t * pcd)
  48355. +{
  48356. + gintsts_data_t gintsts;
  48357. + gintmsk_data_t gintmsk_data;
  48358. + dctl_data_t dctl;
  48359. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  48360. + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if);
  48361. +
  48362. + /* Clear the global non-periodic IN NAK handshake */
  48363. + dctl.d32 = 0;
  48364. + dctl.b.cgnpinnak = 1;
  48365. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
  48366. +
  48367. + /* Mask GINTSTS.FETSUSP interrupt */
  48368. + gintmsk_data.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
  48369. + gintmsk_data.b.fetsusp = 0;
  48370. + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk_data.d32);
  48371. +
  48372. + /* Clear interrupt */
  48373. + gintsts.d32 = 0;
  48374. + gintsts.b.fetsusp = 1;
  48375. + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32);
  48376. +
  48377. + return 1;
  48378. +}
  48379. +/**
  48380. + * This funcion stalls EP0.
  48381. + */
  48382. +static inline void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val)
  48383. +{
  48384. + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
  48385. + usb_device_request_t *ctrl = &pcd->setup_pkt->req;
  48386. + DWC_WARN("req %02x.%02x protocol STALL; err %d\n",
  48387. + ctrl->bmRequestType, ctrl->bRequest, err_val);
  48388. +
  48389. + ep0->dwc_ep.is_in = 1;
  48390. + dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->dwc_ep);
  48391. + pcd->ep0.stopped = 1;
  48392. + pcd->ep0state = EP0_IDLE;
  48393. + ep0_out_start(GET_CORE_IF(pcd), pcd);
  48394. +}
  48395. +
  48396. +/**
  48397. + * This functions delegates the setup command to the gadget driver.
  48398. + */
  48399. +static inline void do_gadget_setup(dwc_otg_pcd_t * pcd,
  48400. + usb_device_request_t * ctrl)
  48401. +{
  48402. + int ret = 0;
  48403. + DWC_SPINUNLOCK(pcd->lock);
  48404. + ret = pcd->fops->setup(pcd, (uint8_t *) ctrl);
  48405. + DWC_SPINLOCK(pcd->lock);
  48406. + if (ret < 0) {
  48407. + ep0_do_stall(pcd, ret);
  48408. + }
  48409. +
  48410. + /** @todo This is a g_file_storage gadget driver specific
  48411. + * workaround: a DELAYED_STATUS result from the fsg_setup
  48412. + * routine will result in the gadget queueing a EP0 IN status
  48413. + * phase for a two-stage control transfer. Exactly the same as
  48414. + * a SET_CONFIGURATION/SET_INTERFACE except that this is a class
  48415. + * specific request. Need a generic way to know when the gadget
  48416. + * driver will queue the status phase. Can we assume when we
  48417. + * call the gadget driver setup() function that it will always
  48418. + * queue and require the following flag? Need to look into
  48419. + * this.
  48420. + */
  48421. +
  48422. + if (ret == 256 + 999) {
  48423. + pcd->request_config = 1;
  48424. + }
  48425. +}
  48426. +
  48427. +#ifdef DWC_UTE_CFI
  48428. +/**
  48429. + * This functions delegates the CFI setup commands to the gadget driver.
  48430. + * This function will return a negative value to indicate a failure.
  48431. + */
  48432. +static inline int cfi_gadget_setup(dwc_otg_pcd_t * pcd,
  48433. + struct cfi_usb_ctrlrequest *ctrl_req)
  48434. +{
  48435. + int ret = 0;
  48436. +
  48437. + if (pcd->fops && pcd->fops->cfi_setup) {
  48438. + DWC_SPINUNLOCK(pcd->lock);
  48439. + ret = pcd->fops->cfi_setup(pcd, ctrl_req);
  48440. + DWC_SPINLOCK(pcd->lock);
  48441. + if (ret < 0) {
  48442. + ep0_do_stall(pcd, ret);
  48443. + return ret;
  48444. + }
  48445. + }
  48446. +
  48447. + return ret;
  48448. +}
  48449. +#endif
  48450. +
  48451. +/**
  48452. + * This function starts the Zero-Length Packet for the IN status phase
  48453. + * of a 2 stage control transfer.
  48454. + */
  48455. +static inline void do_setup_in_status_phase(dwc_otg_pcd_t * pcd)
  48456. +{
  48457. + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
  48458. + if (pcd->ep0state == EP0_STALL) {
  48459. + return;
  48460. + }
  48461. +
  48462. + pcd->ep0state = EP0_IN_STATUS_PHASE;
  48463. +
  48464. + /* Prepare for more SETUP Packets */
  48465. + DWC_DEBUGPL(DBG_PCD, "EP0 IN ZLP\n");
  48466. + if ((GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a)
  48467. + && (pcd->core_if->dma_desc_enable)
  48468. + && (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len)) {
  48469. + DWC_DEBUGPL(DBG_PCDV,
  48470. + "Data terminated wait next packet in out_desc_addr\n");
  48471. + pcd->backup_buf = phys_to_virt(ep0->dwc_ep.dma_addr);
  48472. + pcd->data_terminated = 1;
  48473. + }
  48474. + ep0->dwc_ep.xfer_len = 0;
  48475. + ep0->dwc_ep.xfer_count = 0;
  48476. + ep0->dwc_ep.is_in = 1;
  48477. + ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
  48478. + dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
  48479. +
  48480. + /* Prepare for more SETUP Packets */
  48481. + //ep0_out_start(GET_CORE_IF(pcd), pcd);
  48482. +}
  48483. +
  48484. +/**
  48485. + * This function starts the Zero-Length Packet for the OUT status phase
  48486. + * of a 2 stage control transfer.
  48487. + */
  48488. +static inline void do_setup_out_status_phase(dwc_otg_pcd_t * pcd)
  48489. +{
  48490. + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
  48491. + if (pcd->ep0state == EP0_STALL) {
  48492. + DWC_DEBUGPL(DBG_PCD, "EP0 STALLED\n");
  48493. + return;
  48494. + }
  48495. + pcd->ep0state = EP0_OUT_STATUS_PHASE;
  48496. +
  48497. + DWC_DEBUGPL(DBG_PCD, "EP0 OUT ZLP\n");
  48498. + ep0->dwc_ep.xfer_len = 0;
  48499. + ep0->dwc_ep.xfer_count = 0;
  48500. + ep0->dwc_ep.is_in = 0;
  48501. + ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle;
  48502. + dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
  48503. +
  48504. + /* Prepare for more SETUP Packets */
  48505. + if (GET_CORE_IF(pcd)->dma_enable == 0) {
  48506. + ep0_out_start(GET_CORE_IF(pcd), pcd);
  48507. + }
  48508. +}
  48509. +
  48510. +/**
  48511. + * Clear the EP halt (STALL) and if pending requests start the
  48512. + * transfer.
  48513. + */
  48514. +static inline void pcd_clear_halt(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
  48515. +{
  48516. + if (ep->dwc_ep.stall_clear_flag == 0)
  48517. + dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep);
  48518. +
  48519. + /* Reactive the EP */
  48520. + dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep);
  48521. + if (ep->stopped) {
  48522. + ep->stopped = 0;
  48523. + /* If there is a request in the EP queue start it */
  48524. +
  48525. + /** @todo FIXME: this causes an EP mismatch in DMA mode.
  48526. + * epmismatch not yet implemented. */
  48527. +
  48528. + /*
  48529. + * Above fixme is solved by implmenting a tasklet to call the
  48530. + * start_next_request(), outside of interrupt context at some
  48531. + * time after the current time, after a clear-halt setup packet.
  48532. + * Still need to implement ep mismatch in the future if a gadget
  48533. + * ever uses more than one endpoint at once
  48534. + */
  48535. + ep->queue_sof = 1;
  48536. + DWC_TASK_SCHEDULE(pcd->start_xfer_tasklet);
  48537. + }
  48538. + /* Start Control Status Phase */
  48539. + do_setup_in_status_phase(pcd);
  48540. +}
  48541. +
  48542. +/**
  48543. + * This function is called when the SET_FEATURE TEST_MODE Setup packet
  48544. + * is sent from the host. The Device Control register is written with
  48545. + * the Test Mode bits set to the specified Test Mode. This is done as
  48546. + * a tasklet so that the "Status" phase of the control transfer
  48547. + * completes before transmitting the TEST packets.
  48548. + *
  48549. + * @todo This has not been tested since the tasklet struct was put
  48550. + * into the PCD struct!
  48551. + *
  48552. + */
  48553. +void do_test_mode(void *data)
  48554. +{
  48555. + dctl_data_t dctl;
  48556. + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data;
  48557. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  48558. + int test_mode = pcd->test_mode;
  48559. +
  48560. +// DWC_WARN("%s() has not been tested since being rewritten!\n", __func__);
  48561. +
  48562. + dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
  48563. + switch (test_mode) {
  48564. + case 1: // TEST_J
  48565. + dctl.b.tstctl = 1;
  48566. + break;
  48567. +
  48568. + case 2: // TEST_K
  48569. + dctl.b.tstctl = 2;
  48570. + break;
  48571. +
  48572. + case 3: // TEST_SE0_NAK
  48573. + dctl.b.tstctl = 3;
  48574. + break;
  48575. +
  48576. + case 4: // TEST_PACKET
  48577. + dctl.b.tstctl = 4;
  48578. + break;
  48579. +
  48580. + case 5: // TEST_FORCE_ENABLE
  48581. + dctl.b.tstctl = 5;
  48582. + break;
  48583. + }
  48584. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
  48585. +}
  48586. +
  48587. +/**
  48588. + * This function process the GET_STATUS Setup Commands.
  48589. + */
  48590. +static inline void do_get_status(dwc_otg_pcd_t * pcd)
  48591. +{
  48592. + usb_device_request_t ctrl = pcd->setup_pkt->req;
  48593. + dwc_otg_pcd_ep_t *ep;
  48594. + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
  48595. + uint16_t *status = pcd->status_buf;
  48596. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  48597. +
  48598. +#ifdef DEBUG_EP0
  48599. + DWC_DEBUGPL(DBG_PCD,
  48600. + "GET_STATUS %02x.%02x v%04x i%04x l%04x\n",
  48601. + ctrl.bmRequestType, ctrl.bRequest,
  48602. + UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
  48603. + UGETW(ctrl.wLength));
  48604. +#endif
  48605. +
  48606. + switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
  48607. + case UT_DEVICE:
  48608. + if(UGETW(ctrl.wIndex) == 0xF000) { /* OTG Status selector */
  48609. + DWC_PRINTF("wIndex - %d\n", UGETW(ctrl.wIndex));
  48610. + DWC_PRINTF("OTG VERSION - %d\n", core_if->otg_ver);
  48611. + DWC_PRINTF("OTG CAP - %d, %d\n",
  48612. + core_if->core_params->otg_cap,
  48613. + DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
  48614. + if (core_if->otg_ver == 1
  48615. + && core_if->core_params->otg_cap ==
  48616. + DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
  48617. + uint8_t *otgsts = (uint8_t*)pcd->status_buf;
  48618. + *otgsts = (core_if->otg_sts & 0x1);
  48619. + pcd->ep0_pending = 1;
  48620. + ep0->dwc_ep.start_xfer_buff =
  48621. + (uint8_t *) otgsts;
  48622. + ep0->dwc_ep.xfer_buff = (uint8_t *) otgsts;
  48623. + ep0->dwc_ep.dma_addr =
  48624. + pcd->status_buf_dma_handle;
  48625. + ep0->dwc_ep.xfer_len = 1;
  48626. + ep0->dwc_ep.xfer_count = 0;
  48627. + ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
  48628. + dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd),
  48629. + &ep0->dwc_ep);
  48630. + return;
  48631. + } else {
  48632. + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
  48633. + return;
  48634. + }
  48635. + break;
  48636. + } else {
  48637. + *status = 0x1; /* Self powered */
  48638. + *status |= pcd->remote_wakeup_enable << 1;
  48639. + break;
  48640. + }
  48641. + case UT_INTERFACE:
  48642. + *status = 0;
  48643. + break;
  48644. +
  48645. + case UT_ENDPOINT:
  48646. + ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
  48647. + if (ep == 0 || UGETW(ctrl.wLength) > 2) {
  48648. + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
  48649. + return;
  48650. + }
  48651. + /** @todo check for EP stall */
  48652. + *status = ep->stopped;
  48653. + break;
  48654. + }
  48655. + pcd->ep0_pending = 1;
  48656. + ep0->dwc_ep.start_xfer_buff = (uint8_t *) status;
  48657. + ep0->dwc_ep.xfer_buff = (uint8_t *) status;
  48658. + ep0->dwc_ep.dma_addr = pcd->status_buf_dma_handle;
  48659. + ep0->dwc_ep.xfer_len = 2;
  48660. + ep0->dwc_ep.xfer_count = 0;
  48661. + ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len;
  48662. + dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep);
  48663. +}
  48664. +
  48665. +/**
  48666. + * This function process the SET_FEATURE Setup Commands.
  48667. + */
  48668. +static inline void do_set_feature(dwc_otg_pcd_t * pcd)
  48669. +{
  48670. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  48671. + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
  48672. + usb_device_request_t ctrl = pcd->setup_pkt->req;
  48673. + dwc_otg_pcd_ep_t *ep = 0;
  48674. + int32_t otg_cap_param = core_if->core_params->otg_cap;
  48675. + gotgctl_data_t gotgctl = {.d32 = 0 };
  48676. +
  48677. + DWC_DEBUGPL(DBG_PCD, "SET_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
  48678. + ctrl.bmRequestType, ctrl.bRequest,
  48679. + UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
  48680. + UGETW(ctrl.wLength));
  48681. + DWC_DEBUGPL(DBG_PCD, "otg_cap=%d\n", otg_cap_param);
  48682. +
  48683. + switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
  48684. + case UT_DEVICE:
  48685. + switch (UGETW(ctrl.wValue)) {
  48686. + case UF_DEVICE_REMOTE_WAKEUP:
  48687. + pcd->remote_wakeup_enable = 1;
  48688. + break;
  48689. +
  48690. + case UF_TEST_MODE:
  48691. + /* Setup the Test Mode tasklet to do the Test
  48692. + * Packet generation after the SETUP Status
  48693. + * phase has completed. */
  48694. +
  48695. + /** @todo This has not been tested since the
  48696. + * tasklet struct was put into the PCD
  48697. + * struct! */
  48698. + pcd->test_mode = UGETW(ctrl.wIndex) >> 8;
  48699. + DWC_TASK_SCHEDULE(pcd->test_mode_tasklet);
  48700. + break;
  48701. +
  48702. + case UF_DEVICE_B_HNP_ENABLE:
  48703. + DWC_DEBUGPL(DBG_PCDV,
  48704. + "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n");
  48705. +
  48706. + /* dev may initiate HNP */
  48707. + if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
  48708. + pcd->b_hnp_enable = 1;
  48709. + dwc_otg_pcd_update_otg(pcd, 0);
  48710. + DWC_DEBUGPL(DBG_PCD, "Request B HNP\n");
  48711. + /**@todo Is the gotgctl.devhnpen cleared
  48712. + * by a USB Reset? */
  48713. + gotgctl.b.devhnpen = 1;
  48714. + gotgctl.b.hnpreq = 1;
  48715. + DWC_WRITE_REG32(&global_regs->gotgctl,
  48716. + gotgctl.d32);
  48717. + } else {
  48718. + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
  48719. + return;
  48720. + }
  48721. + break;
  48722. +
  48723. + case UF_DEVICE_A_HNP_SUPPORT:
  48724. + /* RH port supports HNP */
  48725. + DWC_DEBUGPL(DBG_PCDV,
  48726. + "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n");
  48727. + if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
  48728. + pcd->a_hnp_support = 1;
  48729. + dwc_otg_pcd_update_otg(pcd, 0);
  48730. + } else {
  48731. + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
  48732. + return;
  48733. + }
  48734. + break;
  48735. +
  48736. + case UF_DEVICE_A_ALT_HNP_SUPPORT:
  48737. + /* other RH port does */
  48738. + DWC_DEBUGPL(DBG_PCDV,
  48739. + "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n");
  48740. + if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) {
  48741. + pcd->a_alt_hnp_support = 1;
  48742. + dwc_otg_pcd_update_otg(pcd, 0);
  48743. + } else {
  48744. + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
  48745. + return;
  48746. + }
  48747. + break;
  48748. +
  48749. + default:
  48750. + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
  48751. + return;
  48752. +
  48753. + }
  48754. + do_setup_in_status_phase(pcd);
  48755. + break;
  48756. +
  48757. + case UT_INTERFACE:
  48758. + do_gadget_setup(pcd, &ctrl);
  48759. + break;
  48760. +
  48761. + case UT_ENDPOINT:
  48762. + if (UGETW(ctrl.wValue) == UF_ENDPOINT_HALT) {
  48763. + ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
  48764. + if (ep == 0) {
  48765. + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
  48766. + return;
  48767. + }
  48768. + ep->stopped = 1;
  48769. + dwc_otg_ep_set_stall(core_if, &ep->dwc_ep);
  48770. + }
  48771. + do_setup_in_status_phase(pcd);
  48772. + break;
  48773. + }
  48774. +}
  48775. +
  48776. +/**
  48777. + * This function process the CLEAR_FEATURE Setup Commands.
  48778. + */
  48779. +static inline void do_clear_feature(dwc_otg_pcd_t * pcd)
  48780. +{
  48781. + usb_device_request_t ctrl = pcd->setup_pkt->req;
  48782. + dwc_otg_pcd_ep_t *ep = 0;
  48783. +
  48784. + DWC_DEBUGPL(DBG_PCD,
  48785. + "CLEAR_FEATURE:%02x.%02x v%04x i%04x l%04x\n",
  48786. + ctrl.bmRequestType, ctrl.bRequest,
  48787. + UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
  48788. + UGETW(ctrl.wLength));
  48789. +
  48790. + switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) {
  48791. + case UT_DEVICE:
  48792. + switch (UGETW(ctrl.wValue)) {
  48793. + case UF_DEVICE_REMOTE_WAKEUP:
  48794. + pcd->remote_wakeup_enable = 0;
  48795. + break;
  48796. +
  48797. + case UF_TEST_MODE:
  48798. + /** @todo Add CLEAR_FEATURE for TEST modes. */
  48799. + break;
  48800. +
  48801. + default:
  48802. + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
  48803. + return;
  48804. + }
  48805. + do_setup_in_status_phase(pcd);
  48806. + break;
  48807. +
  48808. + case UT_ENDPOINT:
  48809. + ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex));
  48810. + if (ep == 0) {
  48811. + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED);
  48812. + return;
  48813. + }
  48814. +
  48815. + pcd_clear_halt(pcd, ep);
  48816. +
  48817. + break;
  48818. + }
  48819. +}
  48820. +
  48821. +/**
  48822. + * This function process the SET_ADDRESS Setup Commands.
  48823. + */
  48824. +static inline void do_set_address(dwc_otg_pcd_t * pcd)
  48825. +{
  48826. + dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
  48827. + usb_device_request_t ctrl = pcd->setup_pkt->req;
  48828. +
  48829. + if (ctrl.bmRequestType == UT_DEVICE) {
  48830. + dcfg_data_t dcfg = {.d32 = 0 };
  48831. +
  48832. +#ifdef DEBUG_EP0
  48833. +// DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue);
  48834. +#endif
  48835. + dcfg.b.devaddr = UGETW(ctrl.wValue);
  48836. + DWC_MODIFY_REG32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32);
  48837. + do_setup_in_status_phase(pcd);
  48838. + }
  48839. +}
  48840. +
  48841. +/**
  48842. + * This function processes SETUP commands. In Linux, the USB Command
  48843. + * processing is done in two places - the first being the PCD and the
  48844. + * second in the Gadget Driver (for example, the File-Backed Storage
  48845. + * Gadget Driver).
  48846. + *
  48847. + * <table>
  48848. + * <tr><td>Command </td><td>Driver </td><td>Description</td></tr>
  48849. + *
  48850. + * <tr><td>GET_STATUS </td><td>PCD </td><td>Command is processed as
  48851. + * defined in chapter 9 of the USB 2.0 Specification chapter 9
  48852. + * </td></tr>
  48853. + *
  48854. + * <tr><td>CLEAR_FEATURE </td><td>PCD </td><td>The Device and Endpoint
  48855. + * requests are the ENDPOINT_HALT feature is procesed, all others the
  48856. + * interface requests are ignored.</td></tr>
  48857. + *
  48858. + * <tr><td>SET_FEATURE </td><td>PCD </td><td>The Device and Endpoint
  48859. + * requests are processed by the PCD. Interface requests are passed
  48860. + * to the Gadget Driver.</td></tr>
  48861. + *
  48862. + * <tr><td>SET_ADDRESS </td><td>PCD </td><td>Program the DCFG reg,
  48863. + * with device address received </td></tr>
  48864. + *
  48865. + * <tr><td>GET_DESCRIPTOR </td><td>Gadget Driver </td><td>Return the
  48866. + * requested descriptor</td></tr>
  48867. + *
  48868. + * <tr><td>SET_DESCRIPTOR </td><td>Gadget Driver </td><td>Optional -
  48869. + * not implemented by any of the existing Gadget Drivers.</td></tr>
  48870. + *
  48871. + * <tr><td>SET_CONFIGURATION </td><td>Gadget Driver </td><td>Disable
  48872. + * all EPs and enable EPs for new configuration.</td></tr>
  48873. + *
  48874. + * <tr><td>GET_CONFIGURATION </td><td>Gadget Driver </td><td>Return
  48875. + * the current configuration</td></tr>
  48876. + *
  48877. + * <tr><td>SET_INTERFACE </td><td>Gadget Driver </td><td>Disable all
  48878. + * EPs and enable EPs for new configuration.</td></tr>
  48879. + *
  48880. + * <tr><td>GET_INTERFACE </td><td>Gadget Driver </td><td>Return the
  48881. + * current interface.</td></tr>
  48882. + *
  48883. + * <tr><td>SYNC_FRAME </td><td>PCD </td><td>Display debug
  48884. + * message.</td></tr>
  48885. + * </table>
  48886. + *
  48887. + * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are
  48888. + * processed by pcd_setup. Calling the Function Driver's setup function from
  48889. + * pcd_setup processes the gadget SETUP commands.
  48890. + */
  48891. +static inline void pcd_setup(dwc_otg_pcd_t * pcd)
  48892. +{
  48893. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  48894. + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
  48895. + usb_device_request_t ctrl = pcd->setup_pkt->req;
  48896. + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
  48897. +
  48898. + deptsiz0_data_t doeptsize0 = {.d32 = 0 };
  48899. +
  48900. +#ifdef DWC_UTE_CFI
  48901. + int retval = 0;
  48902. + struct cfi_usb_ctrlrequest cfi_req;
  48903. +#endif
  48904. +
  48905. + doeptsize0.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doeptsiz);
  48906. +
  48907. + /** In BDMA more then 1 setup packet is not supported till 3.00a */
  48908. + if (core_if->dma_enable && core_if->dma_desc_enable == 0
  48909. + && (doeptsize0.b.supcnt < 2)
  48910. + && (core_if->snpsid < OTG_CORE_REV_2_94a)) {
  48911. + DWC_ERROR
  48912. + ("\n\n----------- CANNOT handle > 1 setup packet in DMA mode\n\n");
  48913. + }
  48914. + if ((core_if->snpsid >= OTG_CORE_REV_3_00a)
  48915. + && (core_if->dma_enable == 1) && (core_if->dma_desc_enable == 0)) {
  48916. + ctrl =
  48917. + (pcd->setup_pkt +
  48918. + (3 - doeptsize0.b.supcnt - 1 +
  48919. + ep0->dwc_ep.stp_rollover))->req;
  48920. + }
  48921. +#ifdef DEBUG_EP0
  48922. + DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n",
  48923. + ctrl.bmRequestType, ctrl.bRequest,
  48924. + UGETW(ctrl.wValue), UGETW(ctrl.wIndex),
  48925. + UGETW(ctrl.wLength));
  48926. +#endif
  48927. +
  48928. + /* Clean up the request queue */
  48929. + dwc_otg_request_nuke(ep0);
  48930. + ep0->stopped = 0;
  48931. +
  48932. + if (ctrl.bmRequestType & UE_DIR_IN) {
  48933. + ep0->dwc_ep.is_in = 1;
  48934. + pcd->ep0state = EP0_IN_DATA_PHASE;
  48935. + } else {
  48936. + ep0->dwc_ep.is_in = 0;
  48937. + pcd->ep0state = EP0_OUT_DATA_PHASE;
  48938. + }
  48939. +
  48940. + if (UGETW(ctrl.wLength) == 0) {
  48941. + ep0->dwc_ep.is_in = 1;
  48942. + pcd->ep0state = EP0_IN_STATUS_PHASE;
  48943. + }
  48944. +
  48945. + if (UT_GET_TYPE(ctrl.bmRequestType) != UT_STANDARD) {
  48946. +
  48947. +#ifdef DWC_UTE_CFI
  48948. + DWC_MEMCPY(&cfi_req, &ctrl, sizeof(usb_device_request_t));
  48949. +
  48950. + //printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n",
  48951. + ctrl.bRequestType, ctrl.bRequest);
  48952. + if (UT_GET_TYPE(cfi_req.bRequestType) == UT_VENDOR) {
  48953. + if (cfi_req.bRequest > 0xB0 && cfi_req.bRequest < 0xBF) {
  48954. + retval = cfi_setup(pcd, &cfi_req);
  48955. + if (retval < 0) {
  48956. + ep0_do_stall(pcd, retval);
  48957. + pcd->ep0_pending = 0;
  48958. + return;
  48959. + }
  48960. +
  48961. + /* if need gadget setup then call it and check the retval */
  48962. + if (pcd->cfi->need_gadget_att) {
  48963. + retval =
  48964. + cfi_gadget_setup(pcd,
  48965. + &pcd->
  48966. + cfi->ctrl_req);
  48967. + if (retval < 0) {
  48968. + pcd->ep0_pending = 0;
  48969. + return;
  48970. + }
  48971. + }
  48972. +
  48973. + if (pcd->cfi->need_status_in_complete) {
  48974. + do_setup_in_status_phase(pcd);
  48975. + }
  48976. + return;
  48977. + }
  48978. + }
  48979. +#endif
  48980. +
  48981. + /* handle non-standard (class/vendor) requests in the gadget driver */
  48982. + do_gadget_setup(pcd, &ctrl);
  48983. + return;
  48984. + }
  48985. +
  48986. + /** @todo NGS: Handle bad setup packet? */
  48987. +
  48988. +///////////////////////////////////////////
  48989. +//// --- Standard Request handling --- ////
  48990. +
  48991. + switch (ctrl.bRequest) {
  48992. + case UR_GET_STATUS:
  48993. + do_get_status(pcd);
  48994. + break;
  48995. +
  48996. + case UR_CLEAR_FEATURE:
  48997. + do_clear_feature(pcd);
  48998. + break;
  48999. +
  49000. + case UR_SET_FEATURE:
  49001. + do_set_feature(pcd);
  49002. + break;
  49003. +
  49004. + case UR_SET_ADDRESS:
  49005. + do_set_address(pcd);
  49006. + break;
  49007. +
  49008. + case UR_SET_INTERFACE:
  49009. + case UR_SET_CONFIG:
  49010. +// _pcd->request_config = 1; /* Configuration changed */
  49011. + do_gadget_setup(pcd, &ctrl);
  49012. + break;
  49013. +
  49014. + case UR_SYNCH_FRAME:
  49015. + do_gadget_setup(pcd, &ctrl);
  49016. + break;
  49017. +
  49018. + default:
  49019. + /* Call the Gadget Driver's setup functions */
  49020. + do_gadget_setup(pcd, &ctrl);
  49021. + break;
  49022. + }
  49023. +}
  49024. +
  49025. +/**
  49026. + * This function completes the ep0 control transfer.
  49027. + */
  49028. +static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep)
  49029. +{
  49030. + dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
  49031. + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
  49032. + dwc_otg_dev_in_ep_regs_t *in_ep_regs =
  49033. + dev_if->in_ep_regs[ep->dwc_ep.num];
  49034. +#ifdef DEBUG_EP0
  49035. + dwc_otg_dev_out_ep_regs_t *out_ep_regs =
  49036. + dev_if->out_ep_regs[ep->dwc_ep.num];
  49037. +#endif
  49038. + deptsiz0_data_t deptsiz;
  49039. + dev_dma_desc_sts_t desc_sts;
  49040. + dwc_otg_pcd_request_t *req;
  49041. + int is_last = 0;
  49042. + dwc_otg_pcd_t *pcd = ep->pcd;
  49043. +
  49044. +#ifdef DWC_UTE_CFI
  49045. + struct cfi_usb_ctrlrequest *ctrlreq;
  49046. + int retval = -DWC_E_NOT_SUPPORTED;
  49047. +#endif
  49048. +
  49049. + desc_sts.b.bytes = 0;
  49050. +
  49051. + if (pcd->ep0_pending && DWC_CIRCLEQ_EMPTY(&ep->queue)) {
  49052. + if (ep->dwc_ep.is_in) {
  49053. +#ifdef DEBUG_EP0
  49054. + DWC_DEBUGPL(DBG_PCDV, "Do setup OUT status phase\n");
  49055. +#endif
  49056. + do_setup_out_status_phase(pcd);
  49057. + } else {
  49058. +#ifdef DEBUG_EP0
  49059. + DWC_DEBUGPL(DBG_PCDV, "Do setup IN status phase\n");
  49060. +#endif
  49061. +
  49062. +#ifdef DWC_UTE_CFI
  49063. + ctrlreq = &pcd->cfi->ctrl_req;
  49064. +
  49065. + if (UT_GET_TYPE(ctrlreq->bRequestType) == UT_VENDOR) {
  49066. + if (ctrlreq->bRequest > 0xB0
  49067. + && ctrlreq->bRequest < 0xBF) {
  49068. +
  49069. + /* Return if the PCD failed to handle the request */
  49070. + if ((retval =
  49071. + pcd->cfi->ops.
  49072. + ctrl_write_complete(pcd->cfi,
  49073. + pcd)) < 0) {
  49074. + CFI_INFO
  49075. + ("ERROR setting a new value in the PCD(%d)\n",
  49076. + retval);
  49077. + ep0_do_stall(pcd, retval);
  49078. + pcd->ep0_pending = 0;
  49079. + return 0;
  49080. + }
  49081. +
  49082. + /* If the gadget needs to be notified on the request */
  49083. + if (pcd->cfi->need_gadget_att == 1) {
  49084. + //retval = do_gadget_setup(pcd, &pcd->cfi->ctrl_req);
  49085. + retval =
  49086. + cfi_gadget_setup(pcd,
  49087. + &pcd->cfi->
  49088. + ctrl_req);
  49089. +
  49090. + /* Return from the function if the gadget failed to process
  49091. + * the request properly - this should never happen !!!
  49092. + */
  49093. + if (retval < 0) {
  49094. + CFI_INFO
  49095. + ("ERROR setting a new value in the gadget(%d)\n",
  49096. + retval);
  49097. + pcd->ep0_pending = 0;
  49098. + return 0;
  49099. + }
  49100. + }
  49101. +
  49102. + CFI_INFO("%s: RETVAL=%d\n", __func__,
  49103. + retval);
  49104. + /* If we hit here then the PCD and the gadget has properly
  49105. + * handled the request - so send the ZLP IN to the host.
  49106. + */
  49107. + /* @todo: MAS - decide whether we need to start the setup
  49108. + * stage based on the need_setup value of the cfi object
  49109. + */
  49110. + do_setup_in_status_phase(pcd);
  49111. + pcd->ep0_pending = 0;
  49112. + return 1;
  49113. + }
  49114. + }
  49115. +#endif
  49116. +
  49117. + do_setup_in_status_phase(pcd);
  49118. + }
  49119. + pcd->ep0_pending = 0;
  49120. + return 1;
  49121. + }
  49122. +
  49123. + if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
  49124. + return 0;
  49125. + }
  49126. + req = DWC_CIRCLEQ_FIRST(&ep->queue);
  49127. +
  49128. + if (pcd->ep0state == EP0_OUT_STATUS_PHASE
  49129. + || pcd->ep0state == EP0_IN_STATUS_PHASE) {
  49130. + is_last = 1;
  49131. + } else if (ep->dwc_ep.is_in) {
  49132. + deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);
  49133. + if (core_if->dma_desc_enable != 0)
  49134. + desc_sts = dev_if->in_desc_addr->status;
  49135. +#ifdef DEBUG_EP0
  49136. + DWC_DEBUGPL(DBG_PCDV, "%d len=%d xfersize=%d pktcnt=%d\n",
  49137. + ep->dwc_ep.num, ep->dwc_ep.xfer_len,
  49138. + deptsiz.b.xfersize, deptsiz.b.pktcnt);
  49139. +#endif
  49140. +
  49141. + if (((core_if->dma_desc_enable == 0)
  49142. + && (deptsiz.b.xfersize == 0))
  49143. + || ((core_if->dma_desc_enable != 0)
  49144. + && (desc_sts.b.bytes == 0))) {
  49145. + req->actual = ep->dwc_ep.xfer_count;
  49146. + /* Is a Zero Len Packet needed? */
  49147. + if (req->sent_zlp) {
  49148. +#ifdef DEBUG_EP0
  49149. + DWC_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n");
  49150. +#endif
  49151. + req->sent_zlp = 0;
  49152. + }
  49153. + do_setup_out_status_phase(pcd);
  49154. + }
  49155. + } else {
  49156. + /* ep0-OUT */
  49157. +#ifdef DEBUG_EP0
  49158. + deptsiz.d32 = DWC_READ_REG32(&out_ep_regs->doeptsiz);
  49159. + DWC_DEBUGPL(DBG_PCDV, "%d len=%d xsize=%d pktcnt=%d\n",
  49160. + ep->dwc_ep.num, ep->dwc_ep.xfer_len,
  49161. + deptsiz.b.xfersize, deptsiz.b.pktcnt);
  49162. +#endif
  49163. + req->actual = ep->dwc_ep.xfer_count;
  49164. +
  49165. + /* Is a Zero Len Packet needed? */
  49166. + if (req->sent_zlp) {
  49167. +#ifdef DEBUG_EP0
  49168. + DWC_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n");
  49169. +#endif
  49170. + req->sent_zlp = 0;
  49171. + }
  49172. + /* For older cores do setup in status phase in Slave/BDMA modes,
  49173. + * starting from 3.00 do that only in slave, and for DMA modes
  49174. + * just re-enable ep 0 OUT here*/
  49175. + if (core_if->dma_enable == 0
  49176. + || (core_if->dma_desc_enable == 0
  49177. + && core_if->snpsid <= OTG_CORE_REV_2_94a)) {
  49178. + do_setup_in_status_phase(pcd);
  49179. + } else if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
  49180. + DWC_DEBUGPL(DBG_PCDV,
  49181. + "Enable out ep before in status phase\n");
  49182. + ep0_out_start(core_if, pcd);
  49183. + }
  49184. + }
  49185. +
  49186. + /* Complete the request */
  49187. + if (is_last) {
  49188. + dwc_otg_request_done(ep, req, 0);
  49189. + ep->dwc_ep.start_xfer_buff = 0;
  49190. + ep->dwc_ep.xfer_buff = 0;
  49191. + ep->dwc_ep.xfer_len = 0;
  49192. + return 1;
  49193. + }
  49194. + return 0;
  49195. +}
  49196. +
  49197. +#ifdef DWC_UTE_CFI
  49198. +/**
  49199. + * This function calculates traverses all the CFI DMA descriptors and
  49200. + * and accumulates the bytes that are left to be transfered.
  49201. + *
  49202. + * @return The total bytes left to transfered, or a negative value as failure
  49203. + */
  49204. +static inline int cfi_calc_desc_residue(dwc_otg_pcd_ep_t * ep)
  49205. +{
  49206. + int32_t ret = 0;
  49207. + int i;
  49208. + struct dwc_otg_dma_desc *ddesc = NULL;
  49209. + struct cfi_ep *cfiep;
  49210. +
  49211. + /* See if the pcd_ep has its respective cfi_ep mapped */
  49212. + cfiep = get_cfi_ep_by_pcd_ep(ep->pcd->cfi, ep);
  49213. + if (!cfiep) {
  49214. + CFI_INFO("%s: Failed to find ep\n", __func__);
  49215. + return -1;
  49216. + }
  49217. +
  49218. + ddesc = ep->dwc_ep.descs;
  49219. +
  49220. + for (i = 0; (i < cfiep->desc_count) && (i < MAX_DMA_DESCS_PER_EP); i++) {
  49221. +
  49222. +#if defined(PRINT_CFI_DMA_DESCS)
  49223. + print_desc(ddesc, ep->ep.name, i);
  49224. +#endif
  49225. + ret += ddesc->status.b.bytes;
  49226. + ddesc++;
  49227. + }
  49228. +
  49229. + if (ret)
  49230. + CFI_INFO("!!!!!!!!!! WARNING (%s) - residue=%d\n", __func__,
  49231. + ret);
  49232. +
  49233. + return ret;
  49234. +}
  49235. +#endif
  49236. +
  49237. +/**
  49238. + * This function completes the request for the EP. If there are
  49239. + * additional requests for the EP in the queue they will be started.
  49240. + */
  49241. +static void complete_ep(dwc_otg_pcd_ep_t * ep)
  49242. +{
  49243. + dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
  49244. + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
  49245. + dwc_otg_dev_in_ep_regs_t *in_ep_regs =
  49246. + dev_if->in_ep_regs[ep->dwc_ep.num];
  49247. + deptsiz_data_t deptsiz;
  49248. + dev_dma_desc_sts_t desc_sts;
  49249. + dwc_otg_pcd_request_t *req = 0;
  49250. + dwc_otg_dev_dma_desc_t *dma_desc;
  49251. + uint32_t byte_count = 0;
  49252. + int is_last = 0;
  49253. + int i;
  49254. +
  49255. + DWC_DEBUGPL(DBG_PCDV, "%s() %d-%s\n", __func__, ep->dwc_ep.num,
  49256. + (ep->dwc_ep.is_in ? "IN" : "OUT"));
  49257. +
  49258. + /* Get any pending requests */
  49259. + if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
  49260. + req = DWC_CIRCLEQ_FIRST(&ep->queue);
  49261. + if (!req) {
  49262. + DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
  49263. + return;
  49264. + }
  49265. + } else {
  49266. + DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
  49267. + return;
  49268. + }
  49269. +
  49270. + DWC_DEBUGPL(DBG_PCD, "Requests %d\n", ep->pcd->request_pending);
  49271. +
  49272. + if (ep->dwc_ep.is_in) {
  49273. + deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz);
  49274. +
  49275. + if (core_if->dma_enable) {
  49276. + if (core_if->dma_desc_enable == 0) {
  49277. + if (deptsiz.b.xfersize == 0
  49278. + && deptsiz.b.pktcnt == 0) {
  49279. + byte_count =
  49280. + ep->dwc_ep.xfer_len -
  49281. + ep->dwc_ep.xfer_count;
  49282. +
  49283. + ep->dwc_ep.xfer_buff += byte_count;
  49284. + ep->dwc_ep.dma_addr += byte_count;
  49285. + ep->dwc_ep.xfer_count += byte_count;
  49286. +
  49287. + DWC_DEBUGPL(DBG_PCDV,
  49288. + "%d-%s len=%d xfersize=%d pktcnt=%d\n",
  49289. + ep->dwc_ep.num,
  49290. + (ep->dwc_ep.
  49291. + is_in ? "IN" : "OUT"),
  49292. + ep->dwc_ep.xfer_len,
  49293. + deptsiz.b.xfersize,
  49294. + deptsiz.b.pktcnt);
  49295. +
  49296. + if (ep->dwc_ep.xfer_len <
  49297. + ep->dwc_ep.total_len) {
  49298. + dwc_otg_ep_start_transfer
  49299. + (core_if, &ep->dwc_ep);
  49300. + } else if (ep->dwc_ep.sent_zlp) {
  49301. + /*
  49302. + * This fragment of code should initiate 0
  49303. + * length transfer in case if it is queued
  49304. + * a transfer with size divisible to EPs max
  49305. + * packet size and with usb_request zero field
  49306. + * is set, which means that after data is transfered,
  49307. + * it is also should be transfered
  49308. + * a 0 length packet at the end. For Slave and
  49309. + * Buffer DMA modes in this case SW has
  49310. + * to initiate 2 transfers one with transfer size,
  49311. + * and the second with 0 size. For Descriptor
  49312. + * DMA mode SW is able to initiate a transfer,
  49313. + * which will handle all the packets including
  49314. + * the last 0 length.
  49315. + */
  49316. + ep->dwc_ep.sent_zlp = 0;
  49317. + dwc_otg_ep_start_zl_transfer
  49318. + (core_if, &ep->dwc_ep);
  49319. + } else {
  49320. + is_last = 1;
  49321. + }
  49322. + } else {
  49323. + if (ep->dwc_ep.type ==
  49324. + DWC_OTG_EP_TYPE_ISOC) {
  49325. + req->actual = 0;
  49326. + dwc_otg_request_done(ep, req, 0);
  49327. +
  49328. + ep->dwc_ep.start_xfer_buff = 0;
  49329. + ep->dwc_ep.xfer_buff = 0;
  49330. + ep->dwc_ep.xfer_len = 0;
  49331. +
  49332. + /* If there is a request in the queue start it. */
  49333. + start_next_request(ep);
  49334. + } else
  49335. + DWC_WARN
  49336. + ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n",
  49337. + ep->dwc_ep.num,
  49338. + (ep->dwc_ep.is_in ? "IN" : "OUT"),
  49339. + deptsiz.b.xfersize,
  49340. + deptsiz.b.pktcnt);
  49341. + }
  49342. + } else {
  49343. + dma_desc = ep->dwc_ep.desc_addr;
  49344. + byte_count = 0;
  49345. + ep->dwc_ep.sent_zlp = 0;
  49346. +
  49347. +#ifdef DWC_UTE_CFI
  49348. + CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,
  49349. + ep->dwc_ep.buff_mode);
  49350. + if (ep->dwc_ep.buff_mode != BM_STANDARD) {
  49351. + int residue;
  49352. +
  49353. + residue = cfi_calc_desc_residue(ep);
  49354. + if (residue < 0)
  49355. + return;
  49356. +
  49357. + byte_count = residue;
  49358. + } else {
  49359. +#endif
  49360. + for (i = 0; i < ep->dwc_ep.desc_cnt;
  49361. + ++i) {
  49362. + desc_sts = dma_desc->status;
  49363. + byte_count += desc_sts.b.bytes;
  49364. + dma_desc++;
  49365. + }
  49366. +#ifdef DWC_UTE_CFI
  49367. + }
  49368. +#endif
  49369. + if (byte_count == 0) {
  49370. + ep->dwc_ep.xfer_count =
  49371. + ep->dwc_ep.total_len;
  49372. + is_last = 1;
  49373. + } else {
  49374. + DWC_WARN("Incomplete transfer\n");
  49375. + }
  49376. + }
  49377. + } else {
  49378. + if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0) {
  49379. + DWC_DEBUGPL(DBG_PCDV,
  49380. + "%d-%s len=%d xfersize=%d pktcnt=%d\n",
  49381. + ep->dwc_ep.num,
  49382. + ep->dwc_ep.is_in ? "IN" : "OUT",
  49383. + ep->dwc_ep.xfer_len,
  49384. + deptsiz.b.xfersize,
  49385. + deptsiz.b.pktcnt);
  49386. +
  49387. + /* Check if the whole transfer was completed,
  49388. + * if no, setup transfer for next portion of data
  49389. + */
  49390. + if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
  49391. + dwc_otg_ep_start_transfer(core_if,
  49392. + &ep->dwc_ep);
  49393. + } else if (ep->dwc_ep.sent_zlp) {
  49394. + /*
  49395. + * This fragment of code should initiate 0
  49396. + * length trasfer in case if it is queued
  49397. + * a trasfer with size divisible to EPs max
  49398. + * packet size and with usb_request zero field
  49399. + * is set, which means that after data is transfered,
  49400. + * it is also should be transfered
  49401. + * a 0 length packet at the end. For Slave and
  49402. + * Buffer DMA modes in this case SW has
  49403. + * to initiate 2 transfers one with transfer size,
  49404. + * and the second with 0 size. For Desriptor
  49405. + * DMA mode SW is able to initiate a transfer,
  49406. + * which will handle all the packets including
  49407. + * the last 0 legth.
  49408. + */
  49409. + ep->dwc_ep.sent_zlp = 0;
  49410. + dwc_otg_ep_start_zl_transfer(core_if,
  49411. + &ep->dwc_ep);
  49412. + } else {
  49413. + is_last = 1;
  49414. + }
  49415. + } else {
  49416. + DWC_WARN
  49417. + ("Incomplete transfer (%d-%s [siz=%d pkt=%d])\n",
  49418. + ep->dwc_ep.num,
  49419. + (ep->dwc_ep.is_in ? "IN" : "OUT"),
  49420. + deptsiz.b.xfersize, deptsiz.b.pktcnt);
  49421. + }
  49422. + }
  49423. + } else {
  49424. + dwc_otg_dev_out_ep_regs_t *out_ep_regs =
  49425. + dev_if->out_ep_regs[ep->dwc_ep.num];
  49426. + desc_sts.d32 = 0;
  49427. + if (core_if->dma_enable) {
  49428. + if (core_if->dma_desc_enable) {
  49429. + dma_desc = ep->dwc_ep.desc_addr;
  49430. + byte_count = 0;
  49431. + ep->dwc_ep.sent_zlp = 0;
  49432. +
  49433. +#ifdef DWC_UTE_CFI
  49434. + CFI_INFO("%s: BUFFER_MODE=%d\n", __func__,
  49435. + ep->dwc_ep.buff_mode);
  49436. + if (ep->dwc_ep.buff_mode != BM_STANDARD) {
  49437. + int residue;
  49438. + residue = cfi_calc_desc_residue(ep);
  49439. + if (residue < 0)
  49440. + return;
  49441. + byte_count = residue;
  49442. + } else {
  49443. +#endif
  49444. +
  49445. + for (i = 0; i < ep->dwc_ep.desc_cnt;
  49446. + ++i) {
  49447. + desc_sts = dma_desc->status;
  49448. + byte_count += desc_sts.b.bytes;
  49449. + dma_desc++;
  49450. + }
  49451. +
  49452. +#ifdef DWC_UTE_CFI
  49453. + }
  49454. +#endif
  49455. + /* Checking for interrupt Out transfers with not
  49456. + * dword aligned mps sizes
  49457. + */
  49458. + if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_INTR &&
  49459. + (ep->dwc_ep.maxpacket%4)) {
  49460. + ep->dwc_ep.xfer_count =
  49461. + ep->dwc_ep.total_len - byte_count;
  49462. + if ((ep->dwc_ep.xfer_len %
  49463. + ep->dwc_ep.maxpacket)
  49464. + && (ep->dwc_ep.xfer_len /
  49465. + ep->dwc_ep.maxpacket <
  49466. + MAX_DMA_DESC_CNT))
  49467. + ep->dwc_ep.xfer_len -=
  49468. + (ep->dwc_ep.desc_cnt -
  49469. + 1) * ep->dwc_ep.maxpacket +
  49470. + ep->dwc_ep.xfer_len %
  49471. + ep->dwc_ep.maxpacket;
  49472. + else
  49473. + ep->dwc_ep.xfer_len -=
  49474. + ep->dwc_ep.desc_cnt *
  49475. + ep->dwc_ep.maxpacket;
  49476. + if (ep->dwc_ep.xfer_len > 0) {
  49477. + dwc_otg_ep_start_transfer
  49478. + (core_if, &ep->dwc_ep);
  49479. + } else {
  49480. + is_last = 1;
  49481. + }
  49482. + } else {
  49483. + ep->dwc_ep.xfer_count =
  49484. + ep->dwc_ep.total_len - byte_count +
  49485. + ((4 -
  49486. + (ep->dwc_ep.
  49487. + total_len & 0x3)) & 0x3);
  49488. + is_last = 1;
  49489. + }
  49490. + } else {
  49491. + deptsiz.d32 = 0;
  49492. + deptsiz.d32 =
  49493. + DWC_READ_REG32(&out_ep_regs->doeptsiz);
  49494. +
  49495. + byte_count = (ep->dwc_ep.xfer_len -
  49496. + ep->dwc_ep.xfer_count -
  49497. + deptsiz.b.xfersize);
  49498. + ep->dwc_ep.xfer_buff += byte_count;
  49499. + ep->dwc_ep.dma_addr += byte_count;
  49500. + ep->dwc_ep.xfer_count += byte_count;
  49501. +
  49502. + /* Check if the whole transfer was completed,
  49503. + * if no, setup transfer for next portion of data
  49504. + */
  49505. + if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
  49506. + dwc_otg_ep_start_transfer(core_if,
  49507. + &ep->dwc_ep);
  49508. + } else if (ep->dwc_ep.sent_zlp) {
  49509. + /*
  49510. + * This fragment of code should initiate 0
  49511. + * length trasfer in case if it is queued
  49512. + * a trasfer with size divisible to EPs max
  49513. + * packet size and with usb_request zero field
  49514. + * is set, which means that after data is transfered,
  49515. + * it is also should be transfered
  49516. + * a 0 length packet at the end. For Slave and
  49517. + * Buffer DMA modes in this case SW has
  49518. + * to initiate 2 transfers one with transfer size,
  49519. + * and the second with 0 size. For Desriptor
  49520. + * DMA mode SW is able to initiate a transfer,
  49521. + * which will handle all the packets including
  49522. + * the last 0 legth.
  49523. + */
  49524. + ep->dwc_ep.sent_zlp = 0;
  49525. + dwc_otg_ep_start_zl_transfer(core_if,
  49526. + &ep->dwc_ep);
  49527. + } else {
  49528. + is_last = 1;
  49529. + }
  49530. + }
  49531. + } else {
  49532. + /* Check if the whole transfer was completed,
  49533. + * if no, setup transfer for next portion of data
  49534. + */
  49535. + if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) {
  49536. + dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
  49537. + } else if (ep->dwc_ep.sent_zlp) {
  49538. + /*
  49539. + * This fragment of code should initiate 0
  49540. + * length transfer in case if it is queued
  49541. + * a transfer with size divisible to EPs max
  49542. + * packet size and with usb_request zero field
  49543. + * is set, which means that after data is transfered,
  49544. + * it is also should be transfered
  49545. + * a 0 length packet at the end. For Slave and
  49546. + * Buffer DMA modes in this case SW has
  49547. + * to initiate 2 transfers one with transfer size,
  49548. + * and the second with 0 size. For Descriptor
  49549. + * DMA mode SW is able to initiate a transfer,
  49550. + * which will handle all the packets including
  49551. + * the last 0 length.
  49552. + */
  49553. + ep->dwc_ep.sent_zlp = 0;
  49554. + dwc_otg_ep_start_zl_transfer(core_if,
  49555. + &ep->dwc_ep);
  49556. + } else {
  49557. + is_last = 1;
  49558. + }
  49559. + }
  49560. +
  49561. + DWC_DEBUGPL(DBG_PCDV,
  49562. + "addr %p, %d-%s len=%d cnt=%d xsize=%d pktcnt=%d\n",
  49563. + &out_ep_regs->doeptsiz, ep->dwc_ep.num,
  49564. + ep->dwc_ep.is_in ? "IN" : "OUT",
  49565. + ep->dwc_ep.xfer_len, ep->dwc_ep.xfer_count,
  49566. + deptsiz.b.xfersize, deptsiz.b.pktcnt);
  49567. + }
  49568. +
  49569. + /* Complete the request */
  49570. + if (is_last) {
  49571. +#ifdef DWC_UTE_CFI
  49572. + if (ep->dwc_ep.buff_mode != BM_STANDARD) {
  49573. + req->actual = ep->dwc_ep.cfi_req_len - byte_count;
  49574. + } else {
  49575. +#endif
  49576. + req->actual = ep->dwc_ep.xfer_count;
  49577. +#ifdef DWC_UTE_CFI
  49578. + }
  49579. +#endif
  49580. + if (req->dw_align_buf) {
  49581. + if (!ep->dwc_ep.is_in) {
  49582. + dwc_memcpy(req->buf, req->dw_align_buf, req->length);
  49583. + }
  49584. + DWC_DMA_FREE(req->length, req->dw_align_buf,
  49585. + req->dw_align_buf_dma);
  49586. + }
  49587. +
  49588. + dwc_otg_request_done(ep, req, 0);
  49589. +
  49590. + ep->dwc_ep.start_xfer_buff = 0;
  49591. + ep->dwc_ep.xfer_buff = 0;
  49592. + ep->dwc_ep.xfer_len = 0;
  49593. +
  49594. + /* If there is a request in the queue start it. */
  49595. + start_next_request(ep);
  49596. + }
  49597. +}
  49598. +
  49599. +#ifdef DWC_EN_ISOC
  49600. +
  49601. +/**
  49602. + * This function BNA interrupt for Isochronous EPs
  49603. + *
  49604. + */
  49605. +static void dwc_otg_pcd_handle_iso_bna(dwc_otg_pcd_ep_t * ep)
  49606. +{
  49607. + dwc_ep_t *dwc_ep = &ep->dwc_ep;
  49608. + volatile uint32_t *addr;
  49609. + depctl_data_t depctl = {.d32 = 0 };
  49610. + dwc_otg_pcd_t *pcd = ep->pcd;
  49611. + dwc_otg_dev_dma_desc_t *dma_desc;
  49612. + int i;
  49613. +
  49614. + dma_desc =
  49615. + dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * (dwc_ep->proc_buf_num);
  49616. +
  49617. + if (dwc_ep->is_in) {
  49618. + dev_dma_desc_sts_t sts = {.d32 = 0 };
  49619. + for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
  49620. + sts.d32 = dma_desc->status.d32;
  49621. + sts.b_iso_in.bs = BS_HOST_READY;
  49622. + dma_desc->status.d32 = sts.d32;
  49623. + }
  49624. + } else {
  49625. + dev_dma_desc_sts_t sts = {.d32 = 0 };
  49626. + for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
  49627. + sts.d32 = dma_desc->status.d32;
  49628. + sts.b_iso_out.bs = BS_HOST_READY;
  49629. + dma_desc->status.d32 = sts.d32;
  49630. + }
  49631. + }
  49632. +
  49633. + if (dwc_ep->is_in == 0) {
  49634. + addr =
  49635. + &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->
  49636. + num]->doepctl;
  49637. + } else {
  49638. + addr =
  49639. + &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
  49640. + }
  49641. + depctl.b.epena = 1;
  49642. + DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32);
  49643. +}
  49644. +
  49645. +/**
  49646. + * This function sets latest iso packet information(non-PTI mode)
  49647. + *
  49648. + * @param core_if Programming view of DWC_otg controller.
  49649. + * @param ep The EP to start the transfer on.
  49650. + *
  49651. + */
  49652. +void set_current_pkt_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
  49653. +{
  49654. + deptsiz_data_t deptsiz = {.d32 = 0 };
  49655. + dma_addr_t dma_addr;
  49656. + uint32_t offset;
  49657. +
  49658. + if (ep->proc_buf_num)
  49659. + dma_addr = ep->dma_addr1;
  49660. + else
  49661. + dma_addr = ep->dma_addr0;
  49662. +
  49663. + if (ep->is_in) {
  49664. + deptsiz.d32 =
  49665. + DWC_READ_REG32(&core_if->dev_if->
  49666. + in_ep_regs[ep->num]->dieptsiz);
  49667. + offset = ep->data_per_frame;
  49668. + } else {
  49669. + deptsiz.d32 =
  49670. + DWC_READ_REG32(&core_if->dev_if->
  49671. + out_ep_regs[ep->num]->doeptsiz);
  49672. + offset =
  49673. + ep->data_per_frame +
  49674. + (0x4 & (0x4 - (ep->data_per_frame & 0x3)));
  49675. + }
  49676. +
  49677. + if (!deptsiz.b.xfersize) {
  49678. + ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;
  49679. + ep->pkt_info[ep->cur_pkt].offset =
  49680. + ep->cur_pkt_dma_addr - dma_addr;
  49681. + ep->pkt_info[ep->cur_pkt].status = 0;
  49682. + } else {
  49683. + ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame;
  49684. + ep->pkt_info[ep->cur_pkt].offset =
  49685. + ep->cur_pkt_dma_addr - dma_addr;
  49686. + ep->pkt_info[ep->cur_pkt].status = -DWC_E_NO_DATA;
  49687. + }
  49688. + ep->cur_pkt_addr += offset;
  49689. + ep->cur_pkt_dma_addr += offset;
  49690. + ep->cur_pkt++;
  49691. +}
  49692. +
  49693. +/**
  49694. + * This function sets latest iso packet information(DDMA mode)
  49695. + *
  49696. + * @param core_if Programming view of DWC_otg controller.
  49697. + * @param dwc_ep The EP to start the transfer on.
  49698. + *
  49699. + */
  49700. +static void set_ddma_iso_pkts_info(dwc_otg_core_if_t * core_if,
  49701. + dwc_ep_t * dwc_ep)
  49702. +{
  49703. + dwc_otg_dev_dma_desc_t *dma_desc;
  49704. + dev_dma_desc_sts_t sts = {.d32 = 0 };
  49705. + iso_pkt_info_t *iso_packet;
  49706. + uint32_t data_per_desc;
  49707. + uint32_t offset;
  49708. + int i, j;
  49709. +
  49710. + iso_packet = dwc_ep->pkt_info;
  49711. +
  49712. + /** Reinit closed DMA Descriptors*/
  49713. + /** ISO OUT EP */
  49714. + if (dwc_ep->is_in == 0) {
  49715. + dma_desc =
  49716. + dwc_ep->iso_desc_addr +
  49717. + dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
  49718. + offset = 0;
  49719. +
  49720. + for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
  49721. + i += dwc_ep->pkt_per_frm) {
  49722. + for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
  49723. + data_per_desc =
  49724. + ((j + 1) * dwc_ep->maxpacket >
  49725. + dwc_ep->
  49726. + data_per_frame) ? dwc_ep->data_per_frame -
  49727. + j * dwc_ep->maxpacket : dwc_ep->maxpacket;
  49728. + data_per_desc +=
  49729. + (data_per_desc % 4) ? (4 -
  49730. + data_per_desc %
  49731. + 4) : 0;
  49732. +
  49733. + sts.d32 = dma_desc->status.d32;
  49734. +
  49735. + /* Write status in iso_packet_decsriptor */
  49736. + iso_packet->status =
  49737. + sts.b_iso_out.rxsts +
  49738. + (sts.b_iso_out.bs ^ BS_DMA_DONE);
  49739. + if (iso_packet->status) {
  49740. + iso_packet->status = -DWC_E_NO_DATA;
  49741. + }
  49742. +
  49743. + /* Received data length */
  49744. + if (!sts.b_iso_out.rxbytes) {
  49745. + iso_packet->length =
  49746. + data_per_desc -
  49747. + sts.b_iso_out.rxbytes;
  49748. + } else {
  49749. + iso_packet->length =
  49750. + data_per_desc -
  49751. + sts.b_iso_out.rxbytes + (4 -
  49752. + dwc_ep->data_per_frame
  49753. + % 4);
  49754. + }
  49755. +
  49756. + iso_packet->offset = offset;
  49757. +
  49758. + offset += data_per_desc;
  49759. + dma_desc++;
  49760. + iso_packet++;
  49761. + }
  49762. + }
  49763. +
  49764. + for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
  49765. + data_per_desc =
  49766. + ((j + 1) * dwc_ep->maxpacket >
  49767. + dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
  49768. + j * dwc_ep->maxpacket : dwc_ep->maxpacket;
  49769. + data_per_desc +=
  49770. + (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
  49771. +
  49772. + sts.d32 = dma_desc->status.d32;
  49773. +
  49774. + /* Write status in iso_packet_decsriptor */
  49775. + iso_packet->status =
  49776. + sts.b_iso_out.rxsts +
  49777. + (sts.b_iso_out.bs ^ BS_DMA_DONE);
  49778. + if (iso_packet->status) {
  49779. + iso_packet->status = -DWC_E_NO_DATA;
  49780. + }
  49781. +
  49782. + /* Received data length */
  49783. + iso_packet->length =
  49784. + dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;
  49785. +
  49786. + iso_packet->offset = offset;
  49787. +
  49788. + offset += data_per_desc;
  49789. + iso_packet++;
  49790. + dma_desc++;
  49791. + }
  49792. +
  49793. + sts.d32 = dma_desc->status.d32;
  49794. +
  49795. + /* Write status in iso_packet_decsriptor */
  49796. + iso_packet->status =
  49797. + sts.b_iso_out.rxsts + (sts.b_iso_out.bs ^ BS_DMA_DONE);
  49798. + if (iso_packet->status) {
  49799. + iso_packet->status = -DWC_E_NO_DATA;
  49800. + }
  49801. + /* Received data length */
  49802. + if (!sts.b_iso_out.rxbytes) {
  49803. + iso_packet->length =
  49804. + dwc_ep->data_per_frame - sts.b_iso_out.rxbytes;
  49805. + } else {
  49806. + iso_packet->length =
  49807. + dwc_ep->data_per_frame - sts.b_iso_out.rxbytes +
  49808. + (4 - dwc_ep->data_per_frame % 4);
  49809. + }
  49810. +
  49811. + iso_packet->offset = offset;
  49812. + } else {
  49813. +/** ISO IN EP */
  49814. +
  49815. + dma_desc =
  49816. + dwc_ep->iso_desc_addr +
  49817. + dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
  49818. +
  49819. + for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
  49820. + sts.d32 = dma_desc->status.d32;
  49821. +
  49822. + /* Write status in iso packet descriptor */
  49823. + iso_packet->status =
  49824. + sts.b_iso_in.txsts +
  49825. + (sts.b_iso_in.bs ^ BS_DMA_DONE);
  49826. + if (iso_packet->status != 0) {
  49827. + iso_packet->status = -DWC_E_NO_DATA;
  49828. +
  49829. + }
  49830. + /* Bytes has been transfered */
  49831. + iso_packet->length =
  49832. + dwc_ep->data_per_frame - sts.b_iso_in.txbytes;
  49833. +
  49834. + dma_desc++;
  49835. + iso_packet++;
  49836. + }
  49837. +
  49838. + sts.d32 = dma_desc->status.d32;
  49839. + while (sts.b_iso_in.bs == BS_DMA_BUSY) {
  49840. + sts.d32 = dma_desc->status.d32;
  49841. + }
  49842. +
  49843. + /* Write status in iso packet descriptor ??? do be done with ERROR codes */
  49844. + iso_packet->status =
  49845. + sts.b_iso_in.txsts + (sts.b_iso_in.bs ^ BS_DMA_DONE);
  49846. + if (iso_packet->status != 0) {
  49847. + iso_packet->status = -DWC_E_NO_DATA;
  49848. + }
  49849. +
  49850. + /* Bytes has been transfered */
  49851. + iso_packet->length =
  49852. + dwc_ep->data_per_frame - sts.b_iso_in.txbytes;
  49853. + }
  49854. +}
  49855. +
  49856. +/**
  49857. + * This function reinitialize DMA Descriptors for Isochronous transfer
  49858. + *
  49859. + * @param core_if Programming view of DWC_otg controller.
  49860. + * @param dwc_ep The EP to start the transfer on.
  49861. + *
  49862. + */
  49863. +static void reinit_ddma_iso_xfer(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep)
  49864. +{
  49865. + int i, j;
  49866. + dwc_otg_dev_dma_desc_t *dma_desc;
  49867. + dma_addr_t dma_ad;
  49868. + volatile uint32_t *addr;
  49869. + dev_dma_desc_sts_t sts = {.d32 = 0 };
  49870. + uint32_t data_per_desc;
  49871. +
  49872. + if (dwc_ep->is_in == 0) {
  49873. + addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl;
  49874. + } else {
  49875. + addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
  49876. + }
  49877. +
  49878. + if (dwc_ep->proc_buf_num == 0) {
  49879. + /** Buffer 0 descriptors setup */
  49880. + dma_ad = dwc_ep->dma_addr0;
  49881. + } else {
  49882. + /** Buffer 1 descriptors setup */
  49883. + dma_ad = dwc_ep->dma_addr1;
  49884. + }
  49885. +
  49886. + /** Reinit closed DMA Descriptors*/
  49887. + /** ISO OUT EP */
  49888. + if (dwc_ep->is_in == 0) {
  49889. + dma_desc =
  49890. + dwc_ep->iso_desc_addr +
  49891. + dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
  49892. +
  49893. + sts.b_iso_out.bs = BS_HOST_READY;
  49894. + sts.b_iso_out.rxsts = 0;
  49895. + sts.b_iso_out.l = 0;
  49896. + sts.b_iso_out.sp = 0;
  49897. + sts.b_iso_out.ioc = 0;
  49898. + sts.b_iso_out.pid = 0;
  49899. + sts.b_iso_out.framenum = 0;
  49900. +
  49901. + for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm;
  49902. + i += dwc_ep->pkt_per_frm) {
  49903. + for (j = 0; j < dwc_ep->pkt_per_frm; ++j) {
  49904. + data_per_desc =
  49905. + ((j + 1) * dwc_ep->maxpacket >
  49906. + dwc_ep->
  49907. + data_per_frame) ? dwc_ep->data_per_frame -
  49908. + j * dwc_ep->maxpacket : dwc_ep->maxpacket;
  49909. + data_per_desc +=
  49910. + (data_per_desc % 4) ? (4 -
  49911. + data_per_desc %
  49912. + 4) : 0;
  49913. + sts.b_iso_out.rxbytes = data_per_desc;
  49914. + dma_desc->buf = dma_ad;
  49915. + dma_desc->status.d32 = sts.d32;
  49916. +
  49917. + dma_ad += data_per_desc;
  49918. + dma_desc++;
  49919. + }
  49920. + }
  49921. +
  49922. + for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) {
  49923. +
  49924. + data_per_desc =
  49925. + ((j + 1) * dwc_ep->maxpacket >
  49926. + dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
  49927. + j * dwc_ep->maxpacket : dwc_ep->maxpacket;
  49928. + data_per_desc +=
  49929. + (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
  49930. + sts.b_iso_out.rxbytes = data_per_desc;
  49931. +
  49932. + dma_desc->buf = dma_ad;
  49933. + dma_desc->status.d32 = sts.d32;
  49934. +
  49935. + dma_desc++;
  49936. + dma_ad += data_per_desc;
  49937. + }
  49938. +
  49939. + sts.b_iso_out.ioc = 1;
  49940. + sts.b_iso_out.l = dwc_ep->proc_buf_num;
  49941. +
  49942. + data_per_desc =
  49943. + ((j + 1) * dwc_ep->maxpacket >
  49944. + dwc_ep->data_per_frame) ? dwc_ep->data_per_frame -
  49945. + j * dwc_ep->maxpacket : dwc_ep->maxpacket;
  49946. + data_per_desc +=
  49947. + (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0;
  49948. + sts.b_iso_out.rxbytes = data_per_desc;
  49949. +
  49950. + dma_desc->buf = dma_ad;
  49951. + dma_desc->status.d32 = sts.d32;
  49952. + } else {
  49953. +/** ISO IN EP */
  49954. +
  49955. + dma_desc =
  49956. + dwc_ep->iso_desc_addr +
  49957. + dwc_ep->desc_cnt * dwc_ep->proc_buf_num;
  49958. +
  49959. + sts.b_iso_in.bs = BS_HOST_READY;
  49960. + sts.b_iso_in.txsts = 0;
  49961. + sts.b_iso_in.sp = 0;
  49962. + sts.b_iso_in.ioc = 0;
  49963. + sts.b_iso_in.pid = dwc_ep->pkt_per_frm;
  49964. + sts.b_iso_in.framenum = dwc_ep->next_frame;
  49965. + sts.b_iso_in.txbytes = dwc_ep->data_per_frame;
  49966. + sts.b_iso_in.l = 0;
  49967. +
  49968. + for (i = 0; i < dwc_ep->desc_cnt - 1; i++) {
  49969. + dma_desc->buf = dma_ad;
  49970. + dma_desc->status.d32 = sts.d32;
  49971. +
  49972. + sts.b_iso_in.framenum += dwc_ep->bInterval;
  49973. + dma_ad += dwc_ep->data_per_frame;
  49974. + dma_desc++;
  49975. + }
  49976. +
  49977. + sts.b_iso_in.ioc = 1;
  49978. + sts.b_iso_in.l = dwc_ep->proc_buf_num;
  49979. +
  49980. + dma_desc->buf = dma_ad;
  49981. + dma_desc->status.d32 = sts.d32;
  49982. +
  49983. + dwc_ep->next_frame =
  49984. + sts.b_iso_in.framenum + dwc_ep->bInterval * 1;
  49985. + }
  49986. + dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;
  49987. +}
  49988. +
  49989. +/**
  49990. + * This function is to handle Iso EP transfer complete interrupt
  49991. + * in case Iso out packet was dropped
  49992. + *
  49993. + * @param core_if Programming view of DWC_otg controller.
  49994. + * @param dwc_ep The EP for wihich transfer complete was asserted
  49995. + *
  49996. + */
  49997. +static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t * core_if,
  49998. + dwc_ep_t * dwc_ep)
  49999. +{
  50000. + uint32_t dma_addr;
  50001. + uint32_t drp_pkt;
  50002. + uint32_t drp_pkt_cnt;
  50003. + deptsiz_data_t deptsiz = {.d32 = 0 };
  50004. + depctl_data_t depctl = {.d32 = 0 };
  50005. + int i;
  50006. +
  50007. + deptsiz.d32 =
  50008. + DWC_READ_REG32(&core_if->dev_if->
  50009. + out_ep_regs[dwc_ep->num]->doeptsiz);
  50010. +
  50011. + drp_pkt = dwc_ep->pkt_cnt - deptsiz.b.pktcnt;
  50012. + drp_pkt_cnt = dwc_ep->pkt_per_frm - (drp_pkt % dwc_ep->pkt_per_frm);
  50013. +
  50014. + /* Setting dropped packets status */
  50015. + for (i = 0; i < drp_pkt_cnt; ++i) {
  50016. + dwc_ep->pkt_info[drp_pkt].status = -DWC_E_NO_DATA;
  50017. + drp_pkt++;
  50018. + deptsiz.b.pktcnt--;
  50019. + }
  50020. +
  50021. + if (deptsiz.b.pktcnt > 0) {
  50022. + deptsiz.b.xfersize =
  50023. + dwc_ep->xfer_len - (dwc_ep->pkt_cnt -
  50024. + deptsiz.b.pktcnt) * dwc_ep->maxpacket;
  50025. + } else {
  50026. + deptsiz.b.xfersize = 0;
  50027. + deptsiz.b.pktcnt = 0;
  50028. + }
  50029. +
  50030. + DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz,
  50031. + deptsiz.d32);
  50032. +
  50033. + if (deptsiz.b.pktcnt > 0) {
  50034. + if (dwc_ep->proc_buf_num) {
  50035. + dma_addr =
  50036. + dwc_ep->dma_addr1 + dwc_ep->xfer_len -
  50037. + deptsiz.b.xfersize;
  50038. + } else {
  50039. + dma_addr =
  50040. + dwc_ep->dma_addr0 + dwc_ep->xfer_len -
  50041. + deptsiz.b.xfersize;;
  50042. + }
  50043. +
  50044. + DWC_WRITE_REG32(&core_if->dev_if->
  50045. + out_ep_regs[dwc_ep->num]->doepdma, dma_addr);
  50046. +
  50047. + /** Re-enable endpoint, clear nak */
  50048. + depctl.d32 = 0;
  50049. + depctl.b.epena = 1;
  50050. + depctl.b.cnak = 1;
  50051. +
  50052. + DWC_MODIFY_REG32(&core_if->dev_if->
  50053. + out_ep_regs[dwc_ep->num]->doepctl, depctl.d32,
  50054. + depctl.d32);
  50055. + return 0;
  50056. + } else {
  50057. + return 1;
  50058. + }
  50059. +}
  50060. +
  50061. +/**
  50062. + * This function sets iso packets information(PTI mode)
  50063. + *
  50064. + * @param core_if Programming view of DWC_otg controller.
  50065. + * @param ep The EP to start the transfer on.
  50066. + *
  50067. + */
  50068. +static uint32_t set_iso_pkts_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep)
  50069. +{
  50070. + int i, j;
  50071. + dma_addr_t dma_ad;
  50072. + iso_pkt_info_t *packet_info = ep->pkt_info;
  50073. + uint32_t offset;
  50074. + uint32_t frame_data;
  50075. + deptsiz_data_t deptsiz;
  50076. +
  50077. + if (ep->proc_buf_num == 0) {
  50078. + /** Buffer 0 descriptors setup */
  50079. + dma_ad = ep->dma_addr0;
  50080. + } else {
  50081. + /** Buffer 1 descriptors setup */
  50082. + dma_ad = ep->dma_addr1;
  50083. + }
  50084. +
  50085. + if (ep->is_in) {
  50086. + deptsiz.d32 =
  50087. + DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->
  50088. + dieptsiz);
  50089. + } else {
  50090. + deptsiz.d32 =
  50091. + DWC_READ_REG32(&core_if->dev_if->out_ep_regs[ep->num]->
  50092. + doeptsiz);
  50093. + }
  50094. +
  50095. + if (!deptsiz.b.xfersize) {
  50096. + offset = 0;
  50097. + for (i = 0; i < ep->pkt_cnt; i += ep->pkt_per_frm) {
  50098. + frame_data = ep->data_per_frame;
  50099. + for (j = 0; j < ep->pkt_per_frm; ++j) {
  50100. +
  50101. + /* Packet status - is not set as initially
  50102. + * it is set to 0 and if packet was sent
  50103. + successfully, status field will remain 0*/
  50104. +
  50105. + /* Bytes has been transfered */
  50106. + packet_info->length =
  50107. + (ep->maxpacket <
  50108. + frame_data) ? ep->maxpacket : frame_data;
  50109. +
  50110. + /* Received packet offset */
  50111. + packet_info->offset = offset;
  50112. + offset += packet_info->length;
  50113. + frame_data -= packet_info->length;
  50114. +
  50115. + packet_info++;
  50116. + }
  50117. + }
  50118. + return 1;
  50119. + } else {
  50120. + /* This is a workaround for in case of Transfer Complete with
  50121. + * PktDrpSts interrupts merging - in this case Transfer complete
  50122. + * interrupt for Isoc Out Endpoint is asserted without PktDrpSts
  50123. + * set and with DOEPTSIZ register non zero. Investigations showed,
  50124. + * that this happens when Out packet is dropped, but because of
  50125. + * interrupts merging during first interrupt handling PktDrpSts
  50126. + * bit is cleared and for next merged interrupts it is not reset.
  50127. + * In this case SW hadles the interrupt as if PktDrpSts bit is set.
  50128. + */
  50129. + if (ep->is_in) {
  50130. + return 1;
  50131. + } else {
  50132. + return handle_iso_out_pkt_dropped(core_if, ep);
  50133. + }
  50134. + }
  50135. +}
  50136. +
  50137. +/**
  50138. + * This function is to handle Iso EP transfer complete interrupt
  50139. + *
  50140. + * @param pcd The PCD
  50141. + * @param ep The EP for which transfer complete was asserted
  50142. + *
  50143. + */
  50144. +static void complete_iso_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep)
  50145. +{
  50146. + dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd);
  50147. + dwc_ep_t *dwc_ep = &ep->dwc_ep;
  50148. + uint8_t is_last = 0;
  50149. +
  50150. + if (ep->dwc_ep.next_frame == 0xffffffff) {
  50151. + DWC_WARN("Next frame is not set!\n");
  50152. + return;
  50153. + }
  50154. +
  50155. + if (core_if->dma_enable) {
  50156. + if (core_if->dma_desc_enable) {
  50157. + set_ddma_iso_pkts_info(core_if, dwc_ep);
  50158. + reinit_ddma_iso_xfer(core_if, dwc_ep);
  50159. + is_last = 1;
  50160. + } else {
  50161. + if (core_if->pti_enh_enable) {
  50162. + if (set_iso_pkts_info(core_if, dwc_ep)) {
  50163. + dwc_ep->proc_buf_num =
  50164. + (dwc_ep->proc_buf_num ^ 1) & 0x1;
  50165. + dwc_otg_iso_ep_start_buf_transfer
  50166. + (core_if, dwc_ep);
  50167. + is_last = 1;
  50168. + }
  50169. + } else {
  50170. + set_current_pkt_info(core_if, dwc_ep);
  50171. + if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
  50172. + is_last = 1;
  50173. + dwc_ep->cur_pkt = 0;
  50174. + dwc_ep->proc_buf_num =
  50175. + (dwc_ep->proc_buf_num ^ 1) & 0x1;
  50176. + if (dwc_ep->proc_buf_num) {
  50177. + dwc_ep->cur_pkt_addr =
  50178. + dwc_ep->xfer_buff1;
  50179. + dwc_ep->cur_pkt_dma_addr =
  50180. + dwc_ep->dma_addr1;
  50181. + } else {
  50182. + dwc_ep->cur_pkt_addr =
  50183. + dwc_ep->xfer_buff0;
  50184. + dwc_ep->cur_pkt_dma_addr =
  50185. + dwc_ep->dma_addr0;
  50186. + }
  50187. +
  50188. + }
  50189. + dwc_otg_iso_ep_start_frm_transfer(core_if,
  50190. + dwc_ep);
  50191. + }
  50192. + }
  50193. + } else {
  50194. + set_current_pkt_info(core_if, dwc_ep);
  50195. + if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
  50196. + is_last = 1;
  50197. + dwc_ep->cur_pkt = 0;
  50198. + dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1;
  50199. + if (dwc_ep->proc_buf_num) {
  50200. + dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff1;
  50201. + dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr1;
  50202. + } else {
  50203. + dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff0;
  50204. + dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr0;
  50205. + }
  50206. +
  50207. + }
  50208. + dwc_otg_iso_ep_start_frm_transfer(core_if, dwc_ep);
  50209. + }
  50210. + if (is_last)
  50211. + dwc_otg_iso_buffer_done(pcd, ep, ep->iso_req_handle);
  50212. +}
  50213. +#endif /* DWC_EN_ISOC */
  50214. +
  50215. +/**
  50216. + * This function handle BNA interrupt for Non Isochronous EPs
  50217. + *
  50218. + */
  50219. +static void dwc_otg_pcd_handle_noniso_bna(dwc_otg_pcd_ep_t * ep)
  50220. +{
  50221. + dwc_ep_t *dwc_ep = &ep->dwc_ep;
  50222. + volatile uint32_t *addr;
  50223. + depctl_data_t depctl = {.d32 = 0 };
  50224. + dwc_otg_pcd_t *pcd = ep->pcd;
  50225. + dwc_otg_dev_dma_desc_t *dma_desc;
  50226. + dev_dma_desc_sts_t sts = {.d32 = 0 };
  50227. + dwc_otg_core_if_t *core_if = ep->pcd->core_if;
  50228. + int i, start;
  50229. +
  50230. + if (!dwc_ep->desc_cnt)
  50231. + DWC_WARN("Ep%d %s Descriptor count = %d \n", dwc_ep->num,
  50232. + (dwc_ep->is_in ? "IN" : "OUT"), dwc_ep->desc_cnt);
  50233. +
  50234. + if (core_if->core_params->cont_on_bna && !dwc_ep->is_in
  50235. + && dwc_ep->type != DWC_OTG_EP_TYPE_CONTROL) {
  50236. + uint32_t doepdma;
  50237. + dwc_otg_dev_out_ep_regs_t *out_regs =
  50238. + core_if->dev_if->out_ep_regs[dwc_ep->num];
  50239. + doepdma = DWC_READ_REG32(&(out_regs->doepdma));
  50240. + start = (doepdma - dwc_ep->dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t);
  50241. + dma_desc = &(dwc_ep->desc_addr[start]);
  50242. + } else {
  50243. + start = 0;
  50244. + dma_desc = dwc_ep->desc_addr;
  50245. + }
  50246. +
  50247. +
  50248. + for (i = start; i < dwc_ep->desc_cnt; ++i, ++dma_desc) {
  50249. + sts.d32 = dma_desc->status.d32;
  50250. + sts.b.bs = BS_HOST_READY;
  50251. + dma_desc->status.d32 = sts.d32;
  50252. + }
  50253. +
  50254. + if (dwc_ep->is_in == 0) {
  50255. + addr =
  50256. + &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]->
  50257. + doepctl;
  50258. + } else {
  50259. + addr =
  50260. + &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl;
  50261. + }
  50262. + depctl.b.epena = 1;
  50263. + depctl.b.cnak = 1;
  50264. + DWC_MODIFY_REG32(addr, 0, depctl.d32);
  50265. +}
  50266. +
  50267. +/**
  50268. + * This function handles EP0 Control transfers.
  50269. + *
  50270. + * The state of the control transfers are tracked in
  50271. + * <code>ep0state</code>.
  50272. + */
  50273. +static void handle_ep0(dwc_otg_pcd_t * pcd)
  50274. +{
  50275. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  50276. + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0;
  50277. + dev_dma_desc_sts_t desc_sts;
  50278. + deptsiz0_data_t deptsiz;
  50279. + uint32_t byte_count;
  50280. +
  50281. +#ifdef DEBUG_EP0
  50282. + DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
  50283. + print_ep0_state(pcd);
  50284. +#endif
  50285. +
  50286. +// DWC_PRINTF("HANDLE EP0\n");
  50287. +
  50288. + switch (pcd->ep0state) {
  50289. + case EP0_DISCONNECT:
  50290. + break;
  50291. +
  50292. + case EP0_IDLE:
  50293. + pcd->request_config = 0;
  50294. +
  50295. + pcd_setup(pcd);
  50296. + break;
  50297. +
  50298. + case EP0_IN_DATA_PHASE:
  50299. +#ifdef DEBUG_EP0
  50300. + DWC_DEBUGPL(DBG_PCD, "DATA_IN EP%d-%s: type=%d, mps=%d\n",
  50301. + ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),
  50302. + ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);
  50303. +#endif
  50304. +
  50305. + if (core_if->dma_enable != 0) {
  50306. + /*
  50307. + * For EP0 we can only program 1 packet at a time so we
  50308. + * need to do the make calculations after each complete.
  50309. + * Call write_packet to make the calculations, as in
  50310. + * slave mode, and use those values to determine if we
  50311. + * can complete.
  50312. + */
  50313. + if (core_if->dma_desc_enable == 0) {
  50314. + deptsiz.d32 =
  50315. + DWC_READ_REG32(&core_if->
  50316. + dev_if->in_ep_regs[0]->
  50317. + dieptsiz);
  50318. + byte_count =
  50319. + ep0->dwc_ep.xfer_len - deptsiz.b.xfersize;
  50320. + } else {
  50321. + desc_sts =
  50322. + core_if->dev_if->in_desc_addr->status;
  50323. + byte_count =
  50324. + ep0->dwc_ep.xfer_len - desc_sts.b.bytes;
  50325. + }
  50326. + ep0->dwc_ep.xfer_count += byte_count;
  50327. + ep0->dwc_ep.xfer_buff += byte_count;
  50328. + ep0->dwc_ep.dma_addr += byte_count;
  50329. + }
  50330. + if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {
  50331. + dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
  50332. + &ep0->dwc_ep);
  50333. + DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
  50334. + } else if (ep0->dwc_ep.sent_zlp) {
  50335. + dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
  50336. + &ep0->dwc_ep);
  50337. + ep0->dwc_ep.sent_zlp = 0;
  50338. + DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n");
  50339. + } else {
  50340. + ep0_complete_request(ep0);
  50341. + DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");
  50342. + }
  50343. + break;
  50344. + case EP0_OUT_DATA_PHASE:
  50345. +#ifdef DEBUG_EP0
  50346. + DWC_DEBUGPL(DBG_PCD, "DATA_OUT EP%d-%s: type=%d, mps=%d\n",
  50347. + ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"),
  50348. + ep0->dwc_ep.type, ep0->dwc_ep.maxpacket);
  50349. +#endif
  50350. + if (core_if->dma_enable != 0) {
  50351. + if (core_if->dma_desc_enable == 0) {
  50352. + deptsiz.d32 =
  50353. + DWC_READ_REG32(&core_if->
  50354. + dev_if->out_ep_regs[0]->
  50355. + doeptsiz);
  50356. + byte_count =
  50357. + ep0->dwc_ep.maxpacket - deptsiz.b.xfersize;
  50358. + } else {
  50359. + desc_sts =
  50360. + core_if->dev_if->out_desc_addr->status;
  50361. + byte_count =
  50362. + ep0->dwc_ep.maxpacket - desc_sts.b.bytes;
  50363. + }
  50364. + ep0->dwc_ep.xfer_count += byte_count;
  50365. + ep0->dwc_ep.xfer_buff += byte_count;
  50366. + ep0->dwc_ep.dma_addr += byte_count;
  50367. + }
  50368. + if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {
  50369. + dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
  50370. + &ep0->dwc_ep);
  50371. + DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n");
  50372. + } else if (ep0->dwc_ep.sent_zlp) {
  50373. + dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd),
  50374. + &ep0->dwc_ep);
  50375. + ep0->dwc_ep.sent_zlp = 0;
  50376. + DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n");
  50377. + } else {
  50378. + ep0_complete_request(ep0);
  50379. + DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n");
  50380. + }
  50381. + break;
  50382. +
  50383. + case EP0_IN_STATUS_PHASE:
  50384. + case EP0_OUT_STATUS_PHASE:
  50385. + DWC_DEBUGPL(DBG_PCD, "CASE: EP0_STATUS\n");
  50386. + ep0_complete_request(ep0);
  50387. + pcd->ep0state = EP0_IDLE;
  50388. + ep0->stopped = 1;
  50389. + ep0->dwc_ep.is_in = 0; /* OUT for next SETUP */
  50390. +
  50391. + /* Prepare for more SETUP Packets */
  50392. + if (core_if->dma_enable) {
  50393. + ep0_out_start(core_if, pcd);
  50394. + }
  50395. + break;
  50396. +
  50397. + case EP0_STALL:
  50398. + DWC_ERROR("EP0 STALLed, should not get here pcd_setup()\n");
  50399. + break;
  50400. + }
  50401. +#ifdef DEBUG_EP0
  50402. + print_ep0_state(pcd);
  50403. +#endif
  50404. +}
  50405. +
  50406. +/**
  50407. + * Restart transfer
  50408. + */
  50409. +static void restart_transfer(dwc_otg_pcd_t * pcd, const uint32_t epnum)
  50410. +{
  50411. + dwc_otg_core_if_t *core_if;
  50412. + dwc_otg_dev_if_t *dev_if;
  50413. + deptsiz_data_t dieptsiz = {.d32 = 0 };
  50414. + dwc_otg_pcd_ep_t *ep;
  50415. +
  50416. + ep = get_in_ep(pcd, epnum);
  50417. +
  50418. +#ifdef DWC_EN_ISOC
  50419. + if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
  50420. + return;
  50421. + }
  50422. +#endif /* DWC_EN_ISOC */
  50423. +
  50424. + core_if = GET_CORE_IF(pcd);
  50425. + dev_if = core_if->dev_if;
  50426. +
  50427. + dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz);
  50428. +
  50429. + DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x xfer_len=%0x"
  50430. + " stopped=%d\n", ep->dwc_ep.xfer_buff,
  50431. + ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len, ep->stopped);
  50432. + /*
  50433. + * If xfersize is 0 and pktcnt in not 0, resend the last packet.
  50434. + */
  50435. + if (dieptsiz.b.pktcnt && dieptsiz.b.xfersize == 0 &&
  50436. + ep->dwc_ep.start_xfer_buff != 0) {
  50437. + if (ep->dwc_ep.total_len <= ep->dwc_ep.maxpacket) {
  50438. + ep->dwc_ep.xfer_count = 0;
  50439. + ep->dwc_ep.xfer_buff = ep->dwc_ep.start_xfer_buff;
  50440. + ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;
  50441. + } else {
  50442. + ep->dwc_ep.xfer_count -= ep->dwc_ep.maxpacket;
  50443. + /* convert packet size to dwords. */
  50444. + ep->dwc_ep.xfer_buff -= ep->dwc_ep.maxpacket;
  50445. + ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count;
  50446. + }
  50447. + ep->stopped = 0;
  50448. + DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x "
  50449. + "xfer_len=%0x stopped=%d\n",
  50450. + ep->dwc_ep.xfer_buff,
  50451. + ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len,
  50452. + ep->stopped);
  50453. + if (epnum == 0) {
  50454. + dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep);
  50455. + } else {
  50456. + dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep);
  50457. + }
  50458. + }
  50459. +}
  50460. +
  50461. +/*
  50462. + * This function create new nextep sequnce based on Learn Queue.
  50463. + *
  50464. + * @param core_if Programming view of DWC_otg controller
  50465. + */
  50466. +void predict_nextep_seq( dwc_otg_core_if_t * core_if)
  50467. +{
  50468. + dwc_otg_device_global_regs_t *dev_global_regs =
  50469. + core_if->dev_if->dev_global_regs;
  50470. + const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth;
  50471. + /* Number of Token Queue Registers */
  50472. + const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8;
  50473. + dtknq1_data_t dtknqr1;
  50474. + uint32_t in_tkn_epnums[4];
  50475. + uint8_t seqnum[MAX_EPS_CHANNELS];
  50476. + uint8_t intkn_seq[TOKEN_Q_DEPTH];
  50477. + grstctl_t resetctl = {.d32 = 0 };
  50478. + uint8_t temp;
  50479. + int ndx = 0;
  50480. + int start = 0;
  50481. + int end = 0;
  50482. + int sort_done = 0;
  50483. + int i = 0;
  50484. + volatile uint32_t *addr = &dev_global_regs->dtknqr1;
  50485. +
  50486. +
  50487. + DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH);
  50488. +
  50489. + /* Read the DTKNQ Registers */
  50490. + for (i = 0; i < DTKNQ_REG_CNT; i++) {
  50491. + in_tkn_epnums[i] = DWC_READ_REG32(addr);
  50492. + DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1,
  50493. + in_tkn_epnums[i]);
  50494. + if (addr == &dev_global_regs->dvbusdis) {
  50495. + addr = &dev_global_regs->dtknqr3_dthrctl;
  50496. + } else {
  50497. + ++addr;
  50498. + }
  50499. +
  50500. + }
  50501. +
  50502. + /* Copy the DTKNQR1 data to the bit field. */
  50503. + dtknqr1.d32 = in_tkn_epnums[0];
  50504. + if (dtknqr1.b.wrap_bit) {
  50505. + ndx = dtknqr1.b.intknwptr;
  50506. + end = ndx -1;
  50507. + if (end < 0)
  50508. + end = TOKEN_Q_DEPTH -1;
  50509. + } else {
  50510. + ndx = 0;
  50511. + end = dtknqr1.b.intknwptr -1;
  50512. + if (end < 0)
  50513. + end = 0;
  50514. + }
  50515. + start = ndx;
  50516. +
  50517. + /* Fill seqnum[] by initial values: EP number + 31 */
  50518. + for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
  50519. + seqnum[i] = i +31;
  50520. + }
  50521. +
  50522. + /* Fill intkn_seq[] from in_tkn_epnums[0] */
  50523. + for (i=0; i < 6; i++)
  50524. + intkn_seq[i] = (in_tkn_epnums[0] >> ((7-i) * 4)) & 0xf;
  50525. +
  50526. + if (TOKEN_Q_DEPTH > 6) {
  50527. + /* Fill intkn_seq[] from in_tkn_epnums[1] */
  50528. + for (i=6; i < 14; i++)
  50529. + intkn_seq[i] =
  50530. + (in_tkn_epnums[1] >> ((7 - (i - 6)) * 4)) & 0xf;
  50531. + }
  50532. +
  50533. + if (TOKEN_Q_DEPTH > 14) {
  50534. + /* Fill intkn_seq[] from in_tkn_epnums[1] */
  50535. + for (i=14; i < 22; i++)
  50536. + intkn_seq[i] =
  50537. + (in_tkn_epnums[2] >> ((7 - (i - 14)) * 4)) & 0xf;
  50538. + }
  50539. +
  50540. + if (TOKEN_Q_DEPTH > 22) {
  50541. + /* Fill intkn_seq[] from in_tkn_epnums[1] */
  50542. + for (i=22; i < 30; i++)
  50543. + intkn_seq[i] =
  50544. + (in_tkn_epnums[3] >> ((7 - (i - 22)) * 4)) & 0xf;
  50545. + }
  50546. +
  50547. + DWC_DEBUGPL(DBG_PCDV, "%s start=%d end=%d intkn_seq[]:\n", __func__,
  50548. + start, end);
  50549. + for (i=0; i<TOKEN_Q_DEPTH; i++)
  50550. + DWC_DEBUGPL(DBG_PCDV,"%d\n", intkn_seq[i]);
  50551. +
  50552. + /* Update seqnum based on intkn_seq[] */
  50553. + i = 0;
  50554. + do {
  50555. + seqnum[intkn_seq[ndx]] = i;
  50556. + ndx++;
  50557. + i++;
  50558. + if (ndx == TOKEN_Q_DEPTH)
  50559. + ndx = 0;
  50560. + } while ( i < TOKEN_Q_DEPTH );
  50561. +
  50562. + /* Mark non active EP's in seqnum[] by 0xff */
  50563. + for (i=0; i<=core_if->dev_if->num_in_eps; i++) {
  50564. + if (core_if->nextep_seq[i] == 0xff )
  50565. + seqnum[i] = 0xff;
  50566. + }
  50567. +
  50568. + /* Sort seqnum[] */
  50569. + sort_done = 0;
  50570. + while (!sort_done) {
  50571. + sort_done = 1;
  50572. + for (i=0; i<core_if->dev_if->num_in_eps; i++) {
  50573. + if (seqnum[i] > seqnum[i+1]) {
  50574. + temp = seqnum[i];
  50575. + seqnum[i] = seqnum[i+1];
  50576. + seqnum[i+1] = temp;
  50577. + sort_done = 0;
  50578. + }
  50579. + }
  50580. + }
  50581. +
  50582. + ndx = start + seqnum[0];
  50583. + if (ndx >= TOKEN_Q_DEPTH)
  50584. + ndx = ndx % TOKEN_Q_DEPTH;
  50585. + core_if->first_in_nextep_seq = intkn_seq[ndx];
  50586. +
  50587. + /* Update seqnum[] by EP numbers */
  50588. + for (i=0; i<=core_if->dev_if->num_in_eps; i++) {
  50589. + ndx = start + i;
  50590. + if (seqnum[i] < 31) {
  50591. + ndx = start + seqnum[i];
  50592. + if (ndx >= TOKEN_Q_DEPTH)
  50593. + ndx = ndx % TOKEN_Q_DEPTH;
  50594. + seqnum[i] = intkn_seq[ndx];
  50595. + } else {
  50596. + if (seqnum[i] < 0xff) {
  50597. + seqnum[i] = seqnum[i] - 31;
  50598. + } else {
  50599. + break;
  50600. + }
  50601. + }
  50602. + }
  50603. +
  50604. + /* Update nextep_seq[] based on seqnum[] */
  50605. + for (i=0; i<core_if->dev_if->num_in_eps; i++) {
  50606. + if (seqnum[i] != 0xff) {
  50607. + if (seqnum[i+1] != 0xff) {
  50608. + core_if->nextep_seq[seqnum[i]] = seqnum[i+1];
  50609. + } else {
  50610. + core_if->nextep_seq[seqnum[i]] = core_if->first_in_nextep_seq;
  50611. + break;
  50612. + }
  50613. + } else {
  50614. + break;
  50615. + }
  50616. + }
  50617. +
  50618. + DWC_DEBUGPL(DBG_PCDV, "%s first_in_nextep_seq= %2d; nextep_seq[]:\n",
  50619. + __func__, core_if->first_in_nextep_seq);
  50620. + for (i=0; i <= core_if->dev_if->num_in_eps; i++) {
  50621. + DWC_DEBUGPL(DBG_PCDV,"%2d\n", core_if->nextep_seq[i]);
  50622. + }
  50623. +
  50624. + /* Flush the Learning Queue */
  50625. + resetctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->grstctl);
  50626. + resetctl.b.intknqflsh = 1;
  50627. + DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
  50628. +
  50629. +
  50630. +}
  50631. +
  50632. +/**
  50633. + * handle the IN EP disable interrupt.
  50634. + */
  50635. +static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t * pcd,
  50636. + const uint32_t epnum)
  50637. +{
  50638. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  50639. + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
  50640. + deptsiz_data_t dieptsiz = {.d32 = 0 };
  50641. + dctl_data_t dctl = {.d32 = 0 };
  50642. + dwc_otg_pcd_ep_t *ep;
  50643. + dwc_ep_t *dwc_ep;
  50644. + gintmsk_data_t gintmsk_data;
  50645. + depctl_data_t depctl;
  50646. + uint32_t diepdma;
  50647. + uint32_t remain_to_transfer = 0;
  50648. + uint8_t i;
  50649. + uint32_t xfer_size;
  50650. +
  50651. + ep = get_in_ep(pcd, epnum);
  50652. + dwc_ep = &ep->dwc_ep;
  50653. +
  50654. + if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
  50655. + dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
  50656. + complete_ep(ep);
  50657. + return;
  50658. + }
  50659. +
  50660. + DWC_DEBUGPL(DBG_PCD, "diepctl%d=%0x\n", epnum,
  50661. + DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl));
  50662. + dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz);
  50663. + depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
  50664. +
  50665. + DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
  50666. + dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
  50667. +
  50668. + if ((core_if->start_predict == 0) || (depctl.b.eptype & 1)) {
  50669. + if (ep->stopped) {
  50670. + if (core_if->en_multiple_tx_fifo)
  50671. + /* Flush the Tx FIFO */
  50672. + dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num);
  50673. + /* Clear the Global IN NP NAK */
  50674. + dctl.d32 = 0;
  50675. + dctl.b.cgnpinnak = 1;
  50676. + DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
  50677. + /* Restart the transaction */
  50678. + if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {
  50679. + restart_transfer(pcd, epnum);
  50680. + }
  50681. + } else {
  50682. + /* Restart the transaction */
  50683. + if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) {
  50684. + restart_transfer(pcd, epnum);
  50685. + }
  50686. + DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n");
  50687. + }
  50688. + return;
  50689. + }
  50690. +
  50691. + if (core_if->start_predict > 2) { // NP IN EP
  50692. + core_if->start_predict--;
  50693. + return;
  50694. + }
  50695. +
  50696. + core_if->start_predict--;
  50697. +
  50698. + if (core_if->start_predict == 1) { // All NP IN Ep's disabled now
  50699. +
  50700. + predict_nextep_seq(core_if);
  50701. +
  50702. + /* Update all active IN EP's NextEP field based of nextep_seq[] */
  50703. + for ( i = 0; i <= core_if->dev_if->num_in_eps; i++) {
  50704. + depctl.d32 =
  50705. + DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
  50706. + if (core_if->nextep_seq[i] != 0xff) { // Active NP IN EP
  50707. + depctl.b.nextep = core_if->nextep_seq[i];
  50708. + DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
  50709. + }
  50710. + }
  50711. + /* Flush Shared NP TxFIFO */
  50712. + dwc_otg_flush_tx_fifo(core_if, 0);
  50713. + /* Rewind buffers */
  50714. + if (!core_if->dma_desc_enable) {
  50715. + i = core_if->first_in_nextep_seq;
  50716. + do {
  50717. + ep = get_in_ep(pcd, i);
  50718. + dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
  50719. + xfer_size = ep->dwc_ep.total_len - ep->dwc_ep.xfer_count;
  50720. + if (xfer_size > ep->dwc_ep.maxxfer)
  50721. + xfer_size = ep->dwc_ep.maxxfer;
  50722. + depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
  50723. + if (dieptsiz.b.pktcnt != 0) {
  50724. + if (xfer_size == 0) {
  50725. + remain_to_transfer = 0;
  50726. + } else {
  50727. + if ((xfer_size % ep->dwc_ep.maxpacket) == 0) {
  50728. + remain_to_transfer =
  50729. + dieptsiz.b.pktcnt * ep->dwc_ep.maxpacket;
  50730. + } else {
  50731. + remain_to_transfer = ((dieptsiz.b.pktcnt -1) * ep->dwc_ep.maxpacket)
  50732. + + (xfer_size % ep->dwc_ep.maxpacket);
  50733. + }
  50734. + }
  50735. + diepdma = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepdma);
  50736. + dieptsiz.b.xfersize = remain_to_transfer;
  50737. + DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, dieptsiz.d32);
  50738. + diepdma = ep->dwc_ep.dma_addr + (xfer_size - remain_to_transfer);
  50739. + DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, diepdma);
  50740. + }
  50741. + i = core_if->nextep_seq[i];
  50742. + } while (i != core_if->first_in_nextep_seq);
  50743. + } else { // dma_desc_enable
  50744. + DWC_PRINTF("%s Learning Queue not supported in DDMA\n", __func__);
  50745. + }
  50746. +
  50747. + /* Restart transfers in predicted sequences */
  50748. + i = core_if->first_in_nextep_seq;
  50749. + do {
  50750. + dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
  50751. + depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
  50752. + if (dieptsiz.b.pktcnt != 0) {
  50753. + depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
  50754. + depctl.b.epena = 1;
  50755. + depctl.b.cnak = 1;
  50756. + DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32);
  50757. + }
  50758. + i = core_if->nextep_seq[i];
  50759. + } while (i != core_if->first_in_nextep_seq);
  50760. +
  50761. + /* Clear the global non-periodic IN NAK handshake */
  50762. + dctl.d32 = 0;
  50763. + dctl.b.cgnpinnak = 1;
  50764. + DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
  50765. +
  50766. + /* Unmask EP Mismatch interrupt */
  50767. + gintmsk_data.d32 = 0;
  50768. + gintmsk_data.b.epmismatch = 1;
  50769. + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk_data.d32);
  50770. +
  50771. + core_if->start_predict = 0;
  50772. +
  50773. + }
  50774. +}
  50775. +
  50776. +/**
  50777. + * Handler for the IN EP timeout handshake interrupt.
  50778. + */
  50779. +static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t * pcd,
  50780. + const uint32_t epnum)
  50781. +{
  50782. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  50783. + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
  50784. +
  50785. +#ifdef DEBUG
  50786. + deptsiz_data_t dieptsiz = {.d32 = 0 };
  50787. + uint32_t num = 0;
  50788. +#endif
  50789. + dctl_data_t dctl = {.d32 = 0 };
  50790. + dwc_otg_pcd_ep_t *ep;
  50791. +
  50792. + gintmsk_data_t intr_mask = {.d32 = 0 };
  50793. +
  50794. + ep = get_in_ep(pcd, epnum);
  50795. +
  50796. + /* Disable the NP Tx Fifo Empty Interrrupt */
  50797. + if (!core_if->dma_enable) {
  50798. + intr_mask.b.nptxfempty = 1;
  50799. + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
  50800. + intr_mask.d32, 0);
  50801. + }
  50802. + /** @todo NGS Check EP type.
  50803. + * Implement for Periodic EPs */
  50804. + /*
  50805. + * Non-periodic EP
  50806. + */
  50807. + /* Enable the Global IN NAK Effective Interrupt */
  50808. + intr_mask.b.ginnakeff = 1;
  50809. + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32);
  50810. +
  50811. + /* Set Global IN NAK */
  50812. + dctl.b.sgnpinnak = 1;
  50813. + DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32);
  50814. +
  50815. + ep->stopped = 1;
  50816. +
  50817. +#ifdef DEBUG
  50818. + dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[num]->dieptsiz);
  50819. + DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n",
  50820. + dieptsiz.b.pktcnt, dieptsiz.b.xfersize);
  50821. +#endif
  50822. +
  50823. +#ifdef DISABLE_PERIODIC_EP
  50824. + /*
  50825. + * Set the NAK bit for this EP to
  50826. + * start the disable process.
  50827. + */
  50828. + diepctl.d32 = 0;
  50829. + diepctl.b.snak = 1;
  50830. + DWC_MODIFY_REG32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32,
  50831. + diepctl.d32);
  50832. + ep->disabling = 1;
  50833. + ep->stopped = 1;
  50834. +#endif
  50835. +}
  50836. +
  50837. +/**
  50838. + * Handler for the IN EP NAK interrupt.
  50839. + */
  50840. +static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t * pcd,
  50841. + const uint32_t epnum)
  50842. +{
  50843. + /** @todo implement ISR */
  50844. + dwc_otg_core_if_t *core_if;
  50845. + diepmsk_data_t intr_mask = {.d32 = 0 };
  50846. +
  50847. + DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "IN EP NAK");
  50848. + core_if = GET_CORE_IF(pcd);
  50849. + intr_mask.b.nak = 1;
  50850. +
  50851. + if (core_if->multiproc_int_enable) {
  50852. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
  50853. + diepeachintmsk[epnum], intr_mask.d32, 0);
  50854. + } else {
  50855. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->diepmsk,
  50856. + intr_mask.d32, 0);
  50857. + }
  50858. +
  50859. + return 1;
  50860. +}
  50861. +
  50862. +/**
  50863. + * Handler for the OUT EP Babble interrupt.
  50864. + */
  50865. +static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t * pcd,
  50866. + const uint32_t epnum)
  50867. +{
  50868. + /** @todo implement ISR */
  50869. + dwc_otg_core_if_t *core_if;
  50870. + doepmsk_data_t intr_mask = {.d32 = 0 };
  50871. +
  50872. + DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
  50873. + "OUT EP Babble");
  50874. + core_if = GET_CORE_IF(pcd);
  50875. + intr_mask.b.babble = 1;
  50876. +
  50877. + if (core_if->multiproc_int_enable) {
  50878. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
  50879. + doepeachintmsk[epnum], intr_mask.d32, 0);
  50880. + } else {
  50881. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
  50882. + intr_mask.d32, 0);
  50883. + }
  50884. +
  50885. + return 1;
  50886. +}
  50887. +
  50888. +/**
  50889. + * Handler for the OUT EP NAK interrupt.
  50890. + */
  50891. +static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd,
  50892. + const uint32_t epnum)
  50893. +{
  50894. + /** @todo implement ISR */
  50895. + dwc_otg_core_if_t *core_if;
  50896. + doepmsk_data_t intr_mask = {.d32 = 0 };
  50897. +
  50898. + DWC_DEBUGPL(DBG_ANY, "INTERRUPT Handler not implemented for %s\n", "OUT EP NAK");
  50899. + core_if = GET_CORE_IF(pcd);
  50900. + intr_mask.b.nak = 1;
  50901. +
  50902. + if (core_if->multiproc_int_enable) {
  50903. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
  50904. + doepeachintmsk[epnum], intr_mask.d32, 0);
  50905. + } else {
  50906. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
  50907. + intr_mask.d32, 0);
  50908. + }
  50909. +
  50910. + return 1;
  50911. +}
  50912. +
  50913. +/**
  50914. + * Handler for the OUT EP NYET interrupt.
  50915. + */
  50916. +static inline int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t * pcd,
  50917. + const uint32_t epnum)
  50918. +{
  50919. + /** @todo implement ISR */
  50920. + dwc_otg_core_if_t *core_if;
  50921. + doepmsk_data_t intr_mask = {.d32 = 0 };
  50922. +
  50923. + DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NYET");
  50924. + core_if = GET_CORE_IF(pcd);
  50925. + intr_mask.b.nyet = 1;
  50926. +
  50927. + if (core_if->multiproc_int_enable) {
  50928. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->
  50929. + doepeachintmsk[epnum], intr_mask.d32, 0);
  50930. + } else {
  50931. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
  50932. + intr_mask.d32, 0);
  50933. + }
  50934. +
  50935. + return 1;
  50936. +}
  50937. +
  50938. +/**
  50939. + * This interrupt indicates that an IN EP has a pending Interrupt.
  50940. + * The sequence for handling the IN EP interrupt is shown below:
  50941. + * -# Read the Device All Endpoint Interrupt register
  50942. + * -# Repeat the following for each IN EP interrupt bit set (from
  50943. + * LSB to MSB).
  50944. + * -# Read the Device Endpoint Interrupt (DIEPINTn) register
  50945. + * -# If "Transfer Complete" call the request complete function
  50946. + * -# If "Endpoint Disabled" complete the EP disable procedure.
  50947. + * -# If "AHB Error Interrupt" log error
  50948. + * -# If "Time-out Handshake" log error
  50949. + * -# If "IN Token Received when TxFIFO Empty" write packet to Tx
  50950. + * FIFO.
  50951. + * -# If "IN Token EP Mismatch" (disable, this is handled by EP
  50952. + * Mismatch Interrupt)
  50953. + */
  50954. +static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd)
  50955. +{
  50956. +#define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \
  50957. +do { \
  50958. + diepint_data_t diepint = {.d32=0}; \
  50959. + diepint.b.__intr = 1; \
  50960. + DWC_WRITE_REG32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \
  50961. + diepint.d32); \
  50962. +} while (0)
  50963. +
  50964. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  50965. + dwc_otg_dev_if_t *dev_if = core_if->dev_if;
  50966. + diepint_data_t diepint = {.d32 = 0 };
  50967. + depctl_data_t depctl = {.d32 = 0 };
  50968. + uint32_t ep_intr;
  50969. + uint32_t epnum = 0;
  50970. + dwc_otg_pcd_ep_t *ep;
  50971. + dwc_ep_t *dwc_ep;
  50972. + gintmsk_data_t intr_mask = {.d32 = 0 };
  50973. +
  50974. + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, pcd);
  50975. +
  50976. + /* Read in the device interrupt bits */
  50977. + ep_intr = dwc_otg_read_dev_all_in_ep_intr(core_if);
  50978. +
  50979. + /* Service the Device IN interrupts for each endpoint */
  50980. + while (ep_intr) {
  50981. + if (ep_intr & 0x1) {
  50982. + uint32_t empty_msk;
  50983. + /* Get EP pointer */
  50984. + ep = get_in_ep(pcd, epnum);
  50985. + dwc_ep = &ep->dwc_ep;
  50986. +
  50987. + depctl.d32 =
  50988. + DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
  50989. + empty_msk =
  50990. + DWC_READ_REG32(&dev_if->
  50991. + dev_global_regs->dtknqr4_fifoemptymsk);
  50992. +
  50993. + DWC_DEBUGPL(DBG_PCDV,
  50994. + "IN EP INTERRUPT - %d\nepmty_msk - %8x diepctl - %8x\n",
  50995. + epnum, empty_msk, depctl.d32);
  50996. +
  50997. + DWC_DEBUGPL(DBG_PCD,
  50998. + "EP%d-%s: type=%d, mps=%d\n",
  50999. + dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),
  51000. + dwc_ep->type, dwc_ep->maxpacket);
  51001. +
  51002. + diepint.d32 =
  51003. + dwc_otg_read_dev_in_ep_intr(core_if, dwc_ep);
  51004. +
  51005. + DWC_DEBUGPL(DBG_PCDV,
  51006. + "EP %d Interrupt Register - 0x%x\n", epnum,
  51007. + diepint.d32);
  51008. + /* Transfer complete */
  51009. + if (diepint.b.xfercompl) {
  51010. + /* Disable the NP Tx FIFO Empty
  51011. + * Interrupt */
  51012. + if (core_if->en_multiple_tx_fifo == 0) {
  51013. + intr_mask.b.nptxfempty = 1;
  51014. + DWC_MODIFY_REG32
  51015. + (&core_if->core_global_regs->gintmsk,
  51016. + intr_mask.d32, 0);
  51017. + } else {
  51018. + /* Disable the Tx FIFO Empty Interrupt for this EP */
  51019. + uint32_t fifoemptymsk =
  51020. + 0x1 << dwc_ep->num;
  51021. + DWC_MODIFY_REG32(&core_if->
  51022. + dev_if->dev_global_regs->dtknqr4_fifoemptymsk,
  51023. + fifoemptymsk, 0);
  51024. + }
  51025. + /* Clear the bit in DIEPINTn for this interrupt */
  51026. + CLEAR_IN_EP_INTR(core_if, epnum, xfercompl);
  51027. +
  51028. + /* Complete the transfer */
  51029. + if (epnum == 0) {
  51030. + handle_ep0(pcd);
  51031. + }
  51032. +#ifdef DWC_EN_ISOC
  51033. + else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
  51034. + if (!ep->stopped)
  51035. + complete_iso_ep(pcd, ep);
  51036. + }
  51037. +#endif /* DWC_EN_ISOC */
  51038. +#ifdef DWC_UTE_PER_IO
  51039. + else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
  51040. + if (!ep->stopped)
  51041. + complete_xiso_ep(ep);
  51042. + }
  51043. +#endif /* DWC_UTE_PER_IO */
  51044. + else {
  51045. + if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC &&
  51046. + dwc_ep->bInterval > 1) {
  51047. + dwc_ep->frame_num += dwc_ep->bInterval;
  51048. + if (dwc_ep->frame_num > 0x3FFF)
  51049. + {
  51050. + dwc_ep->frm_overrun = 1;
  51051. + dwc_ep->frame_num &= 0x3FFF;
  51052. + } else
  51053. + dwc_ep->frm_overrun = 0;
  51054. + }
  51055. + complete_ep(ep);
  51056. + if(diepint.b.nak)
  51057. + CLEAR_IN_EP_INTR(core_if, epnum, nak);
  51058. + }
  51059. + }
  51060. + /* Endpoint disable */
  51061. + if (diepint.b.epdisabled) {
  51062. + DWC_DEBUGPL(DBG_ANY, "EP%d IN disabled\n",
  51063. + epnum);
  51064. + handle_in_ep_disable_intr(pcd, epnum);
  51065. +
  51066. + /* Clear the bit in DIEPINTn for this interrupt */
  51067. + CLEAR_IN_EP_INTR(core_if, epnum, epdisabled);
  51068. + }
  51069. + /* AHB Error */
  51070. + if (diepint.b.ahberr) {
  51071. + DWC_ERROR("EP%d IN AHB Error\n", epnum);
  51072. + /* Clear the bit in DIEPINTn for this interrupt */
  51073. + CLEAR_IN_EP_INTR(core_if, epnum, ahberr);
  51074. + }
  51075. + /* TimeOUT Handshake (non-ISOC IN EPs) */
  51076. + if (diepint.b.timeout) {
  51077. + DWC_ERROR("EP%d IN Time-out\n", epnum);
  51078. + handle_in_ep_timeout_intr(pcd, epnum);
  51079. +
  51080. + CLEAR_IN_EP_INTR(core_if, epnum, timeout);
  51081. + }
  51082. + /** IN Token received with TxF Empty */
  51083. + if (diepint.b.intktxfemp) {
  51084. + DWC_DEBUGPL(DBG_ANY,
  51085. + "EP%d IN TKN TxFifo Empty\n",
  51086. + epnum);
  51087. + if (!ep->stopped && epnum != 0) {
  51088. +
  51089. + diepmsk_data_t diepmsk = {.d32 = 0 };
  51090. + diepmsk.b.intktxfemp = 1;
  51091. +
  51092. + if (core_if->multiproc_int_enable) {
  51093. + DWC_MODIFY_REG32
  51094. + (&dev_if->dev_global_regs->diepeachintmsk
  51095. + [epnum], diepmsk.d32, 0);
  51096. + } else {
  51097. + DWC_MODIFY_REG32
  51098. + (&dev_if->dev_global_regs->diepmsk,
  51099. + diepmsk.d32, 0);
  51100. + }
  51101. + } else if (core_if->dma_desc_enable
  51102. + && epnum == 0
  51103. + && pcd->ep0state ==
  51104. + EP0_OUT_STATUS_PHASE) {
  51105. + // EP0 IN set STALL
  51106. + depctl.d32 =
  51107. + DWC_READ_REG32(&dev_if->in_ep_regs
  51108. + [epnum]->diepctl);
  51109. +
  51110. + /* set the disable and stall bits */
  51111. + if (depctl.b.epena) {
  51112. + depctl.b.epdis = 1;
  51113. + }
  51114. + depctl.b.stall = 1;
  51115. + DWC_WRITE_REG32(&dev_if->in_ep_regs
  51116. + [epnum]->diepctl,
  51117. + depctl.d32);
  51118. + }
  51119. + CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp);
  51120. + }
  51121. + /** IN Token Received with EP mismatch */
  51122. + if (diepint.b.intknepmis) {
  51123. + DWC_DEBUGPL(DBG_ANY,
  51124. + "EP%d IN TKN EP Mismatch\n", epnum);
  51125. + CLEAR_IN_EP_INTR(core_if, epnum, intknepmis);
  51126. + }
  51127. + /** IN Endpoint NAK Effective */
  51128. + if (diepint.b.inepnakeff) {
  51129. + DWC_DEBUGPL(DBG_ANY,
  51130. + "EP%d IN EP NAK Effective\n",
  51131. + epnum);
  51132. + /* Periodic EP */
  51133. + if (ep->disabling) {
  51134. + depctl.d32 = 0;
  51135. + depctl.b.snak = 1;
  51136. + depctl.b.epdis = 1;
  51137. + DWC_MODIFY_REG32(&dev_if->in_ep_regs
  51138. + [epnum]->diepctl,
  51139. + depctl.d32,
  51140. + depctl.d32);
  51141. + }
  51142. + CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff);
  51143. +
  51144. + }
  51145. +
  51146. + /** IN EP Tx FIFO Empty Intr */
  51147. + if (diepint.b.emptyintr) {
  51148. + DWC_DEBUGPL(DBG_ANY,
  51149. + "EP%d Tx FIFO Empty Intr \n",
  51150. + epnum);
  51151. + write_empty_tx_fifo(pcd, epnum);
  51152. +
  51153. + CLEAR_IN_EP_INTR(core_if, epnum, emptyintr);
  51154. +
  51155. + }
  51156. +
  51157. + /** IN EP BNA Intr */
  51158. + if (diepint.b.bna) {
  51159. + CLEAR_IN_EP_INTR(core_if, epnum, bna);
  51160. + if (core_if->dma_desc_enable) {
  51161. +#ifdef DWC_EN_ISOC
  51162. + if (dwc_ep->type ==
  51163. + DWC_OTG_EP_TYPE_ISOC) {
  51164. + /*
  51165. + * This checking is performed to prevent first "false" BNA
  51166. + * handling occuring right after reconnect
  51167. + */
  51168. + if (dwc_ep->next_frame !=
  51169. + 0xffffffff)
  51170. + dwc_otg_pcd_handle_iso_bna(ep);
  51171. + } else
  51172. +#endif /* DWC_EN_ISOC */
  51173. + {
  51174. + dwc_otg_pcd_handle_noniso_bna(ep);
  51175. + }
  51176. + }
  51177. + }
  51178. + /* NAK Interrutp */
  51179. + if (diepint.b.nak) {
  51180. + DWC_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n",
  51181. + epnum);
  51182. + if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
  51183. + depctl_data_t depctl;
  51184. + if (ep->dwc_ep.frame_num == 0xFFFFFFFF) {
  51185. + ep->dwc_ep.frame_num = core_if->frame_num;
  51186. + if (ep->dwc_ep.bInterval > 1) {
  51187. + depctl.d32 = 0;
  51188. + depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl);
  51189. + if (ep->dwc_ep.frame_num & 0x1) {
  51190. + depctl.b.setd1pid = 1;
  51191. + depctl.b.setd0pid = 0;
  51192. + } else {
  51193. + depctl.b.setd0pid = 1;
  51194. + depctl.b.setd1pid = 0;
  51195. + }
  51196. + DWC_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepctl, depctl.d32);
  51197. + }
  51198. + start_next_request(ep);
  51199. + }
  51200. + ep->dwc_ep.frame_num += ep->dwc_ep.bInterval;
  51201. + if (dwc_ep->frame_num > 0x3FFF) {
  51202. + dwc_ep->frm_overrun = 1;
  51203. + dwc_ep->frame_num &= 0x3FFF;
  51204. + } else
  51205. + dwc_ep->frm_overrun = 0;
  51206. + }
  51207. +
  51208. + CLEAR_IN_EP_INTR(core_if, epnum, nak);
  51209. + }
  51210. + }
  51211. + epnum++;
  51212. + ep_intr >>= 1;
  51213. + }
  51214. +
  51215. + return 1;
  51216. +#undef CLEAR_IN_EP_INTR
  51217. +}
  51218. +
  51219. +/**
  51220. + * This interrupt indicates that an OUT EP has a pending Interrupt.
  51221. + * The sequence for handling the OUT EP interrupt is shown below:
  51222. + * -# Read the Device All Endpoint Interrupt register
  51223. + * -# Repeat the following for each OUT EP interrupt bit set (from
  51224. + * LSB to MSB).
  51225. + * -# Read the Device Endpoint Interrupt (DOEPINTn) register
  51226. + * -# If "Transfer Complete" call the request complete function
  51227. + * -# If "Endpoint Disabled" complete the EP disable procedure.
  51228. + * -# If "AHB Error Interrupt" log error
  51229. + * -# If "Setup Phase Done" process Setup Packet (See Standard USB
  51230. + * Command Processing)
  51231. + */
  51232. +static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd)
  51233. +{
  51234. +#define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \
  51235. +do { \
  51236. + doepint_data_t doepint = {.d32=0}; \
  51237. + doepint.b.__intr = 1; \
  51238. + DWC_WRITE_REG32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \
  51239. + doepint.d32); \
  51240. +} while (0)
  51241. +
  51242. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  51243. + uint32_t ep_intr;
  51244. + doepint_data_t doepint = {.d32 = 0 };
  51245. + uint32_t epnum = 0;
  51246. + dwc_otg_pcd_ep_t *ep;
  51247. + dwc_ep_t *dwc_ep;
  51248. + dctl_data_t dctl = {.d32 = 0 };
  51249. + gintmsk_data_t gintmsk = {.d32 = 0 };
  51250. +
  51251. +
  51252. + DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__);
  51253. +
  51254. + /* Read in the device interrupt bits */
  51255. + ep_intr = dwc_otg_read_dev_all_out_ep_intr(core_if);
  51256. +
  51257. + while (ep_intr) {
  51258. + if (ep_intr & 0x1) {
  51259. + /* Get EP pointer */
  51260. + ep = get_out_ep(pcd, epnum);
  51261. + dwc_ep = &ep->dwc_ep;
  51262. +
  51263. +#ifdef VERBOSE
  51264. + DWC_DEBUGPL(DBG_PCDV,
  51265. + "EP%d-%s: type=%d, mps=%d\n",
  51266. + dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"),
  51267. + dwc_ep->type, dwc_ep->maxpacket);
  51268. +#endif
  51269. + doepint.d32 =
  51270. + dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep);
  51271. + /* Moved this interrupt upper due to core deffect of asserting
  51272. + * OUT EP 0 xfercompl along with stsphsrcvd in BDMA */
  51273. + if (doepint.b.stsphsercvd) {
  51274. + deptsiz0_data_t deptsiz;
  51275. + CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd);
  51276. + deptsiz.d32 =
  51277. + DWC_READ_REG32(&core_if->dev_if->
  51278. + out_ep_regs[0]->doeptsiz);
  51279. + if (core_if->snpsid >= OTG_CORE_REV_3_00a
  51280. + && core_if->dma_enable
  51281. + && core_if->dma_desc_enable == 0
  51282. + && doepint.b.xfercompl
  51283. + && deptsiz.b.xfersize == 24) {
  51284. + CLEAR_OUT_EP_INTR(core_if, epnum,
  51285. + xfercompl);
  51286. + doepint.b.xfercompl = 0;
  51287. + ep0_out_start(core_if, pcd);
  51288. + }
  51289. + if ((core_if->dma_desc_enable) ||
  51290. + (core_if->dma_enable
  51291. + && core_if->snpsid >=
  51292. + OTG_CORE_REV_3_00a)) {
  51293. + do_setup_in_status_phase(pcd);
  51294. + }
  51295. + }
  51296. + /* Transfer complete */
  51297. + if (doepint.b.xfercompl) {
  51298. +
  51299. + if (epnum == 0) {
  51300. + /* Clear the bit in DOEPINTn for this interrupt */
  51301. + CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl);
  51302. + if (core_if->snpsid >= OTG_CORE_REV_3_00a) {
  51303. + DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n",
  51304. + DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepint),
  51305. + doepint.d32);
  51306. + DWC_DEBUGPL(DBG_PCDV, "DOEPCTL=%x \n",
  51307. + DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepctl));
  51308. +
  51309. + if (core_if->snpsid >= OTG_CORE_REV_3_00a
  51310. + && core_if->dma_enable == 0) {
  51311. + doepint_data_t doepint;
  51312. + doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
  51313. + out_ep_regs[0]->doepint);
  51314. + if (pcd->ep0state == EP0_IDLE && doepint.b.sr) {
  51315. + CLEAR_OUT_EP_INTR(core_if, epnum, sr);
  51316. + goto exit_xfercompl;
  51317. + }
  51318. + }
  51319. + /* In case of DDMA look at SR bit to go to the Data Stage */
  51320. + if (core_if->dma_desc_enable) {
  51321. + dev_dma_desc_sts_t status = {.d32 = 0};
  51322. + if (pcd->ep0state == EP0_IDLE) {
  51323. + status.d32 = core_if->dev_if->setup_desc_addr[core_if->
  51324. + dev_if->setup_desc_index]->status.d32;
  51325. + if(pcd->data_terminated) {
  51326. + pcd->data_terminated = 0;
  51327. + status.d32 = core_if->dev_if->out_desc_addr->status.d32;
  51328. + dwc_memcpy(&pcd->setup_pkt->req, pcd->backup_buf, 8);
  51329. + }
  51330. + if (status.b.sr) {
  51331. + if (doepint.b.setup) {
  51332. + DWC_DEBUGPL(DBG_PCDV, "DMA DESC EP0_IDLE SR=1 setup=1\n");
  51333. + /* Already started data stage, clear setup */
  51334. + CLEAR_OUT_EP_INTR(core_if, epnum, setup);
  51335. + doepint.b.setup = 0;
  51336. + handle_ep0(pcd);
  51337. + /* Prepare for more setup packets */
  51338. + if (pcd->ep0state == EP0_IN_STATUS_PHASE ||
  51339. + pcd->ep0state == EP0_IN_DATA_PHASE) {
  51340. + ep0_out_start(core_if, pcd);
  51341. + }
  51342. +
  51343. + goto exit_xfercompl;
  51344. + } else {
  51345. + /* Prepare for more setup packets */
  51346. + DWC_DEBUGPL(DBG_PCDV,
  51347. + "EP0_IDLE SR=1 setup=0 new setup comes\n");
  51348. + ep0_out_start(core_if, pcd);
  51349. + }
  51350. + }
  51351. + } else {
  51352. + dwc_otg_pcd_request_t *req;
  51353. + dev_dma_desc_sts_t status = {.d32 = 0};
  51354. + diepint_data_t diepint0;
  51355. + diepint0.d32 = DWC_READ_REG32(&core_if->dev_if->
  51356. + in_ep_regs[0]->diepint);
  51357. +
  51358. + if (pcd->ep0state == EP0_STALL || pcd->ep0state == EP0_DISCONNECT) {
  51359. + DWC_ERROR("EP0 is stalled/disconnected\n");
  51360. + }
  51361. +
  51362. + /* Clear IN xfercompl if set */
  51363. + if (diepint0.b.xfercompl && (pcd->ep0state == EP0_IN_STATUS_PHASE
  51364. + || pcd->ep0state == EP0_IN_DATA_PHASE)) {
  51365. + DWC_WRITE_REG32(&core_if->dev_if->
  51366. + in_ep_regs[0]->diepint, diepint0.d32);
  51367. + }
  51368. +
  51369. + status.d32 = core_if->dev_if->setup_desc_addr[core_if->
  51370. + dev_if->setup_desc_index]->status.d32;
  51371. +
  51372. + if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len
  51373. + && (pcd->ep0state == EP0_OUT_DATA_PHASE))
  51374. + status.d32 = core_if->dev_if->out_desc_addr->status.d32;
  51375. + if (pcd->ep0state == EP0_OUT_STATUS_PHASE)
  51376. + status.d32 = status.d32 = core_if->dev_if->
  51377. + out_desc_addr->status.d32;
  51378. +
  51379. + if (status.b.sr) {
  51380. + if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
  51381. + DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n");
  51382. + } else {
  51383. + DWC_DEBUGPL(DBG_PCDV, "complete req!!\n");
  51384. + req = DWC_CIRCLEQ_FIRST(&ep->queue);
  51385. + if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len &&
  51386. + pcd->ep0state == EP0_OUT_DATA_PHASE) {
  51387. + /* Read arrived setup packet from req->buf */
  51388. + dwc_memcpy(&pcd->setup_pkt->req,
  51389. + req->buf + ep->dwc_ep.xfer_count, 8);
  51390. + }
  51391. + req->actual = ep->dwc_ep.xfer_count;
  51392. + dwc_otg_request_done(ep, req, -ECONNRESET);
  51393. + ep->dwc_ep.start_xfer_buff = 0;
  51394. + ep->dwc_ep.xfer_buff = 0;
  51395. + ep->dwc_ep.xfer_len = 0;
  51396. + }
  51397. + pcd->ep0state = EP0_IDLE;
  51398. + if (doepint.b.setup) {
  51399. + DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n");
  51400. + /* Data stage started, clear setup */
  51401. + CLEAR_OUT_EP_INTR(core_if, epnum, setup);
  51402. + doepint.b.setup = 0;
  51403. + handle_ep0(pcd);
  51404. + /* Prepare for setup packets if ep0in was enabled*/
  51405. + if (pcd->ep0state == EP0_IN_STATUS_PHASE) {
  51406. + ep0_out_start(core_if, pcd);
  51407. + }
  51408. +
  51409. + goto exit_xfercompl;
  51410. + } else {
  51411. + /* Prepare for more setup packets */
  51412. + DWC_DEBUGPL(DBG_PCDV,
  51413. + "EP0_IDLE SR=1 setup=0 new setup comes 2\n");
  51414. + ep0_out_start(core_if, pcd);
  51415. + }
  51416. + }
  51417. + }
  51418. + }
  51419. + if (core_if->snpsid >= OTG_CORE_REV_2_94a && core_if->dma_enable
  51420. + && core_if->dma_desc_enable == 0) {
  51421. + doepint_data_t doepint_temp = {.d32 = 0};
  51422. + deptsiz0_data_t doeptsize0 = {.d32 = 0 };
  51423. + doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if->
  51424. + out_ep_regs[ep->dwc_ep.num]->doepint);
  51425. + doeptsize0.d32 = DWC_READ_REG32(&core_if->dev_if->
  51426. + out_ep_regs[ep->dwc_ep.num]->doeptsiz);
  51427. + if (pcd->ep0state == EP0_IDLE) {
  51428. + if (doepint_temp.b.sr) {
  51429. + CLEAR_OUT_EP_INTR(core_if, epnum, sr);
  51430. + }
  51431. + doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
  51432. + out_ep_regs[0]->doepint);
  51433. + if (doeptsize0.b.supcnt == 3) {
  51434. + DWC_DEBUGPL(DBG_ANY, "Rolling over!!!!!!!\n");
  51435. + ep->dwc_ep.stp_rollover = 1;
  51436. + }
  51437. + if (doepint.b.setup) {
  51438. +retry:
  51439. + /* Already started data stage, clear setup */
  51440. + CLEAR_OUT_EP_INTR(core_if, epnum, setup);
  51441. + doepint.b.setup = 0;
  51442. + handle_ep0(pcd);
  51443. + ep->dwc_ep.stp_rollover = 0;
  51444. + /* Prepare for more setup packets */
  51445. + if (pcd->ep0state == EP0_IN_STATUS_PHASE ||
  51446. + pcd->ep0state == EP0_IN_DATA_PHASE) {
  51447. + ep0_out_start(core_if, pcd);
  51448. + }
  51449. + goto exit_xfercompl;
  51450. + } else {
  51451. + /* Prepare for more setup packets */
  51452. + DWC_DEBUGPL(DBG_ANY,
  51453. + "EP0_IDLE SR=1 setup=0 new setup comes\n");
  51454. + doepint.d32 = DWC_READ_REG32(&core_if->dev_if->
  51455. + out_ep_regs[0]->doepint);
  51456. + if(doepint.b.setup)
  51457. + goto retry;
  51458. + ep0_out_start(core_if, pcd);
  51459. + }
  51460. + } else {
  51461. + dwc_otg_pcd_request_t *req;
  51462. + diepint_data_t diepint0 = {.d32 = 0};
  51463. + doepint_data_t doepint_temp = {.d32 = 0};
  51464. + depctl_data_t diepctl0;
  51465. + diepint0.d32 = DWC_READ_REG32(&core_if->dev_if->
  51466. + in_ep_regs[0]->diepint);
  51467. + diepctl0.d32 = DWC_READ_REG32(&core_if->dev_if->
  51468. + in_ep_regs[0]->diepctl);
  51469. +
  51470. + if (pcd->ep0state == EP0_IN_DATA_PHASE
  51471. + || pcd->ep0state == EP0_IN_STATUS_PHASE) {
  51472. + if (diepint0.b.xfercompl) {
  51473. + DWC_WRITE_REG32(&core_if->dev_if->
  51474. + in_ep_regs[0]->diepint, diepint0.d32);
  51475. + }
  51476. + if (diepctl0.b.epena) {
  51477. + diepint_data_t diepint = {.d32 = 0};
  51478. + diepctl0.b.snak = 1;
  51479. + DWC_WRITE_REG32(&core_if->dev_if->
  51480. + in_ep_regs[0]->diepctl, diepctl0.d32);
  51481. + do {
  51482. + dwc_udelay(10);
  51483. + diepint.d32 = DWC_READ_REG32(&core_if->dev_if->
  51484. + in_ep_regs[0]->diepint);
  51485. + } while (!diepint.b.inepnakeff);
  51486. + diepint.b.inepnakeff = 1;
  51487. + DWC_WRITE_REG32(&core_if->dev_if->
  51488. + in_ep_regs[0]->diepint, diepint.d32);
  51489. + diepctl0.d32 = 0;
  51490. + diepctl0.b.epdis = 1;
  51491. + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl,
  51492. + diepctl0.d32);
  51493. + do {
  51494. + dwc_udelay(10);
  51495. + diepint.d32 = DWC_READ_REG32(&core_if->dev_if->
  51496. + in_ep_regs[0]->diepint);
  51497. + } while (!diepint.b.epdisabled);
  51498. + diepint.b.epdisabled = 1;
  51499. + DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepint,
  51500. + diepint.d32);
  51501. + }
  51502. + }
  51503. + doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if->
  51504. + out_ep_regs[ep->dwc_ep.num]->doepint);
  51505. + if (doepint_temp.b.sr) {
  51506. + CLEAR_OUT_EP_INTR(core_if, epnum, sr);
  51507. + if (DWC_CIRCLEQ_EMPTY(&ep->queue)) {
  51508. + DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n");
  51509. + } else {
  51510. + DWC_DEBUGPL(DBG_PCDV, "complete req!!\n");
  51511. + req = DWC_CIRCLEQ_FIRST(&ep->queue);
  51512. + if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len &&
  51513. + pcd->ep0state == EP0_OUT_DATA_PHASE) {
  51514. + /* Read arrived setup packet from req->buf */
  51515. + dwc_memcpy(&pcd->setup_pkt->req,
  51516. + req->buf + ep->dwc_ep.xfer_count, 8);
  51517. + }
  51518. + req->actual = ep->dwc_ep.xfer_count;
  51519. + dwc_otg_request_done(ep, req, -ECONNRESET);
  51520. + ep->dwc_ep.start_xfer_buff = 0;
  51521. + ep->dwc_ep.xfer_buff = 0;
  51522. + ep->dwc_ep.xfer_len = 0;
  51523. + }
  51524. + pcd->ep0state = EP0_IDLE;
  51525. + if (doepint.b.setup) {
  51526. + DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n");
  51527. + /* Data stage started, clear setup */
  51528. + CLEAR_OUT_EP_INTR(core_if, epnum, setup);
  51529. + doepint.b.setup = 0;
  51530. + handle_ep0(pcd);
  51531. + /* Prepare for setup packets if ep0in was enabled*/
  51532. + if (pcd->ep0state == EP0_IN_STATUS_PHASE) {
  51533. + ep0_out_start(core_if, pcd);
  51534. + }
  51535. + goto exit_xfercompl;
  51536. + } else {
  51537. + /* Prepare for more setup packets */
  51538. + DWC_DEBUGPL(DBG_PCDV,
  51539. + "EP0_IDLE SR=1 setup=0 new setup comes 2\n");
  51540. + ep0_out_start(core_if, pcd);
  51541. + }
  51542. + }
  51543. + }
  51544. + }
  51545. + if (core_if->dma_enable == 0 || pcd->ep0state != EP0_IDLE)
  51546. + handle_ep0(pcd);
  51547. +exit_xfercompl:
  51548. + DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n",
  51549. + dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep), doepint.d32);
  51550. + } else {
  51551. + if (core_if->dma_desc_enable == 0
  51552. + || pcd->ep0state != EP0_IDLE)
  51553. + handle_ep0(pcd);
  51554. + }
  51555. +#ifdef DWC_EN_ISOC
  51556. + } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
  51557. + if (doepint.b.pktdrpsts == 0) {
  51558. + /* Clear the bit in DOEPINTn for this interrupt */
  51559. + CLEAR_OUT_EP_INTR(core_if,
  51560. + epnum,
  51561. + xfercompl);
  51562. + complete_iso_ep(pcd, ep);
  51563. + } else {
  51564. +
  51565. + doepint_data_t doepint = {.d32 = 0 };
  51566. + doepint.b.xfercompl = 1;
  51567. + doepint.b.pktdrpsts = 1;
  51568. + DWC_WRITE_REG32
  51569. + (&core_if->dev_if->out_ep_regs
  51570. + [epnum]->doepint,
  51571. + doepint.d32);
  51572. + if (handle_iso_out_pkt_dropped
  51573. + (core_if, dwc_ep)) {
  51574. + complete_iso_ep(pcd,
  51575. + ep);
  51576. + }
  51577. + }
  51578. +#endif /* DWC_EN_ISOC */
  51579. +#ifdef DWC_UTE_PER_IO
  51580. + } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
  51581. + CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl);
  51582. + if (!ep->stopped)
  51583. + complete_xiso_ep(ep);
  51584. +#endif /* DWC_UTE_PER_IO */
  51585. + } else {
  51586. + /* Clear the bit in DOEPINTn for this interrupt */
  51587. + CLEAR_OUT_EP_INTR(core_if, epnum,
  51588. + xfercompl);
  51589. +
  51590. + if (core_if->core_params->dev_out_nak) {
  51591. + DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[epnum]);
  51592. + pcd->core_if->ep_xfer_info[epnum].state = 0;
  51593. +#ifdef DEBUG
  51594. + print_memory_payload(pcd, dwc_ep);
  51595. +#endif
  51596. + }
  51597. + complete_ep(ep);
  51598. + }
  51599. +
  51600. + }
  51601. +
  51602. + /* Endpoint disable */
  51603. + if (doepint.b.epdisabled) {
  51604. +
  51605. + /* Clear the bit in DOEPINTn for this interrupt */
  51606. + CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled);
  51607. + if (core_if->core_params->dev_out_nak) {
  51608. +#ifdef DEBUG
  51609. + print_memory_payload(pcd, dwc_ep);
  51610. +#endif
  51611. + /* In case of timeout condition */
  51612. + if (core_if->ep_xfer_info[epnum].state == 2) {
  51613. + dctl.d32 = DWC_READ_REG32(&core_if->dev_if->
  51614. + dev_global_regs->dctl);
  51615. + dctl.b.cgoutnak = 1;
  51616. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
  51617. + dctl.d32);
  51618. + /* Unmask goutnakeff interrupt which was masked
  51619. + * during handle nak out interrupt */
  51620. + gintmsk.b.goutnakeff = 1;
  51621. + DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk,
  51622. + 0, gintmsk.d32);
  51623. +
  51624. + complete_ep(ep);
  51625. + }
  51626. + }
  51627. + if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC)
  51628. + {
  51629. + dctl_data_t dctl;
  51630. + gintmsk_data_t intr_mask = {.d32 = 0};
  51631. + dwc_otg_pcd_request_t *req = 0;
  51632. +
  51633. + dctl.d32 = DWC_READ_REG32(&core_if->dev_if->
  51634. + dev_global_regs->dctl);
  51635. + dctl.b.cgoutnak = 1;
  51636. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
  51637. + dctl.d32);
  51638. +
  51639. + intr_mask.d32 = 0;
  51640. + intr_mask.b.incomplisoout = 1;
  51641. +
  51642. + /* Get any pending requests */
  51643. + if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) {
  51644. + req = DWC_CIRCLEQ_FIRST(&ep->queue);
  51645. + if (!req) {
  51646. + DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep);
  51647. + } else {
  51648. + dwc_otg_request_done(ep, req, 0);
  51649. + start_next_request(ep);
  51650. + }
  51651. + } else {
  51652. + DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep);
  51653. + }
  51654. + }
  51655. + }
  51656. + /* AHB Error */
  51657. + if (doepint.b.ahberr) {
  51658. + DWC_ERROR("EP%d OUT AHB Error\n", epnum);
  51659. + DWC_ERROR("EP%d DEPDMA=0x%08x \n",
  51660. + epnum, core_if->dev_if->out_ep_regs[epnum]->doepdma);
  51661. + CLEAR_OUT_EP_INTR(core_if, epnum, ahberr);
  51662. + }
  51663. + /* Setup Phase Done (contorl EPs) */
  51664. + if (doepint.b.setup) {
  51665. +#ifdef DEBUG_EP0
  51666. + DWC_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n", epnum);
  51667. +#endif
  51668. + CLEAR_OUT_EP_INTR(core_if, epnum, setup);
  51669. +
  51670. + handle_ep0(pcd);
  51671. + }
  51672. +
  51673. + /** OUT EP BNA Intr */
  51674. + if (doepint.b.bna) {
  51675. + CLEAR_OUT_EP_INTR(core_if, epnum, bna);
  51676. + if (core_if->dma_desc_enable) {
  51677. +#ifdef DWC_EN_ISOC
  51678. + if (dwc_ep->type ==
  51679. + DWC_OTG_EP_TYPE_ISOC) {
  51680. + /*
  51681. + * This checking is performed to prevent first "false" BNA
  51682. + * handling occuring right after reconnect
  51683. + */
  51684. + if (dwc_ep->next_frame !=
  51685. + 0xffffffff)
  51686. + dwc_otg_pcd_handle_iso_bna(ep);
  51687. + } else
  51688. +#endif /* DWC_EN_ISOC */
  51689. + {
  51690. + dwc_otg_pcd_handle_noniso_bna(ep);
  51691. + }
  51692. + }
  51693. + }
  51694. + /* Babble Interrupt */
  51695. + if (doepint.b.babble) {
  51696. + DWC_DEBUGPL(DBG_ANY, "EP%d OUT Babble\n",
  51697. + epnum);
  51698. + handle_out_ep_babble_intr(pcd, epnum);
  51699. +
  51700. + CLEAR_OUT_EP_INTR(core_if, epnum, babble);
  51701. + }
  51702. + if (doepint.b.outtknepdis) {
  51703. + DWC_DEBUGPL(DBG_ANY, "EP%d OUT Token received when EP is \
  51704. + disabled\n",epnum);
  51705. + if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
  51706. + doepmsk_data_t doepmsk = {.d32 = 0};
  51707. + ep->dwc_ep.frame_num = core_if->frame_num;
  51708. + if (ep->dwc_ep.bInterval > 1) {
  51709. + depctl_data_t depctl;
  51710. + depctl.d32 = DWC_READ_REG32(&core_if->dev_if->
  51711. + out_ep_regs[epnum]->doepctl);
  51712. + if (ep->dwc_ep.frame_num & 0x1) {
  51713. + depctl.b.setd1pid = 1;
  51714. + depctl.b.setd0pid = 0;
  51715. + } else {
  51716. + depctl.b.setd0pid = 1;
  51717. + depctl.b.setd1pid = 0;
  51718. + }
  51719. + DWC_WRITE_REG32(&core_if->dev_if->
  51720. + out_ep_regs[epnum]->doepctl, depctl.d32);
  51721. + }
  51722. + start_next_request(ep);
  51723. + doepmsk.b.outtknepdis = 1;
  51724. + DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk,
  51725. + doepmsk.d32, 0);
  51726. + }
  51727. + CLEAR_OUT_EP_INTR(core_if, epnum, outtknepdis);
  51728. + }
  51729. +
  51730. + /* NAK Interrutp */
  51731. + if (doepint.b.nak) {
  51732. + DWC_DEBUGPL(DBG_ANY, "EP%d OUT NAK\n", epnum);
  51733. + handle_out_ep_nak_intr(pcd, epnum);
  51734. +
  51735. + CLEAR_OUT_EP_INTR(core_if, epnum, nak);
  51736. + }
  51737. + /* NYET Interrutp */
  51738. + if (doepint.b.nyet) {
  51739. + DWC_DEBUGPL(DBG_ANY, "EP%d OUT NYET\n", epnum);
  51740. + handle_out_ep_nyet_intr(pcd, epnum);
  51741. +
  51742. + CLEAR_OUT_EP_INTR(core_if, epnum, nyet);
  51743. + }
  51744. + }
  51745. +
  51746. + epnum++;
  51747. + ep_intr >>= 1;
  51748. + }
  51749. +
  51750. + return 1;
  51751. +
  51752. +#undef CLEAR_OUT_EP_INTR
  51753. +}
  51754. +static int drop_transfer(uint32_t trgt_fr, uint32_t curr_fr, uint8_t frm_overrun)
  51755. +{
  51756. + int retval = 0;
  51757. + if(!frm_overrun && curr_fr >= trgt_fr)
  51758. + retval = 1;
  51759. + else if (frm_overrun
  51760. + && (curr_fr >= trgt_fr && ((curr_fr - trgt_fr) < 0x3FFF / 2)))
  51761. + retval = 1;
  51762. + return retval;
  51763. +}
  51764. +/**
  51765. + * Incomplete ISO IN Transfer Interrupt.
  51766. + * This interrupt indicates one of the following conditions occurred
  51767. + * while transmitting an ISOC transaction.
  51768. + * - Corrupted IN Token for ISOC EP.
  51769. + * - Packet not complete in FIFO.
  51770. + * The follow actions will be taken:
  51771. + * -# Determine the EP
  51772. + * -# Set incomplete flag in dwc_ep structure
  51773. + * -# Disable EP; when "Endpoint Disabled" interrupt is received
  51774. + * Flush FIFO
  51775. + */
  51776. +int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd)
  51777. +{
  51778. + gintsts_data_t gintsts;
  51779. +
  51780. +#ifdef DWC_EN_ISOC
  51781. + dwc_otg_dev_if_t *dev_if;
  51782. + deptsiz_data_t deptsiz = {.d32 = 0 };
  51783. + depctl_data_t depctl = {.d32 = 0 };
  51784. + dsts_data_t dsts = {.d32 = 0 };
  51785. + dwc_ep_t *dwc_ep;
  51786. + int i;
  51787. +
  51788. + dev_if = GET_CORE_IF(pcd)->dev_if;
  51789. +
  51790. + for (i = 1; i <= dev_if->num_in_eps; ++i) {
  51791. + dwc_ep = &pcd->in_ep[i].dwc_ep;
  51792. + if (dwc_ep->active && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
  51793. + deptsiz.d32 =
  51794. + DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz);
  51795. + depctl.d32 =
  51796. + DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
  51797. +
  51798. + if (depctl.b.epdis && deptsiz.d32) {
  51799. + set_current_pkt_info(GET_CORE_IF(pcd), dwc_ep);
  51800. + if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
  51801. + dwc_ep->cur_pkt = 0;
  51802. + dwc_ep->proc_buf_num =
  51803. + (dwc_ep->proc_buf_num ^ 1) & 0x1;
  51804. +
  51805. + if (dwc_ep->proc_buf_num) {
  51806. + dwc_ep->cur_pkt_addr =
  51807. + dwc_ep->xfer_buff1;
  51808. + dwc_ep->cur_pkt_dma_addr =
  51809. + dwc_ep->dma_addr1;
  51810. + } else {
  51811. + dwc_ep->cur_pkt_addr =
  51812. + dwc_ep->xfer_buff0;
  51813. + dwc_ep->cur_pkt_dma_addr =
  51814. + dwc_ep->dma_addr0;
  51815. + }
  51816. +
  51817. + }
  51818. +
  51819. + dsts.d32 =
  51820. + DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
  51821. + dev_global_regs->dsts);
  51822. + dwc_ep->next_frame = dsts.b.soffn;
  51823. +
  51824. + dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF
  51825. + (pcd),
  51826. + dwc_ep);
  51827. + }
  51828. + }
  51829. + }
  51830. +
  51831. +#else
  51832. + depctl_data_t depctl = {.d32 = 0 };
  51833. + dwc_ep_t *dwc_ep;
  51834. + dwc_otg_dev_if_t *dev_if;
  51835. + int i;
  51836. + dev_if = GET_CORE_IF(pcd)->dev_if;
  51837. +
  51838. + DWC_DEBUGPL(DBG_PCD,"Incomplete ISO IN \n");
  51839. +
  51840. + for (i = 1; i <= dev_if->num_in_eps; ++i) {
  51841. + dwc_ep = &pcd->in_ep[i-1].dwc_ep;
  51842. + depctl.d32 =
  51843. + DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
  51844. + if (depctl.b.epena && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) {
  51845. + if (drop_transfer(dwc_ep->frame_num, GET_CORE_IF(pcd)->frame_num,
  51846. + dwc_ep->frm_overrun))
  51847. + {
  51848. + depctl.d32 =
  51849. + DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
  51850. + depctl.b.snak = 1;
  51851. + depctl.b.epdis = 1;
  51852. + DWC_MODIFY_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32, depctl.d32);
  51853. + }
  51854. + }
  51855. + }
  51856. +
  51857. + /*intr_mask.b.incomplisoin = 1;
  51858. + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
  51859. + intr_mask.d32, 0); */
  51860. +#endif //DWC_EN_ISOC
  51861. +
  51862. + /* Clear interrupt */
  51863. + gintsts.d32 = 0;
  51864. + gintsts.b.incomplisoin = 1;
  51865. + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
  51866. + gintsts.d32);
  51867. +
  51868. + return 1;
  51869. +}
  51870. +
  51871. +/**
  51872. + * Incomplete ISO OUT Transfer Interrupt.
  51873. + *
  51874. + * This interrupt indicates that the core has dropped an ISO OUT
  51875. + * packet. The following conditions can be the cause:
  51876. + * - FIFO Full, the entire packet would not fit in the FIFO.
  51877. + * - CRC Error
  51878. + * - Corrupted Token
  51879. + * The follow actions will be taken:
  51880. + * -# Determine the EP
  51881. + * -# Set incomplete flag in dwc_ep structure
  51882. + * -# Read any data from the FIFO
  51883. + * -# Disable EP. When "Endpoint Disabled" interrupt is received
  51884. + * re-enable EP.
  51885. + */
  51886. +int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd)
  51887. +{
  51888. +
  51889. + gintsts_data_t gintsts;
  51890. +
  51891. +#ifdef DWC_EN_ISOC
  51892. + dwc_otg_dev_if_t *dev_if;
  51893. + deptsiz_data_t deptsiz = {.d32 = 0 };
  51894. + depctl_data_t depctl = {.d32 = 0 };
  51895. + dsts_data_t dsts = {.d32 = 0 };
  51896. + dwc_ep_t *dwc_ep;
  51897. + int i;
  51898. +
  51899. + dev_if = GET_CORE_IF(pcd)->dev_if;
  51900. +
  51901. + for (i = 1; i <= dev_if->num_out_eps; ++i) {
  51902. + dwc_ep = &pcd->in_ep[i].dwc_ep;
  51903. + if (pcd->out_ep[i].dwc_ep.active &&
  51904. + pcd->out_ep[i].dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) {
  51905. + deptsiz.d32 =
  51906. + DWC_READ_REG32(&dev_if->out_ep_regs[i]->doeptsiz);
  51907. + depctl.d32 =
  51908. + DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
  51909. +
  51910. + if (depctl.b.epdis && deptsiz.d32) {
  51911. + set_current_pkt_info(GET_CORE_IF(pcd),
  51912. + &pcd->out_ep[i].dwc_ep);
  51913. + if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) {
  51914. + dwc_ep->cur_pkt = 0;
  51915. + dwc_ep->proc_buf_num =
  51916. + (dwc_ep->proc_buf_num ^ 1) & 0x1;
  51917. +
  51918. + if (dwc_ep->proc_buf_num) {
  51919. + dwc_ep->cur_pkt_addr =
  51920. + dwc_ep->xfer_buff1;
  51921. + dwc_ep->cur_pkt_dma_addr =
  51922. + dwc_ep->dma_addr1;
  51923. + } else {
  51924. + dwc_ep->cur_pkt_addr =
  51925. + dwc_ep->xfer_buff0;
  51926. + dwc_ep->cur_pkt_dma_addr =
  51927. + dwc_ep->dma_addr0;
  51928. + }
  51929. +
  51930. + }
  51931. +
  51932. + dsts.d32 =
  51933. + DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if->
  51934. + dev_global_regs->dsts);
  51935. + dwc_ep->next_frame = dsts.b.soffn;
  51936. +
  51937. + dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF
  51938. + (pcd),
  51939. + dwc_ep);
  51940. + }
  51941. + }
  51942. + }
  51943. +#else
  51944. + /** @todo implement ISR */
  51945. + gintmsk_data_t intr_mask = {.d32 = 0 };
  51946. + dwc_otg_core_if_t *core_if;
  51947. + deptsiz_data_t deptsiz = {.d32 = 0 };
  51948. + depctl_data_t depctl = {.d32 = 0 };
  51949. + dctl_data_t dctl = {.d32 = 0 };
  51950. + dwc_ep_t *dwc_ep = NULL;
  51951. + int i;
  51952. + core_if = GET_CORE_IF(pcd);
  51953. +
  51954. + for (i = 0; i < core_if->dev_if->num_out_eps; ++i) {
  51955. + dwc_ep = &pcd->out_ep[i].dwc_ep;
  51956. + depctl.d32 =
  51957. + DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl);
  51958. + if (depctl.b.epena && depctl.b.dpid == (core_if->frame_num & 0x1)) {
  51959. + core_if->dev_if->isoc_ep = dwc_ep;
  51960. + deptsiz.d32 =
  51961. + DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz);
  51962. + break;
  51963. + }
  51964. + }
  51965. + dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
  51966. + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
  51967. + intr_mask.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
  51968. +
  51969. + if (!intr_mask.b.goutnakeff) {
  51970. + /* Unmask it */
  51971. + intr_mask.b.goutnakeff = 1;
  51972. + DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32);
  51973. + }
  51974. + if (!gintsts.b.goutnakeff) {
  51975. + dctl.b.sgoutnak = 1;
  51976. + }
  51977. + DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32);
  51978. +
  51979. + depctl.d32 = DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl);
  51980. + if (depctl.b.epena) {
  51981. + depctl.b.epdis = 1;
  51982. + depctl.b.snak = 1;
  51983. + }
  51984. + DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl, depctl.d32);
  51985. +
  51986. + intr_mask.d32 = 0;
  51987. + intr_mask.b.incomplisoout = 1;
  51988. +
  51989. +#endif /* DWC_EN_ISOC */
  51990. +
  51991. + /* Clear interrupt */
  51992. + gintsts.d32 = 0;
  51993. + gintsts.b.incomplisoout = 1;
  51994. + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
  51995. + gintsts.d32);
  51996. +
  51997. + return 1;
  51998. +}
  51999. +
  52000. +/**
  52001. + * This function handles the Global IN NAK Effective interrupt.
  52002. + *
  52003. + */
  52004. +int32_t dwc_otg_pcd_handle_in_nak_effective(dwc_otg_pcd_t * pcd)
  52005. +{
  52006. + dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
  52007. + depctl_data_t diepctl = {.d32 = 0 };
  52008. + gintmsk_data_t intr_mask = {.d32 = 0 };
  52009. + gintsts_data_t gintsts;
  52010. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  52011. + int i;
  52012. +
  52013. + DWC_DEBUGPL(DBG_PCD, "Global IN NAK Effective\n");
  52014. +
  52015. + /* Disable all active IN EPs */
  52016. + for (i = 0; i <= dev_if->num_in_eps; i++) {
  52017. + diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl);
  52018. + if (!(diepctl.b.eptype & 1) && diepctl.b.epena) {
  52019. + if (core_if->start_predict > 0)
  52020. + core_if->start_predict++;
  52021. + diepctl.b.epdis = 1;
  52022. + diepctl.b.snak = 1;
  52023. + DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, diepctl.d32);
  52024. + }
  52025. + }
  52026. +
  52027. +
  52028. + /* Disable the Global IN NAK Effective Interrupt */
  52029. + intr_mask.b.ginnakeff = 1;
  52030. + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
  52031. + intr_mask.d32, 0);
  52032. +
  52033. + /* Clear interrupt */
  52034. + gintsts.d32 = 0;
  52035. + gintsts.b.ginnakeff = 1;
  52036. + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
  52037. + gintsts.d32);
  52038. +
  52039. + return 1;
  52040. +}
  52041. +
  52042. +/**
  52043. + * OUT NAK Effective.
  52044. + *
  52045. + */
  52046. +int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd)
  52047. +{
  52048. + dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if;
  52049. + gintmsk_data_t intr_mask = {.d32 = 0 };
  52050. + gintsts_data_t gintsts;
  52051. + depctl_data_t doepctl;
  52052. + int i;
  52053. +
  52054. + /* Disable the Global OUT NAK Effective Interrupt */
  52055. + intr_mask.b.goutnakeff = 1;
  52056. + DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk,
  52057. + intr_mask.d32, 0);
  52058. +
  52059. + /* If DEV OUT NAK enabled*/
  52060. + if (pcd->core_if->core_params->dev_out_nak) {
  52061. + /* Run over all out endpoints to determine the ep number on
  52062. + * which the timeout has happened
  52063. + */
  52064. + for (i = 0; i <= dev_if->num_out_eps; i++) {
  52065. + if ( pcd->core_if->ep_xfer_info[i].state == 2 )
  52066. + break;
  52067. + }
  52068. + if (i > dev_if->num_out_eps) {
  52069. + dctl_data_t dctl;
  52070. + dctl.d32 =
  52071. + DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
  52072. + dctl.b.cgoutnak = 1;
  52073. + DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl,
  52074. + dctl.d32);
  52075. + goto out;
  52076. + }
  52077. +
  52078. + /* Disable the endpoint */
  52079. + doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl);
  52080. + if (doepctl.b.epena) {
  52081. + doepctl.b.epdis = 1;
  52082. + doepctl.b.snak = 1;
  52083. + }
  52084. + DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32);
  52085. + return 1;
  52086. + }
  52087. + /* We come here from Incomplete ISO OUT handler */
  52088. + if (dev_if->isoc_ep) {
  52089. + dwc_ep_t *dwc_ep = (dwc_ep_t *)dev_if->isoc_ep;
  52090. + uint32_t epnum = dwc_ep->num;
  52091. + doepint_data_t doepint;
  52092. + doepint.d32 =
  52093. + DWC_READ_REG32(&dev_if->out_ep_regs[dwc_ep->num]->doepint);
  52094. + dev_if->isoc_ep = NULL;
  52095. + doepctl.d32 =
  52096. + DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl);
  52097. + DWC_PRINTF("Before disable DOEPCTL = %08x\n", doepctl.d32);
  52098. + if (doepctl.b.epena) {
  52099. + doepctl.b.epdis = 1;
  52100. + doepctl.b.snak = 1;
  52101. + }
  52102. + DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepctl,
  52103. + doepctl.d32);
  52104. + return 1;
  52105. + } else
  52106. + DWC_PRINTF("INTERRUPT Handler not implemented for %s\n",
  52107. + "Global OUT NAK Effective\n");
  52108. +
  52109. +out:
  52110. + /* Clear interrupt */
  52111. + gintsts.d32 = 0;
  52112. + gintsts.b.goutnakeff = 1;
  52113. + DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts,
  52114. + gintsts.d32);
  52115. +
  52116. + return 1;
  52117. +}
  52118. +
  52119. +/**
  52120. + * PCD interrupt handler.
  52121. + *
  52122. + * The PCD handles the device interrupts. Many conditions can cause a
  52123. + * device interrupt. When an interrupt occurs, the device interrupt
  52124. + * service routine determines the cause of the interrupt and
  52125. + * dispatches handling to the appropriate function. These interrupt
  52126. + * handling functions are described below.
  52127. + *
  52128. + * All interrupt registers are processed from LSB to MSB.
  52129. + *
  52130. + */
  52131. +int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd)
  52132. +{
  52133. + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
  52134. +#ifdef VERBOSE
  52135. + dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
  52136. +#endif
  52137. + gintsts_data_t gintr_status;
  52138. + int32_t retval = 0;
  52139. +
  52140. + /* Exit from ISR if core is hibernated */
  52141. + if (core_if->hibernation_suspend == 1) {
  52142. + return retval;
  52143. + }
  52144. +#ifdef VERBOSE
  52145. + DWC_DEBUGPL(DBG_ANY, "%s() gintsts=%08x gintmsk=%08x\n",
  52146. + __func__,
  52147. + DWC_READ_REG32(&global_regs->gintsts),
  52148. + DWC_READ_REG32(&global_regs->gintmsk));
  52149. +#endif
  52150. +
  52151. + if (dwc_otg_is_device_mode(core_if)) {
  52152. + DWC_SPINLOCK(pcd->lock);
  52153. +#ifdef VERBOSE
  52154. + DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%08x gintmsk=%08x\n",
  52155. + __func__,
  52156. + DWC_READ_REG32(&global_regs->gintsts),
  52157. + DWC_READ_REG32(&global_regs->gintmsk));
  52158. +#endif
  52159. +
  52160. + gintr_status.d32 = dwc_otg_read_core_intr(core_if);
  52161. +
  52162. + DWC_DEBUGPL(DBG_PCDV, "%s: gintsts&gintmsk=%08x\n",
  52163. + __func__, gintr_status.d32);
  52164. +
  52165. + if (gintr_status.b.sofintr) {
  52166. + retval |= dwc_otg_pcd_handle_sof_intr(pcd);
  52167. + }
  52168. + if (gintr_status.b.rxstsqlvl) {
  52169. + retval |=
  52170. + dwc_otg_pcd_handle_rx_status_q_level_intr(pcd);
  52171. + }
  52172. + if (gintr_status.b.nptxfempty) {
  52173. + retval |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr(pcd);
  52174. + }
  52175. + if (gintr_status.b.goutnakeff) {
  52176. + retval |= dwc_otg_pcd_handle_out_nak_effective(pcd);
  52177. + }
  52178. + if (gintr_status.b.i2cintr) {
  52179. + retval |= dwc_otg_pcd_handle_i2c_intr(pcd);
  52180. + }
  52181. + if (gintr_status.b.erlysuspend) {
  52182. + retval |= dwc_otg_pcd_handle_early_suspend_intr(pcd);
  52183. + }
  52184. + if (gintr_status.b.usbreset) {
  52185. + retval |= dwc_otg_pcd_handle_usb_reset_intr(pcd);
  52186. + }
  52187. + if (gintr_status.b.enumdone) {
  52188. + retval |= dwc_otg_pcd_handle_enum_done_intr(pcd);
  52189. + }
  52190. + if (gintr_status.b.isooutdrop) {
  52191. + retval |=
  52192. + dwc_otg_pcd_handle_isoc_out_packet_dropped_intr
  52193. + (pcd);
  52194. + }
  52195. + if (gintr_status.b.eopframe) {
  52196. + retval |=
  52197. + dwc_otg_pcd_handle_end_periodic_frame_intr(pcd);
  52198. + }
  52199. + if (gintr_status.b.inepint) {
  52200. + if (!core_if->multiproc_int_enable) {
  52201. + retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
  52202. + }
  52203. + }
  52204. + if (gintr_status.b.outepintr) {
  52205. + if (!core_if->multiproc_int_enable) {
  52206. + retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
  52207. + }
  52208. + }
  52209. + if (gintr_status.b.epmismatch) {
  52210. + retval |= dwc_otg_pcd_handle_ep_mismatch_intr(pcd);
  52211. + }
  52212. + if (gintr_status.b.fetsusp) {
  52213. + retval |= dwc_otg_pcd_handle_ep_fetsusp_intr(pcd);
  52214. + }
  52215. + if (gintr_status.b.ginnakeff) {
  52216. + retval |= dwc_otg_pcd_handle_in_nak_effective(pcd);
  52217. + }
  52218. + if (gintr_status.b.incomplisoin) {
  52219. + retval |=
  52220. + dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd);
  52221. + }
  52222. + if (gintr_status.b.incomplisoout) {
  52223. + retval |=
  52224. + dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd);
  52225. + }
  52226. +
  52227. + /* In MPI mode Device Endpoints interrupts are asserted
  52228. + * without setting outepintr and inepint bits set, so these
  52229. + * Interrupt handlers are called without checking these bit-fields
  52230. + */
  52231. + if (core_if->multiproc_int_enable) {
  52232. + retval |= dwc_otg_pcd_handle_in_ep_intr(pcd);
  52233. + retval |= dwc_otg_pcd_handle_out_ep_intr(pcd);
  52234. + }
  52235. +#ifdef VERBOSE
  52236. + DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__,
  52237. + DWC_READ_REG32(&global_regs->gintsts));
  52238. +#endif
  52239. + DWC_SPINUNLOCK(pcd->lock);
  52240. + }
  52241. + return retval;
  52242. +}
  52243. +
  52244. +#endif /* DWC_HOST_ONLY */
  52245. --- /dev/null
  52246. +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
  52247. @@ -0,0 +1,1358 @@
  52248. + /* ==========================================================================
  52249. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $
  52250. + * $Revision: #21 $
  52251. + * $Date: 2012/08/10 $
  52252. + * $Change: 2047372 $
  52253. + *
  52254. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  52255. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  52256. + * otherwise expressly agreed to in writing between Synopsys and you.
  52257. + *
  52258. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  52259. + * any End User Software License Agreement or Agreement for Licensed Product
  52260. + * with Synopsys or any supplement thereto. You are permitted to use and
  52261. + * redistribute this Software in source and binary forms, with or without
  52262. + * modification, provided that redistributions of source code must retain this
  52263. + * notice. You may not view, use, disclose, copy or distribute this file or
  52264. + * any information contained herein except pursuant to this license grant from
  52265. + * Synopsys. If you do not agree with this notice, including the disclaimer
  52266. + * below, then you are not authorized to use the Software.
  52267. + *
  52268. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  52269. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  52270. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  52271. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  52272. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  52273. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  52274. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  52275. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  52276. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  52277. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  52278. + * DAMAGE.
  52279. + * ========================================================================== */
  52280. +#ifndef DWC_HOST_ONLY
  52281. +
  52282. +/** @file
  52283. + * This file implements the Peripheral Controller Driver.
  52284. + *
  52285. + * The Peripheral Controller Driver (PCD) is responsible for
  52286. + * translating requests from the Function Driver into the appropriate
  52287. + * actions on the DWC_otg controller. It isolates the Function Driver
  52288. + * from the specifics of the controller by providing an API to the
  52289. + * Function Driver.
  52290. + *
  52291. + * The Peripheral Controller Driver for Linux will implement the
  52292. + * Gadget API, so that the existing Gadget drivers can be used.
  52293. + * (Gadget Driver is the Linux terminology for a Function Driver.)
  52294. + *
  52295. + * The Linux Gadget API is defined in the header file
  52296. + * <code><linux/usb_gadget.h></code>. The USB EP operations API is
  52297. + * defined in the structure <code>usb_ep_ops</code> and the USB
  52298. + * Controller API is defined in the structure
  52299. + * <code>usb_gadget_ops</code>.
  52300. + *
  52301. + */
  52302. +
  52303. +#include "dwc_otg_os_dep.h"
  52304. +#include "dwc_otg_pcd_if.h"
  52305. +#include "dwc_otg_pcd.h"
  52306. +#include "dwc_otg_driver.h"
  52307. +#include "dwc_otg_dbg.h"
  52308. +
  52309. +static struct gadget_wrapper {
  52310. + dwc_otg_pcd_t *pcd;
  52311. +
  52312. + struct usb_gadget gadget;
  52313. + struct usb_gadget_driver *driver;
  52314. +
  52315. + struct usb_ep ep0;
  52316. + struct usb_ep in_ep[16];
  52317. + struct usb_ep out_ep[16];
  52318. +
  52319. +} *gadget_wrapper;
  52320. +
  52321. +/* Display the contents of the buffer */
  52322. +extern void dump_msg(const u8 * buf, unsigned int length);
  52323. +/**
  52324. + * Get the dwc_otg_pcd_ep_t* from usb_ep* pointer - NULL in case
  52325. + * if the endpoint is not found
  52326. + */
  52327. +static struct dwc_otg_pcd_ep *ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)
  52328. +{
  52329. + int i;
  52330. + if (pcd->ep0.priv == handle) {
  52331. + return &pcd->ep0;
  52332. + }
  52333. +
  52334. + for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {
  52335. + if (pcd->in_ep[i].priv == handle)
  52336. + return &pcd->in_ep[i];
  52337. + if (pcd->out_ep[i].priv == handle)
  52338. + return &pcd->out_ep[i];
  52339. + }
  52340. +
  52341. + return NULL;
  52342. +}
  52343. +
  52344. +/* USB Endpoint Operations */
  52345. +/*
  52346. + * The following sections briefly describe the behavior of the Gadget
  52347. + * API endpoint operations implemented in the DWC_otg driver
  52348. + * software. Detailed descriptions of the generic behavior of each of
  52349. + * these functions can be found in the Linux header file
  52350. + * include/linux/usb_gadget.h.
  52351. + *
  52352. + * The Gadget API provides wrapper functions for each of the function
  52353. + * pointers defined in usb_ep_ops. The Gadget Driver calls the wrapper
  52354. + * function, which then calls the underlying PCD function. The
  52355. + * following sections are named according to the wrapper
  52356. + * functions. Within each section, the corresponding DWC_otg PCD
  52357. + * function name is specified.
  52358. + *
  52359. + */
  52360. +
  52361. +/**
  52362. + * This function is called by the Gadget Driver for each EP to be
  52363. + * configured for the current configuration (SET_CONFIGURATION).
  52364. + *
  52365. + * This function initializes the dwc_otg_ep_t data structure, and then
  52366. + * calls dwc_otg_ep_activate.
  52367. + */
  52368. +static int ep_enable(struct usb_ep *usb_ep,
  52369. + const struct usb_endpoint_descriptor *ep_desc)
  52370. +{
  52371. + int retval;
  52372. +
  52373. + DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, ep_desc);
  52374. +
  52375. + if (!usb_ep || !ep_desc || ep_desc->bDescriptorType != USB_DT_ENDPOINT) {
  52376. + DWC_WARN("%s, bad ep or descriptor\n", __func__);
  52377. + return -EINVAL;
  52378. + }
  52379. + if (usb_ep == &gadget_wrapper->ep0) {
  52380. + DWC_WARN("%s, bad ep(0)\n", __func__);
  52381. + return -EINVAL;
  52382. + }
  52383. +
  52384. + /* Check FIFO size? */
  52385. + if (!ep_desc->wMaxPacketSize) {
  52386. + DWC_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name);
  52387. + return -ERANGE;
  52388. + }
  52389. +
  52390. + if (!gadget_wrapper->driver ||
  52391. + gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
  52392. + DWC_WARN("%s, bogus device state\n", __func__);
  52393. + return -ESHUTDOWN;
  52394. + }
  52395. +
  52396. + /* Delete after check - MAS */
  52397. +#if 0
  52398. + nat = (uint32_t) ep_desc->wMaxPacketSize;
  52399. + printk(KERN_ALERT "%s: nat (before) =%d\n", __func__, nat);
  52400. + nat = (nat >> 11) & 0x03;
  52401. + printk(KERN_ALERT "%s: nat (after) =%d\n", __func__, nat);
  52402. +#endif
  52403. + retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd,
  52404. + (const uint8_t *)ep_desc,
  52405. + (void *)usb_ep);
  52406. + if (retval) {
  52407. + DWC_WARN("dwc_otg_pcd_ep_enable failed\n");
  52408. + return -EINVAL;
  52409. + }
  52410. +
  52411. + usb_ep->maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize);
  52412. +
  52413. + return 0;
  52414. +}
  52415. +
  52416. +/**
  52417. + * This function is called when an EP is disabled due to disconnect or
  52418. + * change in configuration. Any pending requests will terminate with a
  52419. + * status of -ESHUTDOWN.
  52420. + *
  52421. + * This function modifies the dwc_otg_ep_t data structure for this EP,
  52422. + * and then calls dwc_otg_ep_deactivate.
  52423. + */
  52424. +static int ep_disable(struct usb_ep *usb_ep)
  52425. +{
  52426. + int retval;
  52427. +
  52428. + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, usb_ep);
  52429. + if (!usb_ep) {
  52430. + DWC_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__,
  52431. + usb_ep ? usb_ep->name : NULL);
  52432. + return -EINVAL;
  52433. + }
  52434. +
  52435. + retval = dwc_otg_pcd_ep_disable(gadget_wrapper->pcd, usb_ep);
  52436. + if (retval) {
  52437. + retval = -EINVAL;
  52438. + }
  52439. +
  52440. + return retval;
  52441. +}
  52442. +
  52443. +/**
  52444. + * This function allocates a request object to use with the specified
  52445. + * endpoint.
  52446. + *
  52447. + * @param ep The endpoint to be used with with the request
  52448. + * @param gfp_flags the GFP_* flags to use.
  52449. + */
  52450. +static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *ep,
  52451. + gfp_t gfp_flags)
  52452. +{
  52453. + struct usb_request *usb_req;
  52454. +
  52455. + DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d)\n", __func__, ep, gfp_flags);
  52456. + if (0 == ep) {
  52457. + DWC_WARN("%s() %s\n", __func__, "Invalid EP!\n");
  52458. + return 0;
  52459. + }
  52460. + usb_req = kmalloc(sizeof(*usb_req), gfp_flags);
  52461. + if (0 == usb_req) {
  52462. + DWC_WARN("%s() %s\n", __func__, "request allocation failed!\n");
  52463. + return 0;
  52464. + }
  52465. + memset(usb_req, 0, sizeof(*usb_req));
  52466. + usb_req->dma = DWC_DMA_ADDR_INVALID;
  52467. +
  52468. + return usb_req;
  52469. +}
  52470. +
  52471. +/**
  52472. + * This function frees a request object.
  52473. + *
  52474. + * @param ep The endpoint associated with the request
  52475. + * @param req The request being freed
  52476. + */
  52477. +static void dwc_otg_pcd_free_request(struct usb_ep *ep, struct usb_request *req)
  52478. +{
  52479. + DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, ep, req);
  52480. +
  52481. + if (0 == ep || 0 == req) {
  52482. + DWC_WARN("%s() %s\n", __func__,
  52483. + "Invalid ep or req argument!\n");
  52484. + return;
  52485. + }
  52486. +
  52487. + kfree(req);
  52488. +}
  52489. +
  52490. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
  52491. +/**
  52492. + * This function allocates an I/O buffer to be used for a transfer
  52493. + * to/from the specified endpoint.
  52494. + *
  52495. + * @param usb_ep The endpoint to be used with with the request
  52496. + * @param bytes The desired number of bytes for the buffer
  52497. + * @param dma Pointer to the buffer's DMA address; must be valid
  52498. + * @param gfp_flags the GFP_* flags to use.
  52499. + * @return address of a new buffer or null is buffer could not be allocated.
  52500. + */
  52501. +static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes,
  52502. + dma_addr_t * dma, gfp_t gfp_flags)
  52503. +{
  52504. + void *buf;
  52505. + dwc_otg_pcd_t *pcd = 0;
  52506. +
  52507. + pcd = gadget_wrapper->pcd;
  52508. +
  52509. + DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d,%p,%0x)\n", __func__, usb_ep, bytes,
  52510. + dma, gfp_flags);
  52511. +
  52512. + /* Check dword alignment */
  52513. + if ((bytes & 0x3UL) != 0) {
  52514. + DWC_WARN("%s() Buffer size is not a multiple of"
  52515. + "DWORD size (%d)", __func__, bytes);
  52516. + }
  52517. +
  52518. + buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags);
  52519. +
  52520. + /* Check dword alignment */
  52521. + if (((int)buf & 0x3UL) != 0) {
  52522. + DWC_WARN("%s() Buffer is not DWORD aligned (%p)",
  52523. + __func__, buf);
  52524. + }
  52525. +
  52526. + return buf;
  52527. +}
  52528. +
  52529. +/**
  52530. + * This function frees an I/O buffer that was allocated by alloc_buffer.
  52531. + *
  52532. + * @param usb_ep the endpoint associated with the buffer
  52533. + * @param buf address of the buffer
  52534. + * @param dma The buffer's DMA address
  52535. + * @param bytes The number of bytes of the buffer
  52536. + */
  52537. +static void dwc_otg_pcd_free_buffer(struct usb_ep *usb_ep, void *buf,
  52538. + dma_addr_t dma, unsigned bytes)
  52539. +{
  52540. + dwc_otg_pcd_t *pcd = 0;
  52541. +
  52542. + pcd = gadget_wrapper->pcd;
  52543. +
  52544. + DWC_DEBUGPL(DBG_PCDV, "%s(%p,%0x,%d)\n", __func__, buf, dma, bytes);
  52545. +
  52546. + dma_free_coherent(NULL, bytes, buf, dma);
  52547. +}
  52548. +#endif
  52549. +
  52550. +/**
  52551. + * This function is used to submit an I/O Request to an EP.
  52552. + *
  52553. + * - When the request completes the request's completion callback
  52554. + * is called to return the request to the driver.
  52555. + * - An EP, except control EPs, may have multiple requests
  52556. + * pending.
  52557. + * - Once submitted the request cannot be examined or modified.
  52558. + * - Each request is turned into one or more packets.
  52559. + * - A BULK EP can queue any amount of data; the transfer is
  52560. + * packetized.
  52561. + * - Zero length Packets are specified with the request 'zero'
  52562. + * flag.
  52563. + */
  52564. +static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req,
  52565. + gfp_t gfp_flags)
  52566. +{
  52567. + dwc_otg_pcd_t *pcd;
  52568. + struct dwc_otg_pcd_ep *ep = NULL;
  52569. + int retval = 0, is_isoc_ep = 0;
  52570. + dma_addr_t dma_addr = DWC_DMA_ADDR_INVALID;
  52571. +
  52572. + DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p,%d)\n",
  52573. + __func__, usb_ep, usb_req, gfp_flags);
  52574. +
  52575. + if (!usb_req || !usb_req->complete || !usb_req->buf) {
  52576. + DWC_WARN("bad params\n");
  52577. + return -EINVAL;
  52578. + }
  52579. +
  52580. + if (!usb_ep) {
  52581. + DWC_WARN("bad ep\n");
  52582. + return -EINVAL;
  52583. + }
  52584. +
  52585. + pcd = gadget_wrapper->pcd;
  52586. + if (!gadget_wrapper->driver ||
  52587. + gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
  52588. + DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
  52589. + gadget_wrapper->gadget.speed);
  52590. + DWC_WARN("bogus device state\n");
  52591. + return -ESHUTDOWN;
  52592. + }
  52593. +
  52594. + DWC_DEBUGPL(DBG_PCD, "%s queue req %p, len %d buf %p\n",
  52595. + usb_ep->name, usb_req, usb_req->length, usb_req->buf);
  52596. +
  52597. + usb_req->status = -EINPROGRESS;
  52598. + usb_req->actual = 0;
  52599. +
  52600. + ep = ep_from_handle(pcd, usb_ep);
  52601. + if (ep == NULL)
  52602. + is_isoc_ep = 0;
  52603. + else
  52604. + is_isoc_ep = (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ? 1 : 0;
  52605. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
  52606. + dma_addr = usb_req->dma;
  52607. +#else
  52608. + if (GET_CORE_IF(pcd)->dma_enable) {
  52609. + dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev;
  52610. + struct device *dev = NULL;
  52611. +
  52612. + if (otg_dev != NULL)
  52613. + dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep);
  52614. +
  52615. + if (usb_req->length != 0 &&
  52616. + usb_req->dma == DWC_DMA_ADDR_INVALID) {
  52617. + dma_addr = dma_map_single(dev, usb_req->buf,
  52618. + usb_req->length,
  52619. + ep->dwc_ep.is_in ?
  52620. + DMA_TO_DEVICE:
  52621. + DMA_FROM_DEVICE);
  52622. + }
  52623. + }
  52624. +#endif
  52625. +
  52626. +#ifdef DWC_UTE_PER_IO
  52627. + if (is_isoc_ep == 1) {
  52628. + retval = dwc_otg_pcd_xiso_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr,
  52629. + usb_req->length, usb_req->zero, usb_req,
  52630. + gfp_flags == GFP_ATOMIC ? 1 : 0, &usb_req->ext_req);
  52631. + if (retval)
  52632. + return -EINVAL;
  52633. +
  52634. + return 0;
  52635. + }
  52636. +#endif
  52637. + retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr,
  52638. + usb_req->length, usb_req->zero, usb_req,
  52639. + gfp_flags == GFP_ATOMIC ? 1 : 0);
  52640. + if (retval) {
  52641. + return -EINVAL;
  52642. + }
  52643. +
  52644. + return 0;
  52645. +}
  52646. +
  52647. +/**
  52648. + * This function cancels an I/O request from an EP.
  52649. + */
  52650. +static int ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req)
  52651. +{
  52652. + DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, usb_req);
  52653. +
  52654. + if (!usb_ep || !usb_req) {
  52655. + DWC_WARN("bad argument\n");
  52656. + return -EINVAL;
  52657. + }
  52658. + if (!gadget_wrapper->driver ||
  52659. + gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
  52660. + DWC_WARN("bogus device state\n");
  52661. + return -ESHUTDOWN;
  52662. + }
  52663. + if (dwc_otg_pcd_ep_dequeue(gadget_wrapper->pcd, usb_ep, usb_req)) {
  52664. + return -EINVAL;
  52665. + }
  52666. +
  52667. + return 0;
  52668. +}
  52669. +
  52670. +/**
  52671. + * usb_ep_set_halt stalls an endpoint.
  52672. + *
  52673. + * usb_ep_clear_halt clears an endpoint halt and resets its data
  52674. + * toggle.
  52675. + *
  52676. + * Both of these functions are implemented with the same underlying
  52677. + * function. The behavior depends on the value argument.
  52678. + *
  52679. + * @param[in] usb_ep the Endpoint to halt or clear halt.
  52680. + * @param[in] value
  52681. + * - 0 means clear_halt.
  52682. + * - 1 means set_halt,
  52683. + * - 2 means clear stall lock flag.
  52684. + * - 3 means set stall lock flag.
  52685. + */
  52686. +static int ep_halt(struct usb_ep *usb_ep, int value)
  52687. +{
  52688. + int retval = 0;
  52689. +
  52690. + DWC_DEBUGPL(DBG_PCD, "HALT %s %d\n", usb_ep->name, value);
  52691. +
  52692. + if (!usb_ep) {
  52693. + DWC_WARN("bad ep\n");
  52694. + return -EINVAL;
  52695. + }
  52696. +
  52697. + retval = dwc_otg_pcd_ep_halt(gadget_wrapper->pcd, usb_ep, value);
  52698. + if (retval == -DWC_E_AGAIN) {
  52699. + return -EAGAIN;
  52700. + } else if (retval) {
  52701. + retval = -EINVAL;
  52702. + }
  52703. +
  52704. + return retval;
  52705. +}
  52706. +
  52707. +//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
  52708. +#if 0
  52709. +/**
  52710. + * ep_wedge: sets the halt feature and ignores clear requests
  52711. + *
  52712. + * @usb_ep: the endpoint being wedged
  52713. + *
  52714. + * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)
  52715. + * requests. If the gadget driver clears the halt status, it will
  52716. + * automatically unwedge the endpoint.
  52717. + *
  52718. + * Returns zero on success, else negative errno. *
  52719. + * Check usb_ep_set_wedge() at "usb_gadget.h" for details
  52720. + */
  52721. +static int ep_wedge(struct usb_ep *usb_ep)
  52722. +{
  52723. + int retval = 0;
  52724. +
  52725. + DWC_DEBUGPL(DBG_PCD, "WEDGE %s\n", usb_ep->name);
  52726. +
  52727. + if (!usb_ep) {
  52728. + DWC_WARN("bad ep\n");
  52729. + return -EINVAL;
  52730. + }
  52731. +
  52732. + retval = dwc_otg_pcd_ep_wedge(gadget_wrapper->pcd, usb_ep);
  52733. + if (retval == -DWC_E_AGAIN) {
  52734. + retval = -EAGAIN;
  52735. + } else if (retval) {
  52736. + retval = -EINVAL;
  52737. + }
  52738. +
  52739. + return retval;
  52740. +}
  52741. +#endif
  52742. +
  52743. +#ifdef DWC_EN_ISOC
  52744. +/**
  52745. + * This function is used to submit an ISOC Transfer Request to an EP.
  52746. + *
  52747. + * - Every time a sync period completes the request's completion callback
  52748. + * is called to provide data to the gadget driver.
  52749. + * - Once submitted the request cannot be modified.
  52750. + * - Each request is turned into periodic data packets untill ISO
  52751. + * Transfer is stopped..
  52752. + */
  52753. +static int iso_ep_start(struct usb_ep *usb_ep, struct usb_iso_request *req,
  52754. + gfp_t gfp_flags)
  52755. +{
  52756. + int retval = 0;
  52757. +
  52758. + if (!req || !req->process_buffer || !req->buf0 || !req->buf1) {
  52759. + DWC_WARN("bad params\n");
  52760. + return -EINVAL;
  52761. + }
  52762. +
  52763. + if (!usb_ep) {
  52764. + DWC_PRINTF("bad params\n");
  52765. + return -EINVAL;
  52766. + }
  52767. +
  52768. + req->status = -EINPROGRESS;
  52769. +
  52770. + retval =
  52771. + dwc_otg_pcd_iso_ep_start(gadget_wrapper->pcd, usb_ep, req->buf0,
  52772. + req->buf1, req->dma0, req->dma1,
  52773. + req->sync_frame, req->data_pattern_frame,
  52774. + req->data_per_frame,
  52775. + req->
  52776. + flags & USB_REQ_ISO_ASAP ? -1 :
  52777. + req->start_frame, req->buf_proc_intrvl,
  52778. + req, gfp_flags == GFP_ATOMIC ? 1 : 0);
  52779. +
  52780. + if (retval) {
  52781. + return -EINVAL;
  52782. + }
  52783. +
  52784. + return retval;
  52785. +}
  52786. +
  52787. +/**
  52788. + * This function stops ISO EP Periodic Data Transfer.
  52789. + */
  52790. +static int iso_ep_stop(struct usb_ep *usb_ep, struct usb_iso_request *req)
  52791. +{
  52792. + int retval = 0;
  52793. + if (!usb_ep) {
  52794. + DWC_WARN("bad ep\n");
  52795. + }
  52796. +
  52797. + if (!gadget_wrapper->driver ||
  52798. + gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
  52799. + DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
  52800. + gadget_wrapper->gadget.speed);
  52801. + DWC_WARN("bogus device state\n");
  52802. + }
  52803. +
  52804. + dwc_otg_pcd_iso_ep_stop(gadget_wrapper->pcd, usb_ep, req);
  52805. + if (retval) {
  52806. + retval = -EINVAL;
  52807. + }
  52808. +
  52809. + return retval;
  52810. +}
  52811. +
  52812. +static struct usb_iso_request *alloc_iso_request(struct usb_ep *ep,
  52813. + int packets, gfp_t gfp_flags)
  52814. +{
  52815. + struct usb_iso_request *pReq = NULL;
  52816. + uint32_t req_size;
  52817. +
  52818. + req_size = sizeof(struct usb_iso_request);
  52819. + req_size +=
  52820. + (2 * packets * (sizeof(struct usb_gadget_iso_packet_descriptor)));
  52821. +
  52822. + pReq = kmalloc(req_size, gfp_flags);
  52823. + if (!pReq) {
  52824. + DWC_WARN("Can't allocate Iso Request\n");
  52825. + return 0;
  52826. + }
  52827. + pReq->iso_packet_desc0 = (void *)(pReq + 1);
  52828. +
  52829. + pReq->iso_packet_desc1 = pReq->iso_packet_desc0 + packets;
  52830. +
  52831. + return pReq;
  52832. +}
  52833. +
  52834. +static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req)
  52835. +{
  52836. + kfree(req);
  52837. +}
  52838. +
  52839. +static struct usb_isoc_ep_ops dwc_otg_pcd_ep_ops = {
  52840. + .ep_ops = {
  52841. + .enable = ep_enable,
  52842. + .disable = ep_disable,
  52843. +
  52844. + .alloc_request = dwc_otg_pcd_alloc_request,
  52845. + .free_request = dwc_otg_pcd_free_request,
  52846. +
  52847. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
  52848. + .alloc_buffer = dwc_otg_pcd_alloc_buffer,
  52849. + .free_buffer = dwc_otg_pcd_free_buffer,
  52850. +#endif
  52851. +
  52852. + .queue = ep_queue,
  52853. + .dequeue = ep_dequeue,
  52854. +
  52855. + .set_halt = ep_halt,
  52856. + .fifo_status = 0,
  52857. + .fifo_flush = 0,
  52858. + },
  52859. + .iso_ep_start = iso_ep_start,
  52860. + .iso_ep_stop = iso_ep_stop,
  52861. + .alloc_iso_request = alloc_iso_request,
  52862. + .free_iso_request = free_iso_request,
  52863. +};
  52864. +
  52865. +#else
  52866. +
  52867. + int (*enable) (struct usb_ep *ep,
  52868. + const struct usb_endpoint_descriptor *desc);
  52869. + int (*disable) (struct usb_ep *ep);
  52870. +
  52871. + struct usb_request *(*alloc_request) (struct usb_ep *ep,
  52872. + gfp_t gfp_flags);
  52873. + void (*free_request) (struct usb_ep *ep, struct usb_request *req);
  52874. +
  52875. + int (*queue) (struct usb_ep *ep, struct usb_request *req,
  52876. + gfp_t gfp_flags);
  52877. + int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
  52878. +
  52879. + int (*set_halt) (struct usb_ep *ep, int value);
  52880. + int (*set_wedge) (struct usb_ep *ep);
  52881. +
  52882. + int (*fifo_status) (struct usb_ep *ep);
  52883. + void (*fifo_flush) (struct usb_ep *ep);
  52884. +static struct usb_ep_ops dwc_otg_pcd_ep_ops = {
  52885. + .enable = ep_enable,
  52886. + .disable = ep_disable,
  52887. +
  52888. + .alloc_request = dwc_otg_pcd_alloc_request,
  52889. + .free_request = dwc_otg_pcd_free_request,
  52890. +
  52891. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
  52892. + .alloc_buffer = dwc_otg_pcd_alloc_buffer,
  52893. + .free_buffer = dwc_otg_pcd_free_buffer,
  52894. +#else
  52895. + /* .set_wedge = ep_wedge, */
  52896. + .set_wedge = NULL, /* uses set_halt instead */
  52897. +#endif
  52898. +
  52899. + .queue = ep_queue,
  52900. + .dequeue = ep_dequeue,
  52901. +
  52902. + .set_halt = ep_halt,
  52903. + .fifo_status = 0,
  52904. + .fifo_flush = 0,
  52905. +
  52906. +};
  52907. +
  52908. +#endif /* _EN_ISOC_ */
  52909. +/* Gadget Operations */
  52910. +/**
  52911. + * The following gadget operations will be implemented in the DWC_otg
  52912. + * PCD. Functions in the API that are not described below are not
  52913. + * implemented.
  52914. + *
  52915. + * The Gadget API provides wrapper functions for each of the function
  52916. + * pointers defined in usb_gadget_ops. The Gadget Driver calls the
  52917. + * wrapper function, which then calls the underlying PCD function. The
  52918. + * following sections are named according to the wrapper functions
  52919. + * (except for ioctl, which doesn't have a wrapper function). Within
  52920. + * each section, the corresponding DWC_otg PCD function name is
  52921. + * specified.
  52922. + *
  52923. + */
  52924. +
  52925. +/**
  52926. + *Gets the USB Frame number of the last SOF.
  52927. + */
  52928. +static int get_frame_number(struct usb_gadget *gadget)
  52929. +{
  52930. + struct gadget_wrapper *d;
  52931. +
  52932. + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
  52933. +
  52934. + if (gadget == 0) {
  52935. + return -ENODEV;
  52936. + }
  52937. +
  52938. + d = container_of(gadget, struct gadget_wrapper, gadget);
  52939. + return dwc_otg_pcd_get_frame_number(d->pcd);
  52940. +}
  52941. +
  52942. +#ifdef CONFIG_USB_DWC_OTG_LPM
  52943. +static int test_lpm_enabled(struct usb_gadget *gadget)
  52944. +{
  52945. + struct gadget_wrapper *d;
  52946. +
  52947. + d = container_of(gadget, struct gadget_wrapper, gadget);
  52948. +
  52949. + return dwc_otg_pcd_is_lpm_enabled(d->pcd);
  52950. +}
  52951. +#endif
  52952. +
  52953. +/**
  52954. + * Initiates Session Request Protocol (SRP) to wakeup the host if no
  52955. + * session is in progress. If a session is already in progress, but
  52956. + * the device is suspended, remote wakeup signaling is started.
  52957. + *
  52958. + */
  52959. +static int wakeup(struct usb_gadget *gadget)
  52960. +{
  52961. + struct gadget_wrapper *d;
  52962. +
  52963. + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
  52964. +
  52965. + if (gadget == 0) {
  52966. + return -ENODEV;
  52967. + } else {
  52968. + d = container_of(gadget, struct gadget_wrapper, gadget);
  52969. + }
  52970. + dwc_otg_pcd_wakeup(d->pcd);
  52971. + return 0;
  52972. +}
  52973. +
  52974. +static const struct usb_gadget_ops dwc_otg_pcd_ops = {
  52975. + .get_frame = get_frame_number,
  52976. + .wakeup = wakeup,
  52977. +#ifdef CONFIG_USB_DWC_OTG_LPM
  52978. + .lpm_support = test_lpm_enabled,
  52979. +#endif
  52980. + // current versions must always be self-powered
  52981. +};
  52982. +
  52983. +static int _setup(dwc_otg_pcd_t * pcd, uint8_t * bytes)
  52984. +{
  52985. + int retval = -DWC_E_NOT_SUPPORTED;
  52986. + if (gadget_wrapper->driver && gadget_wrapper->driver->setup) {
  52987. + retval = gadget_wrapper->driver->setup(&gadget_wrapper->gadget,
  52988. + (struct usb_ctrlrequest
  52989. + *)bytes);
  52990. + }
  52991. +
  52992. + if (retval == -ENOTSUPP) {
  52993. + retval = -DWC_E_NOT_SUPPORTED;
  52994. + } else if (retval < 0) {
  52995. + retval = -DWC_E_INVALID;
  52996. + }
  52997. +
  52998. + return retval;
  52999. +}
  53000. +
  53001. +#ifdef DWC_EN_ISOC
  53002. +static int _isoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,
  53003. + void *req_handle, int proc_buf_num)
  53004. +{
  53005. + int i, packet_count;
  53006. + struct usb_gadget_iso_packet_descriptor *iso_packet = 0;
  53007. + struct usb_iso_request *iso_req = req_handle;
  53008. +
  53009. + if (proc_buf_num) {
  53010. + iso_packet = iso_req->iso_packet_desc1;
  53011. + } else {
  53012. + iso_packet = iso_req->iso_packet_desc0;
  53013. + }
  53014. + packet_count =
  53015. + dwc_otg_pcd_get_iso_packet_count(pcd, ep_handle, req_handle);
  53016. + for (i = 0; i < packet_count; ++i) {
  53017. + int status;
  53018. + int actual;
  53019. + int offset;
  53020. + dwc_otg_pcd_get_iso_packet_params(pcd, ep_handle, req_handle,
  53021. + i, &status, &actual, &offset);
  53022. + switch (status) {
  53023. + case -DWC_E_NO_DATA:
  53024. + status = -ENODATA;
  53025. + break;
  53026. + default:
  53027. + if (status) {
  53028. + DWC_PRINTF("unknown status in isoc packet\n");
  53029. + }
  53030. +
  53031. + }
  53032. + iso_packet[i].status = status;
  53033. + iso_packet[i].offset = offset;
  53034. + iso_packet[i].actual_length = actual;
  53035. + }
  53036. +
  53037. + iso_req->status = 0;
  53038. + iso_req->process_buffer(ep_handle, iso_req);
  53039. +
  53040. + return 0;
  53041. +}
  53042. +#endif /* DWC_EN_ISOC */
  53043. +
  53044. +#ifdef DWC_UTE_PER_IO
  53045. +/**
  53046. + * Copy the contents of the extended request to the Linux usb_request's
  53047. + * extended part and call the gadget's completion.
  53048. + *
  53049. + * @param pcd Pointer to the pcd structure
  53050. + * @param ep_handle Void pointer to the usb_ep structure
  53051. + * @param req_handle Void pointer to the usb_request structure
  53052. + * @param status Request status returned from the portable logic
  53053. + * @param ereq_port Void pointer to the extended request structure
  53054. + * created in the the portable part that contains the
  53055. + * results of the processed iso packets.
  53056. + */
  53057. +static int _xisoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,
  53058. + void *req_handle, int32_t status, void *ereq_port)
  53059. +{
  53060. + struct dwc_ute_iso_req_ext *ereqorg = NULL;
  53061. + struct dwc_iso_xreq_port *ereqport = NULL;
  53062. + struct dwc_ute_iso_packet_descriptor *desc_org = NULL;
  53063. + int i;
  53064. + struct usb_request *req;
  53065. + //struct dwc_ute_iso_packet_descriptor *
  53066. + //int status = 0;
  53067. +
  53068. + req = (struct usb_request *)req_handle;
  53069. + ereqorg = &req->ext_req;
  53070. + ereqport = (struct dwc_iso_xreq_port *)ereq_port;
  53071. + desc_org = ereqorg->per_io_frame_descs;
  53072. +
  53073. + if (req && req->complete) {
  53074. + /* Copy the request data from the portable logic to our request */
  53075. + for (i = 0; i < ereqport->pio_pkt_count; i++) {
  53076. + desc_org[i].actual_length =
  53077. + ereqport->per_io_frame_descs[i].actual_length;
  53078. + desc_org[i].status =
  53079. + ereqport->per_io_frame_descs[i].status;
  53080. + }
  53081. +
  53082. + switch (status) {
  53083. + case -DWC_E_SHUTDOWN:
  53084. + req->status = -ESHUTDOWN;
  53085. + break;
  53086. + case -DWC_E_RESTART:
  53087. + req->status = -ECONNRESET;
  53088. + break;
  53089. + case -DWC_E_INVALID:
  53090. + req->status = -EINVAL;
  53091. + break;
  53092. + case -DWC_E_TIMEOUT:
  53093. + req->status = -ETIMEDOUT;
  53094. + break;
  53095. + default:
  53096. + req->status = status;
  53097. + }
  53098. +
  53099. + /* And call the gadget's completion */
  53100. + req->complete(ep_handle, req);
  53101. + }
  53102. +
  53103. + return 0;
  53104. +}
  53105. +#endif /* DWC_UTE_PER_IO */
  53106. +
  53107. +static int _complete(dwc_otg_pcd_t * pcd, void *ep_handle,
  53108. + void *req_handle, int32_t status, uint32_t actual)
  53109. +{
  53110. + struct usb_request *req = (struct usb_request *)req_handle;
  53111. +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)
  53112. + struct dwc_otg_pcd_ep *ep = NULL;
  53113. +#endif
  53114. +
  53115. + if (req && req->complete) {
  53116. + switch (status) {
  53117. + case -DWC_E_SHUTDOWN:
  53118. + req->status = -ESHUTDOWN;
  53119. + break;
  53120. + case -DWC_E_RESTART:
  53121. + req->status = -ECONNRESET;
  53122. + break;
  53123. + case -DWC_E_INVALID:
  53124. + req->status = -EINVAL;
  53125. + break;
  53126. + case -DWC_E_TIMEOUT:
  53127. + req->status = -ETIMEDOUT;
  53128. + break;
  53129. + default:
  53130. + req->status = status;
  53131. +
  53132. + }
  53133. +
  53134. + req->actual = actual;
  53135. + DWC_SPINUNLOCK(pcd->lock);
  53136. + req->complete(ep_handle, req);
  53137. + DWC_SPINLOCK(pcd->lock);
  53138. + }
  53139. +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)
  53140. + ep = ep_from_handle(pcd, ep_handle);
  53141. + if (GET_CORE_IF(pcd)->dma_enable) {
  53142. + if (req->length != 0) {
  53143. + dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev;
  53144. + struct device *dev = NULL;
  53145. +
  53146. + if (otg_dev != NULL)
  53147. + dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep);
  53148. +
  53149. + dma_unmap_single(dev, req->dma, req->length,
  53150. + ep->dwc_ep.is_in ?
  53151. + DMA_TO_DEVICE: DMA_FROM_DEVICE);
  53152. + }
  53153. + }
  53154. +#endif
  53155. +
  53156. + return 0;
  53157. +}
  53158. +
  53159. +static int _connect(dwc_otg_pcd_t * pcd, int speed)
  53160. +{
  53161. + gadget_wrapper->gadget.speed = speed;
  53162. + return 0;
  53163. +}
  53164. +
  53165. +static int _disconnect(dwc_otg_pcd_t * pcd)
  53166. +{
  53167. + if (gadget_wrapper->driver && gadget_wrapper->driver->disconnect) {
  53168. + gadget_wrapper->driver->disconnect(&gadget_wrapper->gadget);
  53169. + }
  53170. + return 0;
  53171. +}
  53172. +
  53173. +static int _resume(dwc_otg_pcd_t * pcd)
  53174. +{
  53175. + if (gadget_wrapper->driver && gadget_wrapper->driver->resume) {
  53176. + gadget_wrapper->driver->resume(&gadget_wrapper->gadget);
  53177. + }
  53178. +
  53179. + return 0;
  53180. +}
  53181. +
  53182. +static int _suspend(dwc_otg_pcd_t * pcd)
  53183. +{
  53184. + if (gadget_wrapper->driver && gadget_wrapper->driver->suspend) {
  53185. + gadget_wrapper->driver->suspend(&gadget_wrapper->gadget);
  53186. + }
  53187. + return 0;
  53188. +}
  53189. +
  53190. +/**
  53191. + * This function updates the otg values in the gadget structure.
  53192. + */
  53193. +static int _hnp_changed(dwc_otg_pcd_t * pcd)
  53194. +{
  53195. +
  53196. + if (!gadget_wrapper->gadget.is_otg)
  53197. + return 0;
  53198. +
  53199. + gadget_wrapper->gadget.b_hnp_enable = get_b_hnp_enable(pcd);
  53200. + gadget_wrapper->gadget.a_hnp_support = get_a_hnp_support(pcd);
  53201. + gadget_wrapper->gadget.a_alt_hnp_support = get_a_alt_hnp_support(pcd);
  53202. + return 0;
  53203. +}
  53204. +
  53205. +static int _reset(dwc_otg_pcd_t * pcd)
  53206. +{
  53207. + return 0;
  53208. +}
  53209. +
  53210. +#ifdef DWC_UTE_CFI
  53211. +static int _cfi_setup(dwc_otg_pcd_t * pcd, void *cfi_req)
  53212. +{
  53213. + int retval = -DWC_E_INVALID;
  53214. + if (gadget_wrapper->driver->cfi_feature_setup) {
  53215. + retval =
  53216. + gadget_wrapper->driver->
  53217. + cfi_feature_setup(&gadget_wrapper->gadget,
  53218. + (struct cfi_usb_ctrlrequest *)cfi_req);
  53219. + }
  53220. +
  53221. + return retval;
  53222. +}
  53223. +#endif
  53224. +
  53225. +static const struct dwc_otg_pcd_function_ops fops = {
  53226. + .complete = _complete,
  53227. +#ifdef DWC_EN_ISOC
  53228. + .isoc_complete = _isoc_complete,
  53229. +#endif
  53230. + .setup = _setup,
  53231. + .disconnect = _disconnect,
  53232. + .connect = _connect,
  53233. + .resume = _resume,
  53234. + .suspend = _suspend,
  53235. + .hnp_changed = _hnp_changed,
  53236. + .reset = _reset,
  53237. +#ifdef DWC_UTE_CFI
  53238. + .cfi_setup = _cfi_setup,
  53239. +#endif
  53240. +#ifdef DWC_UTE_PER_IO
  53241. + .xisoc_complete = _xisoc_complete,
  53242. +#endif
  53243. +};
  53244. +
  53245. +/**
  53246. + * This function is the top level PCD interrupt handler.
  53247. + */
  53248. +static irqreturn_t dwc_otg_pcd_irq(int irq, void *dev)
  53249. +{
  53250. + dwc_otg_pcd_t *pcd = dev;
  53251. + int32_t retval = IRQ_NONE;
  53252. +
  53253. + retval = dwc_otg_pcd_handle_intr(pcd);
  53254. + if (retval != 0) {
  53255. + S3C2410X_CLEAR_EINTPEND();
  53256. + }
  53257. + return IRQ_RETVAL(retval);
  53258. +}
  53259. +
  53260. +/**
  53261. + * This function initialized the usb_ep structures to there default
  53262. + * state.
  53263. + *
  53264. + * @param d Pointer on gadget_wrapper.
  53265. + */
  53266. +void gadget_add_eps(struct gadget_wrapper *d)
  53267. +{
  53268. + static const char *names[] = {
  53269. +
  53270. + "ep0",
  53271. + "ep1in",
  53272. + "ep2in",
  53273. + "ep3in",
  53274. + "ep4in",
  53275. + "ep5in",
  53276. + "ep6in",
  53277. + "ep7in",
  53278. + "ep8in",
  53279. + "ep9in",
  53280. + "ep10in",
  53281. + "ep11in",
  53282. + "ep12in",
  53283. + "ep13in",
  53284. + "ep14in",
  53285. + "ep15in",
  53286. + "ep1out",
  53287. + "ep2out",
  53288. + "ep3out",
  53289. + "ep4out",
  53290. + "ep5out",
  53291. + "ep6out",
  53292. + "ep7out",
  53293. + "ep8out",
  53294. + "ep9out",
  53295. + "ep10out",
  53296. + "ep11out",
  53297. + "ep12out",
  53298. + "ep13out",
  53299. + "ep14out",
  53300. + "ep15out"
  53301. + };
  53302. +
  53303. + int i;
  53304. + struct usb_ep *ep;
  53305. + int8_t dev_endpoints;
  53306. +
  53307. + DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__);
  53308. +
  53309. + INIT_LIST_HEAD(&d->gadget.ep_list);
  53310. + d->gadget.ep0 = &d->ep0;
  53311. + d->gadget.speed = USB_SPEED_UNKNOWN;
  53312. +
  53313. + INIT_LIST_HEAD(&d->gadget.ep0->ep_list);
  53314. +
  53315. + /**
  53316. + * Initialize the EP0 structure.
  53317. + */
  53318. + ep = &d->ep0;
  53319. +
  53320. + /* Init the usb_ep structure. */
  53321. + ep->name = names[0];
  53322. + ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
  53323. +
  53324. + /**
  53325. + * @todo NGS: What should the max packet size be set to
  53326. + * here? Before EP type is set?
  53327. + */
  53328. + ep->maxpacket = MAX_PACKET_SIZE;
  53329. + dwc_otg_pcd_ep_enable(d->pcd, NULL, ep);
  53330. +
  53331. + list_add_tail(&ep->ep_list, &d->gadget.ep_list);
  53332. +
  53333. + /**
  53334. + * Initialize the EP structures.
  53335. + */
  53336. + dev_endpoints = d->pcd->core_if->dev_if->num_in_eps;
  53337. +
  53338. + for (i = 0; i < dev_endpoints; i++) {
  53339. + ep = &d->in_ep[i];
  53340. +
  53341. + /* Init the usb_ep structure. */
  53342. + ep->name = names[d->pcd->in_ep[i].dwc_ep.num];
  53343. + ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
  53344. +
  53345. + /**
  53346. + * @todo NGS: What should the max packet size be set to
  53347. + * here? Before EP type is set?
  53348. + */
  53349. + ep->maxpacket = MAX_PACKET_SIZE;
  53350. + list_add_tail(&ep->ep_list, &d->gadget.ep_list);
  53351. + }
  53352. +
  53353. + dev_endpoints = d->pcd->core_if->dev_if->num_out_eps;
  53354. +
  53355. + for (i = 0; i < dev_endpoints; i++) {
  53356. + ep = &d->out_ep[i];
  53357. +
  53358. + /* Init the usb_ep structure. */
  53359. + ep->name = names[15 + d->pcd->out_ep[i].dwc_ep.num];
  53360. + ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
  53361. +
  53362. + /**
  53363. + * @todo NGS: What should the max packet size be set to
  53364. + * here? Before EP type is set?
  53365. + */
  53366. + ep->maxpacket = MAX_PACKET_SIZE;
  53367. +
  53368. + list_add_tail(&ep->ep_list, &d->gadget.ep_list);
  53369. + }
  53370. +
  53371. + /* remove ep0 from the list. There is a ep0 pointer. */
  53372. + list_del_init(&d->ep0.ep_list);
  53373. +
  53374. + d->ep0.maxpacket = MAX_EP0_SIZE;
  53375. +}
  53376. +
  53377. +/**
  53378. + * This function releases the Gadget device.
  53379. + * required by device_unregister().
  53380. + *
  53381. + * @todo Should this do something? Should it free the PCD?
  53382. + */
  53383. +static void dwc_otg_pcd_gadget_release(struct device *dev)
  53384. +{
  53385. + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev);
  53386. +}
  53387. +
  53388. +static struct gadget_wrapper *alloc_wrapper(dwc_bus_dev_t *_dev)
  53389. +{
  53390. + static char pcd_name[] = "dwc_otg_pcd";
  53391. + dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
  53392. + struct gadget_wrapper *d;
  53393. + int retval;
  53394. +
  53395. + d = DWC_ALLOC(sizeof(*d));
  53396. + if (d == NULL) {
  53397. + return NULL;
  53398. + }
  53399. +
  53400. + memset(d, 0, sizeof(*d));
  53401. +
  53402. + d->gadget.name = pcd_name;
  53403. + d->pcd = otg_dev->pcd;
  53404. +
  53405. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
  53406. + strcpy(d->gadget.dev.bus_id, "gadget");
  53407. +#else
  53408. + dev_set_name(&d->gadget.dev, "%s", "gadget");
  53409. +#endif
  53410. +
  53411. + d->gadget.dev.parent = &_dev->dev;
  53412. + d->gadget.dev.release = dwc_otg_pcd_gadget_release;
  53413. + d->gadget.ops = &dwc_otg_pcd_ops;
  53414. + d->gadget.max_speed = dwc_otg_pcd_is_dualspeed(otg_dev->pcd) ? USB_SPEED_HIGH:USB_SPEED_FULL;
  53415. + d->gadget.is_otg = dwc_otg_pcd_is_otg(otg_dev->pcd);
  53416. +
  53417. + d->driver = 0;
  53418. + /* Register the gadget device */
  53419. + retval = device_register(&d->gadget.dev);
  53420. + if (retval != 0) {
  53421. + DWC_ERROR("device_register failed\n");
  53422. + DWC_FREE(d);
  53423. + return NULL;
  53424. + }
  53425. +
  53426. + return d;
  53427. +}
  53428. +
  53429. +static void free_wrapper(struct gadget_wrapper *d)
  53430. +{
  53431. + if (d->driver) {
  53432. + /* should have been done already by driver model core */
  53433. + DWC_WARN("driver '%s' is still registered\n",
  53434. + d->driver->driver.name);
  53435. + usb_gadget_unregister_driver(d->driver);
  53436. + }
  53437. +
  53438. + device_unregister(&d->gadget.dev);
  53439. + DWC_FREE(d);
  53440. +}
  53441. +
  53442. +/**
  53443. + * This function initialized the PCD portion of the driver.
  53444. + *
  53445. + */
  53446. +int pcd_init(dwc_bus_dev_t *_dev)
  53447. +{
  53448. + dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
  53449. + int retval = 0;
  53450. +
  53451. + DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev=%p\n", __func__, _dev, otg_dev);
  53452. +
  53453. + otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if);
  53454. +
  53455. + if (!otg_dev->pcd) {
  53456. + DWC_ERROR("dwc_otg_pcd_init failed\n");
  53457. + return -ENOMEM;
  53458. + }
  53459. +
  53460. + otg_dev->pcd->otg_dev = otg_dev;
  53461. + gadget_wrapper = alloc_wrapper(_dev);
  53462. +
  53463. + /*
  53464. + * Initialize EP structures
  53465. + */
  53466. + gadget_add_eps(gadget_wrapper);
  53467. + /*
  53468. + * Setup interupt handler
  53469. + */
  53470. +#ifdef PLATFORM_INTERFACE
  53471. + DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
  53472. + platform_get_irq(_dev, 0));
  53473. + retval = request_irq(platform_get_irq(_dev, 0), dwc_otg_pcd_irq,
  53474. + IRQF_SHARED, gadget_wrapper->gadget.name,
  53475. + otg_dev->pcd);
  53476. + if (retval != 0) {
  53477. + DWC_ERROR("request of irq%d failed\n",
  53478. + platform_get_irq(_dev, 0));
  53479. + free_wrapper(gadget_wrapper);
  53480. + return -EBUSY;
  53481. + }
  53482. +#else
  53483. + DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n",
  53484. + _dev->irq);
  53485. + retval = request_irq(_dev->irq, dwc_otg_pcd_irq,
  53486. + IRQF_SHARED | IRQF_DISABLED,
  53487. + gadget_wrapper->gadget.name, otg_dev->pcd);
  53488. + if (retval != 0) {
  53489. + DWC_ERROR("request of irq%d failed\n", _dev->irq);
  53490. + free_wrapper(gadget_wrapper);
  53491. + return -EBUSY;
  53492. + }
  53493. +#endif
  53494. +
  53495. + dwc_otg_pcd_start(gadget_wrapper->pcd, &fops);
  53496. +
  53497. + return retval;
  53498. +}
  53499. +
  53500. +/**
  53501. + * Cleanup the PCD.
  53502. + */
  53503. +void pcd_remove(dwc_bus_dev_t *_dev)
  53504. +{
  53505. + dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev);
  53506. + dwc_otg_pcd_t *pcd = otg_dev->pcd;
  53507. +
  53508. + DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev);
  53509. +
  53510. + /*
  53511. + * Free the IRQ
  53512. + */
  53513. +#ifdef PLATFORM_INTERFACE
  53514. + free_irq(platform_get_irq(_dev, 0), pcd);
  53515. +#else
  53516. + free_irq(_dev->irq, pcd);
  53517. +#endif
  53518. + dwc_otg_pcd_remove(otg_dev->pcd);
  53519. + free_wrapper(gadget_wrapper);
  53520. + otg_dev->pcd = 0;
  53521. +}
  53522. +
  53523. +/**
  53524. + * This function registers a gadget driver with the PCD.
  53525. + *
  53526. + * When a driver is successfully registered, it will receive control
  53527. + * requests including set_configuration(), which enables non-control
  53528. + * requests. then usb traffic follows until a disconnect is reported.
  53529. + * then a host may connect again, or the driver might get unbound.
  53530. + *
  53531. + * @param driver The driver being registered
  53532. + * @param bind The bind function of gadget driver
  53533. + */
  53534. +
  53535. +int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
  53536. +{
  53537. + int retval;
  53538. +
  53539. + DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n",
  53540. + driver->driver.name);
  53541. +
  53542. + if (!driver || driver->max_speed == USB_SPEED_UNKNOWN ||
  53543. + !driver->bind ||
  53544. + !driver->unbind || !driver->disconnect || !driver->setup) {
  53545. + DWC_DEBUGPL(DBG_PCDV, "EINVAL\n");
  53546. + return -EINVAL;
  53547. + }
  53548. + if (gadget_wrapper == 0) {
  53549. + DWC_DEBUGPL(DBG_PCDV, "ENODEV\n");
  53550. + return -ENODEV;
  53551. + }
  53552. + if (gadget_wrapper->driver != 0) {
  53553. + DWC_DEBUGPL(DBG_PCDV, "EBUSY (%p)\n", gadget_wrapper->driver);
  53554. + return -EBUSY;
  53555. + }
  53556. +
  53557. + /* hook up the driver */
  53558. + gadget_wrapper->driver = driver;
  53559. + gadget_wrapper->gadget.dev.driver = &driver->driver;
  53560. +
  53561. + DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name);
  53562. + retval = driver->bind(&gadget_wrapper->gadget, gadget_wrapper->driver);
  53563. + if (retval) {
  53564. + DWC_ERROR("bind to driver %s --> error %d\n",
  53565. + driver->driver.name, retval);
  53566. + gadget_wrapper->driver = 0;
  53567. + gadget_wrapper->gadget.dev.driver = 0;
  53568. + return retval;
  53569. + }
  53570. + DWC_DEBUGPL(DBG_ANY, "registered gadget driver '%s'\n",
  53571. + driver->driver.name);
  53572. + return 0;
  53573. +}
  53574. +EXPORT_SYMBOL(usb_gadget_probe_driver);
  53575. +
  53576. +/**
  53577. + * This function unregisters a gadget driver
  53578. + *
  53579. + * @param driver The driver being unregistered
  53580. + */
  53581. +int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
  53582. +{
  53583. + //DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _driver);
  53584. +
  53585. + if (gadget_wrapper == 0) {
  53586. + DWC_DEBUGPL(DBG_ANY, "%s Return(%d): s_pcd==0\n", __func__,
  53587. + -ENODEV);
  53588. + return -ENODEV;
  53589. + }
  53590. + if (driver == 0 || driver != gadget_wrapper->driver) {
  53591. + DWC_DEBUGPL(DBG_ANY, "%s Return(%d): driver?\n", __func__,
  53592. + -EINVAL);
  53593. + return -EINVAL;
  53594. + }
  53595. +
  53596. + driver->unbind(&gadget_wrapper->gadget);
  53597. + gadget_wrapper->driver = 0;
  53598. +
  53599. + DWC_DEBUGPL(DBG_ANY, "unregistered driver '%s'\n", driver->driver.name);
  53600. + return 0;
  53601. +}
  53602. +
  53603. +EXPORT_SYMBOL(usb_gadget_unregister_driver);
  53604. +
  53605. +#endif /* DWC_HOST_ONLY */
  53606. --- /dev/null
  53607. +++ b/drivers/usb/host/dwc_otg/dwc_otg_regs.h
  53608. @@ -0,0 +1,2550 @@
  53609. +/* ==========================================================================
  53610. + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $
  53611. + * $Revision: #98 $
  53612. + * $Date: 2012/08/10 $
  53613. + * $Change: 2047372 $
  53614. + *
  53615. + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
  53616. + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
  53617. + * otherwise expressly agreed to in writing between Synopsys and you.
  53618. + *
  53619. + * The Software IS NOT an item of Licensed Software or Licensed Product under
  53620. + * any End User Software License Agreement or Agreement for Licensed Product
  53621. + * with Synopsys or any supplement thereto. You are permitted to use and
  53622. + * redistribute this Software in source and binary forms, with or without
  53623. + * modification, provided that redistributions of source code must retain this
  53624. + * notice. You may not view, use, disclose, copy or distribute this file or
  53625. + * any information contained herein except pursuant to this license grant from
  53626. + * Synopsys. If you do not agree with this notice, including the disclaimer
  53627. + * below, then you are not authorized to use the Software.
  53628. + *
  53629. + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
  53630. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  53631. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  53632. + * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
  53633. + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  53634. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  53635. + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  53636. + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  53637. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  53638. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  53639. + * DAMAGE.
  53640. + * ========================================================================== */
  53641. +
  53642. +#ifndef __DWC_OTG_REGS_H__
  53643. +#define __DWC_OTG_REGS_H__
  53644. +
  53645. +#include "dwc_otg_core_if.h"
  53646. +
  53647. +/**
  53648. + * @file
  53649. + *
  53650. + * This file contains the data structures for accessing the DWC_otg core registers.
  53651. + *
  53652. + * The application interfaces with the HS OTG core by reading from and
  53653. + * writing to the Control and Status Register (CSR) space through the
  53654. + * AHB Slave interface. These registers are 32 bits wide, and the
  53655. + * addresses are 32-bit-block aligned.
  53656. + * CSRs are classified as follows:
  53657. + * - Core Global Registers
  53658. + * - Device Mode Registers
  53659. + * - Device Global Registers
  53660. + * - Device Endpoint Specific Registers
  53661. + * - Host Mode Registers
  53662. + * - Host Global Registers
  53663. + * - Host Port CSRs
  53664. + * - Host Channel Specific Registers
  53665. + *
  53666. + * Only the Core Global registers can be accessed in both Device and
  53667. + * Host modes. When the HS OTG core is operating in one mode, either
  53668. + * Device or Host, the application must not access registers from the
  53669. + * other mode. When the core switches from one mode to another, the
  53670. + * registers in the new mode of operation must be reprogrammed as they
  53671. + * would be after a power-on reset.
  53672. + */
  53673. +
  53674. +/****************************************************************************/
  53675. +/** DWC_otg Core registers .
  53676. + * The dwc_otg_core_global_regs structure defines the size
  53677. + * and relative field offsets for the Core Global registers.
  53678. + */
  53679. +typedef struct dwc_otg_core_global_regs {
  53680. + /** OTG Control and Status Register. <i>Offset: 000h</i> */
  53681. + volatile uint32_t gotgctl;
  53682. + /** OTG Interrupt Register. <i>Offset: 004h</i> */
  53683. + volatile uint32_t gotgint;
  53684. + /**Core AHB Configuration Register. <i>Offset: 008h</i> */
  53685. + volatile uint32_t gahbcfg;
  53686. +
  53687. +#define DWC_GLBINTRMASK 0x0001
  53688. +#define DWC_DMAENABLE 0x0020
  53689. +#define DWC_NPTXEMPTYLVL_EMPTY 0x0080
  53690. +#define DWC_NPTXEMPTYLVL_HALFEMPTY 0x0000
  53691. +#define DWC_PTXEMPTYLVL_EMPTY 0x0100
  53692. +#define DWC_PTXEMPTYLVL_HALFEMPTY 0x0000
  53693. +
  53694. + /**Core USB Configuration Register. <i>Offset: 00Ch</i> */
  53695. + volatile uint32_t gusbcfg;
  53696. + /**Core Reset Register. <i>Offset: 010h</i> */
  53697. + volatile uint32_t grstctl;
  53698. + /**Core Interrupt Register. <i>Offset: 014h</i> */
  53699. + volatile uint32_t gintsts;
  53700. + /**Core Interrupt Mask Register. <i>Offset: 018h</i> */
  53701. + volatile uint32_t gintmsk;
  53702. + /**Receive Status Queue Read Register (Read Only). <i>Offset: 01Ch</i> */
  53703. + volatile uint32_t grxstsr;
  53704. + /**Receive Status Queue Read & POP Register (Read Only). <i>Offset: 020h</i>*/
  53705. + volatile uint32_t grxstsp;
  53706. + /**Receive FIFO Size Register. <i>Offset: 024h</i> */
  53707. + volatile uint32_t grxfsiz;
  53708. + /**Non Periodic Transmit FIFO Size Register. <i>Offset: 028h</i> */
  53709. + volatile uint32_t gnptxfsiz;
  53710. + /**Non Periodic Transmit FIFO/Queue Status Register (Read
  53711. + * Only). <i>Offset: 02Ch</i> */
  53712. + volatile uint32_t gnptxsts;
  53713. + /**I2C Access Register. <i>Offset: 030h</i> */
  53714. + volatile uint32_t gi2cctl;
  53715. + /**PHY Vendor Control Register. <i>Offset: 034h</i> */
  53716. + volatile uint32_t gpvndctl;
  53717. + /**General Purpose Input/Output Register. <i>Offset: 038h</i> */
  53718. + volatile uint32_t ggpio;
  53719. + /**User ID Register. <i>Offset: 03Ch</i> */
  53720. + volatile uint32_t guid;
  53721. + /**Synopsys ID Register (Read Only). <i>Offset: 040h</i> */
  53722. + volatile uint32_t gsnpsid;
  53723. + /**User HW Config1 Register (Read Only). <i>Offset: 044h</i> */
  53724. + volatile uint32_t ghwcfg1;
  53725. + /**User HW Config2 Register (Read Only). <i>Offset: 048h</i> */
  53726. + volatile uint32_t ghwcfg2;
  53727. +#define DWC_SLAVE_ONLY_ARCH 0
  53728. +#define DWC_EXT_DMA_ARCH 1
  53729. +#define DWC_INT_DMA_ARCH 2
  53730. +
  53731. +#define DWC_MODE_HNP_SRP_CAPABLE 0
  53732. +#define DWC_MODE_SRP_ONLY_CAPABLE 1
  53733. +#define DWC_MODE_NO_HNP_SRP_CAPABLE 2
  53734. +#define DWC_MODE_SRP_CAPABLE_DEVICE 3
  53735. +#define DWC_MODE_NO_SRP_CAPABLE_DEVICE 4
  53736. +#define DWC_MODE_SRP_CAPABLE_HOST 5
  53737. +#define DWC_MODE_NO_SRP_CAPABLE_HOST 6
  53738. +
  53739. + /**User HW Config3 Register (Read Only). <i>Offset: 04Ch</i> */
  53740. + volatile uint32_t ghwcfg3;
  53741. + /**User HW Config4 Register (Read Only). <i>Offset: 050h</i>*/
  53742. + volatile uint32_t ghwcfg4;
  53743. + /** Core LPM Configuration register <i>Offset: 054h</i>*/
  53744. + volatile uint32_t glpmcfg;
  53745. + /** Global PowerDn Register <i>Offset: 058h</i> */
  53746. + volatile uint32_t gpwrdn;
  53747. + /** Global DFIFO SW Config Register <i>Offset: 05Ch</i> */
  53748. + volatile uint32_t gdfifocfg;
  53749. + /** ADP Control Register <i>Offset: 060h</i> */
  53750. + volatile uint32_t adpctl;
  53751. + /** Reserved <i>Offset: 064h-0FFh</i> */
  53752. + volatile uint32_t reserved39[39];
  53753. + /** Host Periodic Transmit FIFO Size Register. <i>Offset: 100h</i> */
  53754. + volatile uint32_t hptxfsiz;
  53755. + /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled,
  53756. + otherwise Device Transmit FIFO#n Register.
  53757. + * <i>Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15).</i> */
  53758. + volatile uint32_t dtxfsiz[15];
  53759. +} dwc_otg_core_global_regs_t;
  53760. +
  53761. +/**
  53762. + * This union represents the bit fields of the Core OTG Control
  53763. + * and Status Register (GOTGCTL). Set the bits using the bit
  53764. + * fields then write the <i>d32</i> value to the register.
  53765. + */
  53766. +typedef union gotgctl_data {
  53767. + /** raw register data */
  53768. + uint32_t d32;
  53769. + /** register bits */
  53770. + struct {
  53771. + unsigned sesreqscs:1;
  53772. + unsigned sesreq:1;
  53773. + unsigned vbvalidoven:1;
  53774. + unsigned vbvalidovval:1;
  53775. + unsigned avalidoven:1;
  53776. + unsigned avalidovval:1;
  53777. + unsigned bvalidoven:1;
  53778. + unsigned bvalidovval:1;
  53779. + unsigned hstnegscs:1;
  53780. + unsigned hnpreq:1;
  53781. + unsigned hstsethnpen:1;
  53782. + unsigned devhnpen:1;
  53783. + unsigned reserved12_15:4;
  53784. + unsigned conidsts:1;
  53785. + unsigned dbnctime:1;
  53786. + unsigned asesvld:1;
  53787. + unsigned bsesvld:1;
  53788. + unsigned otgver:1;
  53789. + unsigned reserved1:1;
  53790. + unsigned multvalidbc:5;
  53791. + unsigned chirpen:1;
  53792. + unsigned reserved28_31:4;
  53793. + } b;
  53794. +} gotgctl_data_t;
  53795. +
  53796. +/**
  53797. + * This union represents the bit fields of the Core OTG Interrupt Register
  53798. + * (GOTGINT). Set/clear the bits using the bit fields then write the <i>d32</i>
  53799. + * value to the register.
  53800. + */
  53801. +typedef union gotgint_data {
  53802. + /** raw register data */
  53803. + uint32_t d32;
  53804. + /** register bits */
  53805. + struct {
  53806. + /** Current Mode */
  53807. + unsigned reserved0_1:2;
  53808. +
  53809. + /** Session End Detected */
  53810. + unsigned sesenddet:1;
  53811. +
  53812. + unsigned reserved3_7:5;
  53813. +
  53814. + /** Session Request Success Status Change */
  53815. + unsigned sesreqsucstschng:1;
  53816. + /** Host Negotiation Success Status Change */
  53817. + unsigned hstnegsucstschng:1;
  53818. +
  53819. + unsigned reserved10_16:7;
  53820. +
  53821. + /** Host Negotiation Detected */
  53822. + unsigned hstnegdet:1;
  53823. + /** A-Device Timeout Change */
  53824. + unsigned adevtoutchng:1;
  53825. + /** Debounce Done */
  53826. + unsigned debdone:1;
  53827. + /** Multi-Valued input changed */
  53828. + unsigned mvic:1;
  53829. +
  53830. + unsigned reserved31_21:11;
  53831. +
  53832. + } b;
  53833. +} gotgint_data_t;
  53834. +
  53835. +/**
  53836. + * This union represents the bit fields of the Core AHB Configuration
  53837. + * Register (GAHBCFG). Set/clear the bits using the bit fields then
  53838. + * write the <i>d32</i> value to the register.
  53839. + */
  53840. +typedef union gahbcfg_data {
  53841. + /** raw register data */
  53842. + uint32_t d32;
  53843. + /** register bits */
  53844. + struct {
  53845. + unsigned glblintrmsk:1;
  53846. +#define DWC_GAHBCFG_GLBINT_ENABLE 1
  53847. +
  53848. + unsigned hburstlen:4;
  53849. +#define DWC_GAHBCFG_INT_DMA_BURST_SINGLE 0
  53850. +#define DWC_GAHBCFG_INT_DMA_BURST_INCR 1
  53851. +#define DWC_GAHBCFG_INT_DMA_BURST_INCR4 3
  53852. +#define DWC_GAHBCFG_INT_DMA_BURST_INCR8 5
  53853. +#define DWC_GAHBCFG_INT_DMA_BURST_INCR16 7
  53854. +
  53855. + unsigned dmaenable:1;
  53856. +#define DWC_GAHBCFG_DMAENABLE 1
  53857. + unsigned reserved:1;
  53858. + unsigned nptxfemplvl_txfemplvl:1;
  53859. + unsigned ptxfemplvl:1;
  53860. +#define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY 1
  53861. +#define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0
  53862. + unsigned reserved9_20:12;
  53863. + unsigned remmemsupp:1;
  53864. + unsigned notialldmawrit:1;
  53865. + unsigned ahbsingle:1;
  53866. + unsigned reserved24_31:8;
  53867. + } b;
  53868. +} gahbcfg_data_t;
  53869. +
  53870. +/**
  53871. + * This union represents the bit fields of the Core USB Configuration
  53872. + * Register (GUSBCFG). Set the bits using the bit fields then write
  53873. + * the <i>d32</i> value to the register.
  53874. + */
  53875. +typedef union gusbcfg_data {
  53876. + /** raw register data */
  53877. + uint32_t d32;
  53878. + /** register bits */
  53879. + struct {
  53880. + unsigned toutcal:3;
  53881. + unsigned phyif:1;
  53882. + unsigned ulpi_utmi_sel:1;
  53883. + unsigned fsintf:1;
  53884. + unsigned physel:1;
  53885. + unsigned ddrsel:1;
  53886. + unsigned srpcap:1;
  53887. + unsigned hnpcap:1;
  53888. + unsigned usbtrdtim:4;
  53889. + unsigned reserved1:1;
  53890. + unsigned phylpwrclksel:1;
  53891. + unsigned otgutmifssel:1;
  53892. + unsigned ulpi_fsls:1;
  53893. + unsigned ulpi_auto_res:1;
  53894. + unsigned ulpi_clk_sus_m:1;
  53895. + unsigned ulpi_ext_vbus_drv:1;
  53896. + unsigned ulpi_int_vbus_indicator:1;
  53897. + unsigned term_sel_dl_pulse:1;
  53898. + unsigned indicator_complement:1;
  53899. + unsigned indicator_pass_through:1;
  53900. + unsigned ulpi_int_prot_dis:1;
  53901. + unsigned ic_usb_cap:1;
  53902. + unsigned ic_traffic_pull_remove:1;
  53903. + unsigned tx_end_delay:1;
  53904. + unsigned force_host_mode:1;
  53905. + unsigned force_dev_mode:1;
  53906. + unsigned reserved31:1;
  53907. + } b;
  53908. +} gusbcfg_data_t;
  53909. +
  53910. +/**
  53911. + * This union represents the bit fields of the Core Reset Register
  53912. + * (GRSTCTL). Set/clear the bits using the bit fields then write the
  53913. + * <i>d32</i> value to the register.
  53914. + */
  53915. +typedef union grstctl_data {
  53916. + /** raw register data */
  53917. + uint32_t d32;
  53918. + /** register bits */
  53919. + struct {
  53920. + /** Core Soft Reset (CSftRst) (Device and Host)
  53921. + *
  53922. + * The application can flush the control logic in the
  53923. + * entire core using this bit. This bit resets the
  53924. + * pipelines in the AHB Clock domain as well as the
  53925. + * PHY Clock domain.
  53926. + *
  53927. + * The state machines are reset to an IDLE state, the
  53928. + * control bits in the CSRs are cleared, all the
  53929. + * transmit FIFOs and the receive FIFO are flushed.
  53930. + *
  53931. + * The status mask bits that control the generation of
  53932. + * the interrupt, are cleared, to clear the
  53933. + * interrupt. The interrupt status bits are not
  53934. + * cleared, so the application can get the status of
  53935. + * any events that occurred in the core after it has
  53936. + * set this bit.
  53937. + *
  53938. + * Any transactions on the AHB are terminated as soon
  53939. + * as possible following the protocol. Any
  53940. + * transactions on the USB are terminated immediately.
  53941. + *
  53942. + * The configuration settings in the CSRs are
  53943. + * unchanged, so the software doesn't have to
  53944. + * reprogram these registers (Device
  53945. + * Configuration/Host Configuration/Core System
  53946. + * Configuration/Core PHY Configuration).
  53947. + *
  53948. + * The application can write to this bit, any time it
  53949. + * wants to reset the core. This is a self clearing
  53950. + * bit and the core clears this bit after all the
  53951. + * necessary logic is reset in the core, which may
  53952. + * take several clocks, depending on the current state
  53953. + * of the core.
  53954. + */
  53955. + unsigned csftrst:1;
  53956. + /** Hclk Soft Reset
  53957. + *
  53958. + * The application uses this bit to reset the control logic in
  53959. + * the AHB clock domain. Only AHB clock domain pipelines are
  53960. + * reset.
  53961. + */
  53962. + unsigned hsftrst:1;
  53963. + /** Host Frame Counter Reset (Host Only)<br>
  53964. + *
  53965. + * The application can reset the (micro)frame number
  53966. + * counter inside the core, using this bit. When the
  53967. + * (micro)frame counter is reset, the subsequent SOF
  53968. + * sent out by the core, will have a (micro)frame
  53969. + * number of 0.
  53970. + */
  53971. + unsigned hstfrm:1;
  53972. + /** In Token Sequence Learning Queue Flush
  53973. + * (INTknQFlsh) (Device Only)
  53974. + */
  53975. + unsigned intknqflsh:1;
  53976. + /** RxFIFO Flush (RxFFlsh) (Device and Host)
  53977. + *
  53978. + * The application can flush the entire Receive FIFO
  53979. + * using this bit. The application must first
  53980. + * ensure that the core is not in the middle of a
  53981. + * transaction. The application should write into
  53982. + * this bit, only after making sure that neither the
  53983. + * DMA engine is reading from the RxFIFO nor the MAC
  53984. + * is writing the data in to the FIFO. The
  53985. + * application should wait until the bit is cleared
  53986. + * before performing any other operations. This bit
  53987. + * will takes 8 clocks (slowest of PHY or AHB clock)
  53988. + * to clear.
  53989. + */
  53990. + unsigned rxfflsh:1;
  53991. + /** TxFIFO Flush (TxFFlsh) (Device and Host).
  53992. + *
  53993. + * This bit is used to selectively flush a single or
  53994. + * all transmit FIFOs. The application must first
  53995. + * ensure that the core is not in the middle of a
  53996. + * transaction. The application should write into
  53997. + * this bit, only after making sure that neither the
  53998. + * DMA engine is writing into the TxFIFO nor the MAC
  53999. + * is reading the data out of the FIFO. The
  54000. + * application should wait until the core clears this
  54001. + * bit, before performing any operations. This bit
  54002. + * will takes 8 clocks (slowest of PHY or AHB clock)
  54003. + * to clear.
  54004. + */
  54005. + unsigned txfflsh:1;
  54006. +
  54007. + /** TxFIFO Number (TxFNum) (Device and Host).
  54008. + *
  54009. + * This is the FIFO number which needs to be flushed,
  54010. + * using the TxFIFO Flush bit. This field should not
  54011. + * be changed until the TxFIFO Flush bit is cleared by
  54012. + * the core.
  54013. + * - 0x0 : Non Periodic TxFIFO Flush
  54014. + * - 0x1 : Periodic TxFIFO #1 Flush in device mode
  54015. + * or Periodic TxFIFO in host mode
  54016. + * - 0x2 : Periodic TxFIFO #2 Flush in device mode.
  54017. + * - ...
  54018. + * - 0xF : Periodic TxFIFO #15 Flush in device mode
  54019. + * - 0x10: Flush all the Transmit NonPeriodic and
  54020. + * Transmit Periodic FIFOs in the core
  54021. + */
  54022. + unsigned txfnum:5;
  54023. + /** Reserved */
  54024. + unsigned reserved11_29:19;
  54025. + /** DMA Request Signal. Indicated DMA request is in
  54026. + * probress. Used for debug purpose. */
  54027. + unsigned dmareq:1;
  54028. + /** AHB Master Idle. Indicates the AHB Master State
  54029. + * Machine is in IDLE condition. */
  54030. + unsigned ahbidle:1;
  54031. + } b;
  54032. +} grstctl_t;
  54033. +
  54034. +/**
  54035. + * This union represents the bit fields of the Core Interrupt Mask
  54036. + * Register (GINTMSK). Set/clear the bits using the bit fields then
  54037. + * write the <i>d32</i> value to the register.
  54038. + */
  54039. +typedef union gintmsk_data {
  54040. + /** raw register data */
  54041. + uint32_t d32;
  54042. + /** register bits */
  54043. + struct {
  54044. + unsigned reserved0:1;
  54045. + unsigned modemismatch:1;
  54046. + unsigned otgintr:1;
  54047. + unsigned sofintr:1;
  54048. + unsigned rxstsqlvl:1;
  54049. + unsigned nptxfempty:1;
  54050. + unsigned ginnakeff:1;
  54051. + unsigned goutnakeff:1;
  54052. + unsigned ulpickint:1;
  54053. + unsigned i2cintr:1;
  54054. + unsigned erlysuspend:1;
  54055. + unsigned usbsuspend:1;
  54056. + unsigned usbreset:1;
  54057. + unsigned enumdone:1;
  54058. + unsigned isooutdrop:1;
  54059. + unsigned eopframe:1;
  54060. + unsigned restoredone:1;
  54061. + unsigned epmismatch:1;
  54062. + unsigned inepintr:1;
  54063. + unsigned outepintr:1;
  54064. + unsigned incomplisoin:1;
  54065. + unsigned incomplisoout:1;
  54066. + unsigned fetsusp:1;
  54067. + unsigned resetdet:1;
  54068. + unsigned portintr:1;
  54069. + unsigned hcintr:1;
  54070. + unsigned ptxfempty:1;
  54071. + unsigned lpmtranrcvd:1;
  54072. + unsigned conidstschng:1;
  54073. + unsigned disconnect:1;
  54074. + unsigned sessreqintr:1;
  54075. + unsigned wkupintr:1;
  54076. + } b;
  54077. +} gintmsk_data_t;
  54078. +/**
  54079. + * This union represents the bit fields of the Core Interrupt Register
  54080. + * (GINTSTS). Set/clear the bits using the bit fields then write the
  54081. + * <i>d32</i> value to the register.
  54082. + */
  54083. +typedef union gintsts_data {
  54084. + /** raw register data */
  54085. + uint32_t d32;
  54086. +#define DWC_SOF_INTR_MASK 0x0008
  54087. + /** register bits */
  54088. + struct {
  54089. +#define DWC_HOST_MODE 1
  54090. + unsigned curmode:1;
  54091. + unsigned modemismatch:1;
  54092. + unsigned otgintr:1;
  54093. + unsigned sofintr:1;
  54094. + unsigned rxstsqlvl:1;
  54095. + unsigned nptxfempty:1;
  54096. + unsigned ginnakeff:1;
  54097. + unsigned goutnakeff:1;
  54098. + unsigned ulpickint:1;
  54099. + unsigned i2cintr:1;
  54100. + unsigned erlysuspend:1;
  54101. + unsigned usbsuspend:1;
  54102. + unsigned usbreset:1;
  54103. + unsigned enumdone:1;
  54104. + unsigned isooutdrop:1;
  54105. + unsigned eopframe:1;
  54106. + unsigned restoredone:1;
  54107. + unsigned epmismatch:1;
  54108. + unsigned inepint:1;
  54109. + unsigned outepintr:1;
  54110. + unsigned incomplisoin:1;
  54111. + unsigned incomplisoout:1;
  54112. + unsigned fetsusp:1;
  54113. + unsigned resetdet:1;
  54114. + unsigned portintr:1;
  54115. + unsigned hcintr:1;
  54116. + unsigned ptxfempty:1;
  54117. + unsigned lpmtranrcvd:1;
  54118. + unsigned conidstschng:1;
  54119. + unsigned disconnect:1;
  54120. + unsigned sessreqintr:1;
  54121. + unsigned wkupintr:1;
  54122. + } b;
  54123. +} gintsts_data_t;
  54124. +
  54125. +/**
  54126. + * This union represents the bit fields in the Device Receive Status Read and
  54127. + * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
  54128. + * element then read out the bits using the <i>b</i>it elements.
  54129. + */
  54130. +typedef union device_grxsts_data {
  54131. + /** raw register data */
  54132. + uint32_t d32;
  54133. + /** register bits */
  54134. + struct {
  54135. + unsigned epnum:4;
  54136. + unsigned bcnt:11;
  54137. + unsigned dpid:2;
  54138. +
  54139. +#define DWC_STS_DATA_UPDT 0x2 // OUT Data Packet
  54140. +#define DWC_STS_XFER_COMP 0x3 // OUT Data Transfer Complete
  54141. +
  54142. +#define DWC_DSTS_GOUT_NAK 0x1 // Global OUT NAK
  54143. +#define DWC_DSTS_SETUP_COMP 0x4 // Setup Phase Complete
  54144. +#define DWC_DSTS_SETUP_UPDT 0x6 // SETUP Packet
  54145. + unsigned pktsts:4;
  54146. + unsigned fn:4;
  54147. + unsigned reserved25_31:7;
  54148. + } b;
  54149. +} device_grxsts_data_t;
  54150. +
  54151. +/**
  54152. + * This union represents the bit fields in the Host Receive Status Read and
  54153. + * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
  54154. + * element then read out the bits using the <i>b</i>it elements.
  54155. + */
  54156. +typedef union host_grxsts_data {
  54157. + /** raw register data */
  54158. + uint32_t d32;
  54159. + /** register bits */
  54160. + struct {
  54161. + unsigned chnum:4;
  54162. + unsigned bcnt:11;
  54163. + unsigned dpid:2;
  54164. +
  54165. + unsigned pktsts:4;
  54166. +#define DWC_GRXSTS_PKTSTS_IN 0x2
  54167. +#define DWC_GRXSTS_PKTSTS_IN_XFER_COMP 0x3
  54168. +#define DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5
  54169. +#define DWC_GRXSTS_PKTSTS_CH_HALTED 0x7
  54170. +
  54171. + unsigned reserved21_31:11;
  54172. + } b;
  54173. +} host_grxsts_data_t;
  54174. +
  54175. +/**
  54176. + * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ,
  54177. + * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the <i>d32</i> element
  54178. + * then read out the bits using the <i>b</i>it elements.
  54179. + */
  54180. +typedef union fifosize_data {
  54181. + /** raw register data */
  54182. + uint32_t d32;
  54183. + /** register bits */
  54184. + struct {
  54185. + unsigned startaddr:16;
  54186. + unsigned depth:16;
  54187. + } b;
  54188. +} fifosize_data_t;
  54189. +
  54190. +/**
  54191. + * This union represents the bit fields in the Non-Periodic Transmit
  54192. + * FIFO/Queue Status Register (GNPTXSTS). Read the register into the
  54193. + * <i>d32</i> element then read out the bits using the <i>b</i>it
  54194. + * elements.
  54195. + */
  54196. +typedef union gnptxsts_data {
  54197. + /** raw register data */
  54198. + uint32_t d32;
  54199. + /** register bits */
  54200. + struct {
  54201. + unsigned nptxfspcavail:16;
  54202. + unsigned nptxqspcavail:8;
  54203. + /** Top of the Non-Periodic Transmit Request Queue
  54204. + * - bit 24 - Terminate (Last entry for the selected
  54205. + * channel/EP)
  54206. + * - bits 26:25 - Token Type
  54207. + * - 2'b00 - IN/OUT
  54208. + * - 2'b01 - Zero Length OUT
  54209. + * - 2'b10 - PING/Complete Split
  54210. + * - 2'b11 - Channel Halt
  54211. + * - bits 30:27 - Channel/EP Number
  54212. + */
  54213. + unsigned nptxqtop_terminate:1;
  54214. + unsigned nptxqtop_token:2;
  54215. + unsigned nptxqtop_chnep:4;
  54216. + unsigned reserved:1;
  54217. + } b;
  54218. +} gnptxsts_data_t;
  54219. +
  54220. +/**
  54221. + * This union represents the bit fields in the Transmit
  54222. + * FIFO Status Register (DTXFSTS). Read the register into the
  54223. + * <i>d32</i> element then read out the bits using the <i>b</i>it
  54224. + * elements.
  54225. + */
  54226. +typedef union dtxfsts_data {
  54227. + /** raw register data */
  54228. + uint32_t d32;
  54229. + /** register bits */
  54230. + struct {
  54231. + unsigned txfspcavail:16;
  54232. + unsigned reserved:16;
  54233. + } b;
  54234. +} dtxfsts_data_t;
  54235. +
  54236. +/**
  54237. + * This union represents the bit fields in the I2C Control Register
  54238. + * (I2CCTL). Read the register into the <i>d32</i> element then read out the
  54239. + * bits using the <i>b</i>it elements.
  54240. + */
  54241. +typedef union gi2cctl_data {
  54242. + /** raw register data */
  54243. + uint32_t d32;
  54244. + /** register bits */
  54245. + struct {
  54246. + unsigned rwdata:8;
  54247. + unsigned regaddr:8;
  54248. + unsigned addr:7;
  54249. + unsigned i2cen:1;
  54250. + unsigned ack:1;
  54251. + unsigned i2csuspctl:1;
  54252. + unsigned i2cdevaddr:2;
  54253. + unsigned i2cdatse0:1;
  54254. + unsigned reserved:1;
  54255. + unsigned rw:1;
  54256. + unsigned bsydne:1;
  54257. + } b;
  54258. +} gi2cctl_data_t;
  54259. +
  54260. +/**
  54261. + * This union represents the bit fields in the PHY Vendor Control Register
  54262. + * (GPVNDCTL). Read the register into the <i>d32</i> element then read out the
  54263. + * bits using the <i>b</i>it elements.
  54264. + */
  54265. +typedef union gpvndctl_data {
  54266. + /** raw register data */
  54267. + uint32_t d32;
  54268. + /** register bits */
  54269. + struct {
  54270. + unsigned regdata:8;
  54271. + unsigned vctrl:8;
  54272. + unsigned regaddr16_21:6;
  54273. + unsigned regwr:1;
  54274. + unsigned reserved23_24:2;
  54275. + unsigned newregreq:1;
  54276. + unsigned vstsbsy:1;
  54277. + unsigned vstsdone:1;
  54278. + unsigned reserved28_30:3;
  54279. + unsigned disulpidrvr:1;
  54280. + } b;
  54281. +} gpvndctl_data_t;
  54282. +
  54283. +/**
  54284. + * This union represents the bit fields in the General Purpose
  54285. + * Input/Output Register (GGPIO).
  54286. + * Read the register into the <i>d32</i> element then read out the
  54287. + * bits using the <i>b</i>it elements.
  54288. + */
  54289. +typedef union ggpio_data {
  54290. + /** raw register data */
  54291. + uint32_t d32;
  54292. + /** register bits */
  54293. + struct {
  54294. + unsigned gpi:16;
  54295. + unsigned gpo:16;
  54296. + } b;
  54297. +} ggpio_data_t;
  54298. +
  54299. +/**
  54300. + * This union represents the bit fields in the User ID Register
  54301. + * (GUID). Read the register into the <i>d32</i> element then read out the
  54302. + * bits using the <i>b</i>it elements.
  54303. + */
  54304. +typedef union guid_data {
  54305. + /** raw register data */
  54306. + uint32_t d32;
  54307. + /** register bits */
  54308. + struct {
  54309. + unsigned rwdata:32;
  54310. + } b;
  54311. +} guid_data_t;
  54312. +
  54313. +/**
  54314. + * This union represents the bit fields in the Synopsys ID Register
  54315. + * (GSNPSID). Read the register into the <i>d32</i> element then read out the
  54316. + * bits using the <i>b</i>it elements.
  54317. + */
  54318. +typedef union gsnpsid_data {
  54319. + /** raw register data */
  54320. + uint32_t d32;
  54321. + /** register bits */
  54322. + struct {
  54323. + unsigned rwdata:32;
  54324. + } b;
  54325. +} gsnpsid_data_t;
  54326. +
  54327. +/**
  54328. + * This union represents the bit fields in the User HW Config1
  54329. + * Register. Read the register into the <i>d32</i> element then read
  54330. + * out the bits using the <i>b</i>it elements.
  54331. + */
  54332. +typedef union hwcfg1_data {
  54333. + /** raw register data */
  54334. + uint32_t d32;
  54335. + /** register bits */
  54336. + struct {
  54337. + unsigned ep_dir0:2;
  54338. + unsigned ep_dir1:2;
  54339. + unsigned ep_dir2:2;
  54340. + unsigned ep_dir3:2;
  54341. + unsigned ep_dir4:2;
  54342. + unsigned ep_dir5:2;
  54343. + unsigned ep_dir6:2;
  54344. + unsigned ep_dir7:2;
  54345. + unsigned ep_dir8:2;
  54346. + unsigned ep_dir9:2;
  54347. + unsigned ep_dir10:2;
  54348. + unsigned ep_dir11:2;
  54349. + unsigned ep_dir12:2;
  54350. + unsigned ep_dir13:2;
  54351. + unsigned ep_dir14:2;
  54352. + unsigned ep_dir15:2;
  54353. + } b;
  54354. +} hwcfg1_data_t;
  54355. +
  54356. +/**
  54357. + * This union represents the bit fields in the User HW Config2
  54358. + * Register. Read the register into the <i>d32</i> element then read
  54359. + * out the bits using the <i>b</i>it elements.
  54360. + */
  54361. +typedef union hwcfg2_data {
  54362. + /** raw register data */
  54363. + uint32_t d32;
  54364. + /** register bits */
  54365. + struct {
  54366. + /* GHWCFG2 */
  54367. + unsigned op_mode:3;
  54368. +#define DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG 0
  54369. +#define DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1
  54370. +#define DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2
  54371. +#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3
  54372. +#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4
  54373. +#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5
  54374. +#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6
  54375. +
  54376. + unsigned architecture:2;
  54377. + unsigned point2point:1;
  54378. + unsigned hs_phy_type:2;
  54379. +#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0
  54380. +#define DWC_HWCFG2_HS_PHY_TYPE_UTMI 1
  54381. +#define DWC_HWCFG2_HS_PHY_TYPE_ULPI 2
  54382. +#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3
  54383. +
  54384. + unsigned fs_phy_type:2;
  54385. + unsigned num_dev_ep:4;
  54386. + unsigned num_host_chan:4;
  54387. + unsigned perio_ep_supported:1;
  54388. + unsigned dynamic_fifo:1;
  54389. + unsigned multi_proc_int:1;
  54390. + unsigned reserved21:1;
  54391. + unsigned nonperio_tx_q_depth:2;
  54392. + unsigned host_perio_tx_q_depth:2;
  54393. + unsigned dev_token_q_depth:5;
  54394. + unsigned otg_enable_ic_usb:1;
  54395. + } b;
  54396. +} hwcfg2_data_t;
  54397. +
  54398. +/**
  54399. + * This union represents the bit fields in the User HW Config3
  54400. + * Register. Read the register into the <i>d32</i> element then read
  54401. + * out the bits using the <i>b</i>it elements.
  54402. + */
  54403. +typedef union hwcfg3_data {
  54404. + /** raw register data */
  54405. + uint32_t d32;
  54406. + /** register bits */
  54407. + struct {
  54408. + /* GHWCFG3 */
  54409. + unsigned xfer_size_cntr_width:4;
  54410. + unsigned packet_size_cntr_width:3;
  54411. + unsigned otg_func:1;
  54412. + unsigned i2c:1;
  54413. + unsigned vendor_ctrl_if:1;
  54414. + unsigned optional_features:1;
  54415. + unsigned synch_reset_type:1;
  54416. + unsigned adp_supp:1;
  54417. + unsigned otg_enable_hsic:1;
  54418. + unsigned bc_support:1;
  54419. + unsigned otg_lpm_en:1;
  54420. + unsigned dfifo_depth:16;
  54421. + } b;
  54422. +} hwcfg3_data_t;
  54423. +
  54424. +/**
  54425. + * This union represents the bit fields in the User HW Config4
  54426. + * Register. Read the register into the <i>d32</i> element then read
  54427. + * out the bits using the <i>b</i>it elements.
  54428. + */
  54429. +typedef union hwcfg4_data {
  54430. + /** raw register data */
  54431. + uint32_t d32;
  54432. + /** register bits */
  54433. + struct {
  54434. + unsigned num_dev_perio_in_ep:4;
  54435. + unsigned power_optimiz:1;
  54436. + unsigned min_ahb_freq:1;
  54437. + unsigned hiber:1;
  54438. + unsigned xhiber:1;
  54439. + unsigned reserved:6;
  54440. + unsigned utmi_phy_data_width:2;
  54441. + unsigned num_dev_mode_ctrl_ep:4;
  54442. + unsigned iddig_filt_en:1;
  54443. + unsigned vbus_valid_filt_en:1;
  54444. + unsigned a_valid_filt_en:1;
  54445. + unsigned b_valid_filt_en:1;
  54446. + unsigned session_end_filt_en:1;
  54447. + unsigned ded_fifo_en:1;
  54448. + unsigned num_in_eps:4;
  54449. + unsigned desc_dma:1;
  54450. + unsigned desc_dma_dyn:1;
  54451. + } b;
  54452. +} hwcfg4_data_t;
  54453. +
  54454. +/**
  54455. + * This union represents the bit fields of the Core LPM Configuration
  54456. + * Register (GLPMCFG). Set the bits using bit fields then write
  54457. + * the <i>d32</i> value to the register.
  54458. + */
  54459. +typedef union glpmctl_data {
  54460. + /** raw register data */
  54461. + uint32_t d32;
  54462. + /** register bits */
  54463. + struct {
  54464. + /** LPM-Capable (LPMCap) (Device and Host)
  54465. + * The application uses this bit to control
  54466. + * the DWC_otg core LPM capabilities.
  54467. + */
  54468. + unsigned lpm_cap_en:1;
  54469. + /** LPM response programmed by application (AppL1Res) (Device)
  54470. + * Handshake response to LPM token pre-programmed
  54471. + * by device application software.
  54472. + */
  54473. + unsigned appl_resp:1;
  54474. + /** Host Initiated Resume Duration (HIRD) (Device and Host)
  54475. + * In Host mode this field indicates the value of HIRD
  54476. + * to be sent in an LPM transaction.
  54477. + * In Device mode this field is updated with the
  54478. + * Received LPM Token HIRD bmAttribute
  54479. + * when an ACK/NYET/STALL response is sent
  54480. + * to an LPM transaction.
  54481. + */
  54482. + unsigned hird:4;
  54483. + /** RemoteWakeEnable (bRemoteWake) (Device and Host)
  54484. + * In Host mode this bit indicates the value of remote
  54485. + * wake up to be sent in wIndex field of LPM transaction.
  54486. + * In Device mode this field is updated with the
  54487. + * Received LPM Token bRemoteWake bmAttribute
  54488. + * when an ACK/NYET/STALL response is sent
  54489. + * to an LPM transaction.
  54490. + */
  54491. + unsigned rem_wkup_en:1;
  54492. + /** Enable utmi_sleep_n (EnblSlpM) (Device and Host)
  54493. + * The application uses this bit to control
  54494. + * the utmi_sleep_n assertion to the PHY when in L1 state.
  54495. + */
  54496. + unsigned en_utmi_sleep:1;
  54497. + /** HIRD Threshold (HIRD_Thres) (Device and Host)
  54498. + */
  54499. + unsigned hird_thres:5;
  54500. + /** LPM Response (CoreL1Res) (Device and Host)
  54501. + * In Host mode this bit contains handsake response to
  54502. + * LPM transaction.
  54503. + * In Device mode the response of the core to
  54504. + * LPM transaction received is reflected in these two bits.
  54505. + - 0x0 : ERROR (No handshake response)
  54506. + - 0x1 : STALL
  54507. + - 0x2 : NYET
  54508. + - 0x3 : ACK
  54509. + */
  54510. + unsigned lpm_resp:2;
  54511. + /** Port Sleep Status (SlpSts) (Device and Host)
  54512. + * This bit is set as long as a Sleep condition
  54513. + * is present on the USB bus.
  54514. + */
  54515. + unsigned prt_sleep_sts:1;
  54516. + /** Sleep State Resume OK (L1ResumeOK) (Device and Host)
  54517. + * Indicates that the application or host
  54518. + * can start resume from Sleep state.
  54519. + */
  54520. + unsigned sleep_state_resumeok:1;
  54521. + /** LPM channel Index (LPM_Chnl_Indx) (Host)
  54522. + * The channel number on which the LPM transaction
  54523. + * has to be applied while sending
  54524. + * an LPM transaction to the local device.
  54525. + */
  54526. + unsigned lpm_chan_index:4;
  54527. + /** LPM Retry Count (LPM_Retry_Cnt) (Host)
  54528. + * Number host retries that would be performed
  54529. + * if the device response was not valid response.
  54530. + */
  54531. + unsigned retry_count:3;
  54532. + /** Send LPM Transaction (SndLPM) (Host)
  54533. + * When set by application software,
  54534. + * an LPM transaction containing two tokens
  54535. + * is sent.
  54536. + */
  54537. + unsigned send_lpm:1;
  54538. + /** LPM Retry status (LPM_RetryCnt_Sts) (Host)
  54539. + * Number of LPM Host Retries still remaining
  54540. + * to be transmitted for the current LPM sequence
  54541. + */
  54542. + unsigned retry_count_sts:3;
  54543. + unsigned reserved28_29:2;
  54544. + /** In host mode once this bit is set, the host
  54545. + * configures to drive the HSIC Idle state on the bus.
  54546. + * It then waits for the device to initiate the Connect sequence.
  54547. + * In device mode once this bit is set, the device waits for
  54548. + * the HSIC Idle line state on the bus. Upon receving the Idle
  54549. + * line state, it initiates the HSIC Connect sequence.
  54550. + */
  54551. + unsigned hsic_connect:1;
  54552. + /** This bit overrides and functionally inverts
  54553. + * the if_select_hsic input port signal.
  54554. + */
  54555. + unsigned inv_sel_hsic:1;
  54556. + } b;
  54557. +} glpmcfg_data_t;
  54558. +
  54559. +/**
  54560. + * This union represents the bit fields of the Core ADP Timer, Control and
  54561. + * Status Register (ADPTIMCTLSTS). Set the bits using bit fields then write
  54562. + * the <i>d32</i> value to the register.
  54563. + */
  54564. +typedef union adpctl_data {
  54565. + /** raw register data */
  54566. + uint32_t d32;
  54567. + /** register bits */
  54568. + struct {
  54569. + /** Probe Discharge (PRB_DSCHG)
  54570. + * These bits set the times for TADP_DSCHG.
  54571. + * These bits are defined as follows:
  54572. + * 2'b00 - 4 msec
  54573. + * 2'b01 - 8 msec
  54574. + * 2'b10 - 16 msec
  54575. + * 2'b11 - 32 msec
  54576. + */
  54577. + unsigned prb_dschg:2;
  54578. + /** Probe Delta (PRB_DELTA)
  54579. + * These bits set the resolution for RTIM value.
  54580. + * The bits are defined in units of 32 kHz clock cycles as follows:
  54581. + * 2'b00 - 1 cycles
  54582. + * 2'b01 - 2 cycles
  54583. + * 2'b10 - 3 cycles
  54584. + * 2'b11 - 4 cycles
  54585. + * For example if this value is chosen to 2'b01, it means that RTIM
  54586. + * increments for every 3(three) 32Khz clock cycles.
  54587. + */
  54588. + unsigned prb_delta:2;
  54589. + /** Probe Period (PRB_PER)
  54590. + * These bits sets the TADP_PRD as shown in Figure 4 as follows:
  54591. + * 2'b00 - 0.625 to 0.925 sec (typical 0.775 sec)
  54592. + * 2'b01 - 1.25 to 1.85 sec (typical 1.55 sec)
  54593. + * 2'b10 - 1.9 to 2.6 sec (typical 2.275 sec)
  54594. + * 2'b11 - Reserved
  54595. + */
  54596. + unsigned prb_per:2;
  54597. + /** These bits capture the latest time it took for VBUS to ramp from
  54598. + * VADP_SINK to VADP_PRB.
  54599. + * 0x000 - 1 cycles
  54600. + * 0x001 - 2 cycles
  54601. + * 0x002 - 3 cycles
  54602. + * etc
  54603. + * 0x7FF - 2048 cycles
  54604. + * A time of 1024 cycles at 32 kHz corresponds to a time of 32 msec.
  54605. + */
  54606. + unsigned rtim:11;
  54607. + /** Enable Probe (EnaPrb)
  54608. + * When programmed to 1'b1, the core performs a probe operation.
  54609. + * This bit is valid only if OTG_Ver = 1'b1.
  54610. + */
  54611. + unsigned enaprb:1;
  54612. + /** Enable Sense (EnaSns)
  54613. + * When programmed to 1'b1, the core performs a Sense operation.
  54614. + * This bit is valid only if OTG_Ver = 1'b1.
  54615. + */
  54616. + unsigned enasns:1;
  54617. + /** ADP Reset (ADPRes)
  54618. + * When set, ADP controller is reset.
  54619. + * This bit is valid only if OTG_Ver = 1'b1.
  54620. + */
  54621. + unsigned adpres:1;
  54622. + /** ADP Enable (ADPEn)
  54623. + * When set, the core performs either ADP probing or sensing
  54624. + * based on EnaPrb or EnaSns.
  54625. + * This bit is valid only if OTG_Ver = 1'b1.
  54626. + */
  54627. + unsigned adpen:1;
  54628. + /** ADP Probe Interrupt (ADP_PRB_INT)
  54629. + * When this bit is set, it means that the VBUS
  54630. + * voltage is greater than VADP_PRB or VADP_PRB is reached.
  54631. + * This bit is valid only if OTG_Ver = 1'b1.
  54632. + */
  54633. + unsigned adp_prb_int:1;
  54634. + /**
  54635. + * ADP Sense Interrupt (ADP_SNS_INT)
  54636. + * When this bit is set, it means that the VBUS voltage is greater than
  54637. + * VADP_SNS value or VADP_SNS is reached.
  54638. + * This bit is valid only if OTG_Ver = 1'b1.
  54639. + */
  54640. + unsigned adp_sns_int:1;
  54641. + /** ADP Tomeout Interrupt (ADP_TMOUT_INT)
  54642. + * This bit is relevant only for an ADP probe.
  54643. + * When this bit is set, it means that the ramp time has
  54644. + * completed ie ADPCTL.RTIM has reached its terminal value
  54645. + * of 0x7FF. This is a debug feature that allows software
  54646. + * to read the ramp time after each cycle.
  54647. + * This bit is valid only if OTG_Ver = 1'b1.
  54648. + */
  54649. + unsigned adp_tmout_int:1;
  54650. + /** ADP Probe Interrupt Mask (ADP_PRB_INT_MSK)
  54651. + * When this bit is set, it unmasks the interrupt due to ADP_PRB_INT.
  54652. + * This bit is valid only if OTG_Ver = 1'b1.
  54653. + */
  54654. + unsigned adp_prb_int_msk:1;
  54655. + /** ADP Sense Interrupt Mask (ADP_SNS_INT_MSK)
  54656. + * When this bit is set, it unmasks the interrupt due to ADP_SNS_INT.
  54657. + * This bit is valid only if OTG_Ver = 1'b1.
  54658. + */
  54659. + unsigned adp_sns_int_msk:1;
  54660. + /** ADP Timoeout Interrupt Mask (ADP_TMOUT_MSK)
  54661. + * When this bit is set, it unmasks the interrupt due to ADP_TMOUT_INT.
  54662. + * This bit is valid only if OTG_Ver = 1'b1.
  54663. + */
  54664. + unsigned adp_tmout_int_msk:1;
  54665. + /** Access Request
  54666. + * 2'b00 - Read/Write Valid (updated by the core)
  54667. + * 2'b01 - Read
  54668. + * 2'b00 - Write
  54669. + * 2'b00 - Reserved
  54670. + */
  54671. + unsigned ar:2;
  54672. + /** Reserved */
  54673. + unsigned reserved29_31:3;
  54674. + } b;
  54675. +} adpctl_data_t;
  54676. +
  54677. +////////////////////////////////////////////
  54678. +// Device Registers
  54679. +/**
  54680. + * Device Global Registers. <i>Offsets 800h-BFFh</i>
  54681. + *
  54682. + * The following structures define the size and relative field offsets
  54683. + * for the Device Mode Registers.
  54684. + *
  54685. + * <i>These registers are visible only in Device mode and must not be
  54686. + * accessed in Host mode, as the results are unknown.</i>
  54687. + */
  54688. +typedef struct dwc_otg_dev_global_regs {
  54689. + /** Device Configuration Register. <i>Offset 800h</i> */
  54690. + volatile uint32_t dcfg;
  54691. + /** Device Control Register. <i>Offset: 804h</i> */
  54692. + volatile uint32_t dctl;
  54693. + /** Device Status Register (Read Only). <i>Offset: 808h</i> */
  54694. + volatile uint32_t dsts;
  54695. + /** Reserved. <i>Offset: 80Ch</i> */
  54696. + uint32_t unused;
  54697. + /** Device IN Endpoint Common Interrupt Mask
  54698. + * Register. <i>Offset: 810h</i> */
  54699. + volatile uint32_t diepmsk;
  54700. + /** Device OUT Endpoint Common Interrupt Mask
  54701. + * Register. <i>Offset: 814h</i> */
  54702. + volatile uint32_t doepmsk;
  54703. + /** Device All Endpoints Interrupt Register. <i>Offset: 818h</i> */
  54704. + volatile uint32_t daint;
  54705. + /** Device All Endpoints Interrupt Mask Register. <i>Offset:
  54706. + * 81Ch</i> */
  54707. + volatile uint32_t daintmsk;
  54708. + /** Device IN Token Queue Read Register-1 (Read Only).
  54709. + * <i>Offset: 820h</i> */
  54710. + volatile uint32_t dtknqr1;
  54711. + /** Device IN Token Queue Read Register-2 (Read Only).
  54712. + * <i>Offset: 824h</i> */
  54713. + volatile uint32_t dtknqr2;
  54714. + /** Device VBUS discharge Register. <i>Offset: 828h</i> */
  54715. + volatile uint32_t dvbusdis;
  54716. + /** Device VBUS Pulse Register. <i>Offset: 82Ch</i> */
  54717. + volatile uint32_t dvbuspulse;
  54718. + /** Device IN Token Queue Read Register-3 (Read Only). /
  54719. + * Device Thresholding control register (Read/Write)
  54720. + * <i>Offset: 830h</i> */
  54721. + volatile uint32_t dtknqr3_dthrctl;
  54722. + /** Device IN Token Queue Read Register-4 (Read Only). /
  54723. + * Device IN EPs empty Inr. Mask Register (Read/Write)
  54724. + * <i>Offset: 834h</i> */
  54725. + volatile uint32_t dtknqr4_fifoemptymsk;
  54726. + /** Device Each Endpoint Interrupt Register (Read Only). /
  54727. + * <i>Offset: 838h</i> */
  54728. + volatile uint32_t deachint;
  54729. + /** Device Each Endpoint Interrupt mask Register (Read/Write). /
  54730. + * <i>Offset: 83Ch</i> */
  54731. + volatile uint32_t deachintmsk;
  54732. + /** Device Each In Endpoint Interrupt mask Register (Read/Write). /
  54733. + * <i>Offset: 840h</i> */
  54734. + volatile uint32_t diepeachintmsk[MAX_EPS_CHANNELS];
  54735. + /** Device Each Out Endpoint Interrupt mask Register (Read/Write). /
  54736. + * <i>Offset: 880h</i> */
  54737. + volatile uint32_t doepeachintmsk[MAX_EPS_CHANNELS];
  54738. +} dwc_otg_device_global_regs_t;
  54739. +
  54740. +/**
  54741. + * This union represents the bit fields in the Device Configuration
  54742. + * Register. Read the register into the <i>d32</i> member then
  54743. + * set/clear the bits using the <i>b</i>it elements. Write the
  54744. + * <i>d32</i> member to the dcfg register.
  54745. + */
  54746. +typedef union dcfg_data {
  54747. + /** raw register data */
  54748. + uint32_t d32;
  54749. + /** register bits */
  54750. + struct {
  54751. + /** Device Speed */
  54752. + unsigned devspd:2;
  54753. + /** Non Zero Length Status OUT Handshake */
  54754. + unsigned nzstsouthshk:1;
  54755. +#define DWC_DCFG_SEND_STALL 1
  54756. +
  54757. + unsigned ena32khzs:1;
  54758. + /** Device Addresses */
  54759. + unsigned devaddr:7;
  54760. + /** Periodic Frame Interval */
  54761. + unsigned perfrint:2;
  54762. +#define DWC_DCFG_FRAME_INTERVAL_80 0
  54763. +#define DWC_DCFG_FRAME_INTERVAL_85 1
  54764. +#define DWC_DCFG_FRAME_INTERVAL_90 2
  54765. +#define DWC_DCFG_FRAME_INTERVAL_95 3
  54766. +
  54767. + /** Enable Device OUT NAK for bulk in DDMA mode */
  54768. + unsigned endevoutnak:1;
  54769. +
  54770. + unsigned reserved14_17:4;
  54771. + /** In Endpoint Mis-match count */
  54772. + unsigned epmscnt:5;
  54773. + /** Enable Descriptor DMA in Device mode */
  54774. + unsigned descdma:1;
  54775. + unsigned perschintvl:2;
  54776. + unsigned resvalid:6;
  54777. + } b;
  54778. +} dcfg_data_t;
  54779. +
  54780. +/**
  54781. + * This union represents the bit fields in the Device Control
  54782. + * Register. Read the register into the <i>d32</i> member then
  54783. + * set/clear the bits using the <i>b</i>it elements.
  54784. + */
  54785. +typedef union dctl_data {
  54786. + /** raw register data */
  54787. + uint32_t d32;
  54788. + /** register bits */
  54789. + struct {
  54790. + /** Remote Wakeup */
  54791. + unsigned rmtwkupsig:1;
  54792. + /** Soft Disconnect */
  54793. + unsigned sftdiscon:1;
  54794. + /** Global Non-Periodic IN NAK Status */
  54795. + unsigned gnpinnaksts:1;
  54796. + /** Global OUT NAK Status */
  54797. + unsigned goutnaksts:1;
  54798. + /** Test Control */
  54799. + unsigned tstctl:3;
  54800. + /** Set Global Non-Periodic IN NAK */
  54801. + unsigned sgnpinnak:1;
  54802. + /** Clear Global Non-Periodic IN NAK */
  54803. + unsigned cgnpinnak:1;
  54804. + /** Set Global OUT NAK */
  54805. + unsigned sgoutnak:1;
  54806. + /** Clear Global OUT NAK */
  54807. + unsigned cgoutnak:1;
  54808. + /** Power-On Programming Done */
  54809. + unsigned pwronprgdone:1;
  54810. + /** Reserved */
  54811. + unsigned reserved:1;
  54812. + /** Global Multi Count */
  54813. + unsigned gmc:2;
  54814. + /** Ignore Frame Number for ISOC EPs */
  54815. + unsigned ifrmnum:1;
  54816. + /** NAK on Babble */
  54817. + unsigned nakonbble:1;
  54818. + /** Enable Continue on BNA */
  54819. + unsigned encontonbna:1;
  54820. +
  54821. + unsigned reserved18_31:14;
  54822. + } b;
  54823. +} dctl_data_t;
  54824. +
  54825. +/**
  54826. + * This union represents the bit fields in the Device Status
  54827. + * Register. Read the register into the <i>d32</i> member then
  54828. + * set/clear the bits using the <i>b</i>it elements.
  54829. + */
  54830. +typedef union dsts_data {
  54831. + /** raw register data */
  54832. + uint32_t d32;
  54833. + /** register bits */
  54834. + struct {
  54835. + /** Suspend Status */
  54836. + unsigned suspsts:1;
  54837. + /** Enumerated Speed */
  54838. + unsigned enumspd:2;
  54839. +#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0
  54840. +#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1
  54841. +#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ 2
  54842. +#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ 3
  54843. + /** Erratic Error */
  54844. + unsigned errticerr:1;
  54845. + unsigned reserved4_7:4;
  54846. + /** Frame or Microframe Number of the received SOF */
  54847. + unsigned soffn:14;
  54848. + unsigned reserved22_31:10;
  54849. + } b;
  54850. +} dsts_data_t;
  54851. +
  54852. +/**
  54853. + * This union represents the bit fields in the Device IN EP Interrupt
  54854. + * Register and the Device IN EP Common Mask Register.
  54855. + *
  54856. + * - Read the register into the <i>d32</i> member then set/clear the
  54857. + * bits using the <i>b</i>it elements.
  54858. + */
  54859. +typedef union diepint_data {
  54860. + /** raw register data */
  54861. + uint32_t d32;
  54862. + /** register bits */
  54863. + struct {
  54864. + /** Transfer complete mask */
  54865. + unsigned xfercompl:1;
  54866. + /** Endpoint disable mask */
  54867. + unsigned epdisabled:1;
  54868. + /** AHB Error mask */
  54869. + unsigned ahberr:1;
  54870. + /** TimeOUT Handshake mask (non-ISOC EPs) */
  54871. + unsigned timeout:1;
  54872. + /** IN Token received with TxF Empty mask */
  54873. + unsigned intktxfemp:1;
  54874. + /** IN Token Received with EP mismatch mask */
  54875. + unsigned intknepmis:1;
  54876. + /** IN Endpoint NAK Effective mask */
  54877. + unsigned inepnakeff:1;
  54878. + /** Reserved */
  54879. + unsigned emptyintr:1;
  54880. +
  54881. + unsigned txfifoundrn:1;
  54882. +
  54883. + /** BNA Interrupt mask */
  54884. + unsigned bna:1;
  54885. +
  54886. + unsigned reserved10_12:3;
  54887. + /** BNA Interrupt mask */
  54888. + unsigned nak:1;
  54889. +
  54890. + unsigned reserved14_31:18;
  54891. + } b;
  54892. +} diepint_data_t;
  54893. +
  54894. +/**
  54895. + * This union represents the bit fields in the Device IN EP
  54896. + * Common/Dedicated Interrupt Mask Register.
  54897. + */
  54898. +typedef union diepint_data diepmsk_data_t;
  54899. +
  54900. +/**
  54901. + * This union represents the bit fields in the Device OUT EP Interrupt
  54902. + * Registerand Device OUT EP Common Interrupt Mask Register.
  54903. + *
  54904. + * - Read the register into the <i>d32</i> member then set/clear the
  54905. + * bits using the <i>b</i>it elements.
  54906. + */
  54907. +typedef union doepint_data {
  54908. + /** raw register data */
  54909. + uint32_t d32;
  54910. + /** register bits */
  54911. + struct {
  54912. + /** Transfer complete */
  54913. + unsigned xfercompl:1;
  54914. + /** Endpoint disable */
  54915. + unsigned epdisabled:1;
  54916. + /** AHB Error */
  54917. + unsigned ahberr:1;
  54918. + /** Setup Phase Done (contorl EPs) */
  54919. + unsigned setup:1;
  54920. + /** OUT Token Received when Endpoint Disabled */
  54921. + unsigned outtknepdis:1;
  54922. +
  54923. + unsigned stsphsercvd:1;
  54924. + /** Back-to-Back SETUP Packets Received */
  54925. + unsigned back2backsetup:1;
  54926. +
  54927. + unsigned reserved7:1;
  54928. + /** OUT packet Error */
  54929. + unsigned outpkterr:1;
  54930. + /** BNA Interrupt */
  54931. + unsigned bna:1;
  54932. +
  54933. + unsigned reserved10:1;
  54934. + /** Packet Drop Status */
  54935. + unsigned pktdrpsts:1;
  54936. + /** Babble Interrupt */
  54937. + unsigned babble:1;
  54938. + /** NAK Interrupt */
  54939. + unsigned nak:1;
  54940. + /** NYET Interrupt */
  54941. + unsigned nyet:1;
  54942. + /** Bit indicating setup packet received */
  54943. + unsigned sr:1;
  54944. +
  54945. + unsigned reserved16_31:16;
  54946. + } b;
  54947. +} doepint_data_t;
  54948. +
  54949. +/**
  54950. + * This union represents the bit fields in the Device OUT EP
  54951. + * Common/Dedicated Interrupt Mask Register.
  54952. + */
  54953. +typedef union doepint_data doepmsk_data_t;
  54954. +
  54955. +/**
  54956. + * This union represents the bit fields in the Device All EP Interrupt
  54957. + * and Mask Registers.
  54958. + * - Read the register into the <i>d32</i> member then set/clear the
  54959. + * bits using the <i>b</i>it elements.
  54960. + */
  54961. +typedef union daint_data {
  54962. + /** raw register data */
  54963. + uint32_t d32;
  54964. + /** register bits */
  54965. + struct {
  54966. + /** IN Endpoint bits */
  54967. + unsigned in:16;
  54968. + /** OUT Endpoint bits */
  54969. + unsigned out:16;
  54970. + } ep;
  54971. + struct {
  54972. + /** IN Endpoint bits */
  54973. + unsigned inep0:1;
  54974. + unsigned inep1:1;
  54975. + unsigned inep2:1;
  54976. + unsigned inep3:1;
  54977. + unsigned inep4:1;
  54978. + unsigned inep5:1;
  54979. + unsigned inep6:1;
  54980. + unsigned inep7:1;
  54981. + unsigned inep8:1;
  54982. + unsigned inep9:1;
  54983. + unsigned inep10:1;
  54984. + unsigned inep11:1;
  54985. + unsigned inep12:1;
  54986. + unsigned inep13:1;
  54987. + unsigned inep14:1;
  54988. + unsigned inep15:1;
  54989. + /** OUT Endpoint bits */
  54990. + unsigned outep0:1;
  54991. + unsigned outep1:1;
  54992. + unsigned outep2:1;
  54993. + unsigned outep3:1;
  54994. + unsigned outep4:1;
  54995. + unsigned outep5:1;
  54996. + unsigned outep6:1;
  54997. + unsigned outep7:1;
  54998. + unsigned outep8:1;
  54999. + unsigned outep9:1;
  55000. + unsigned outep10:1;
  55001. + unsigned outep11:1;
  55002. + unsigned outep12:1;
  55003. + unsigned outep13:1;
  55004. + unsigned outep14:1;
  55005. + unsigned outep15:1;
  55006. + } b;
  55007. +} daint_data_t;
  55008. +
  55009. +/**
  55010. + * This union represents the bit fields in the Device IN Token Queue
  55011. + * Read Registers.
  55012. + * - Read the register into the <i>d32</i> member.
  55013. + * - READ-ONLY Register
  55014. + */
  55015. +typedef union dtknq1_data {
  55016. + /** raw register data */
  55017. + uint32_t d32;
  55018. + /** register bits */
  55019. + struct {
  55020. + /** In Token Queue Write Pointer */
  55021. + unsigned intknwptr:5;
  55022. + /** Reserved */
  55023. + unsigned reserved05_06:2;
  55024. + /** write pointer has wrapped. */
  55025. + unsigned wrap_bit:1;
  55026. + /** EP Numbers of IN Tokens 0 ... 4 */
  55027. + unsigned epnums0_5:24;
  55028. + } b;
  55029. +} dtknq1_data_t;
  55030. +
  55031. +/**
  55032. + * This union represents Threshold control Register
  55033. + * - Read and write the register into the <i>d32</i> member.
  55034. + * - READ-WRITABLE Register
  55035. + */
  55036. +typedef union dthrctl_data {
  55037. + /** raw register data */
  55038. + uint32_t d32;
  55039. + /** register bits */
  55040. + struct {
  55041. + /** non ISO Tx Thr. Enable */
  55042. + unsigned non_iso_thr_en:1;
  55043. + /** ISO Tx Thr. Enable */
  55044. + unsigned iso_thr_en:1;
  55045. + /** Tx Thr. Length */
  55046. + unsigned tx_thr_len:9;
  55047. + /** AHB Threshold ratio */
  55048. + unsigned ahb_thr_ratio:2;
  55049. + /** Reserved */
  55050. + unsigned reserved13_15:3;
  55051. + /** Rx Thr. Enable */
  55052. + unsigned rx_thr_en:1;
  55053. + /** Rx Thr. Length */
  55054. + unsigned rx_thr_len:9;
  55055. + unsigned reserved26:1;
  55056. + /** Arbiter Parking Enable*/
  55057. + unsigned arbprken:1;
  55058. + /** Reserved */
  55059. + unsigned reserved28_31:4;
  55060. + } b;
  55061. +} dthrctl_data_t;
  55062. +
  55063. +/**
  55064. + * Device Logical IN Endpoint-Specific Registers. <i>Offsets
  55065. + * 900h-AFCh</i>
  55066. + *
  55067. + * There will be one set of endpoint registers per logical endpoint
  55068. + * implemented.
  55069. + *
  55070. + * <i>These registers are visible only in Device mode and must not be
  55071. + * accessed in Host mode, as the results are unknown.</i>
  55072. + */
  55073. +typedef struct dwc_otg_dev_in_ep_regs {
  55074. + /** Device IN Endpoint Control Register. <i>Offset:900h +
  55075. + * (ep_num * 20h) + 00h</i> */
  55076. + volatile uint32_t diepctl;
  55077. + /** Reserved. <i>Offset:900h + (ep_num * 20h) + 04h</i> */
  55078. + uint32_t reserved04;
  55079. + /** Device IN Endpoint Interrupt Register. <i>Offset:900h +
  55080. + * (ep_num * 20h) + 08h</i> */
  55081. + volatile uint32_t diepint;
  55082. + /** Reserved. <i>Offset:900h + (ep_num * 20h) + 0Ch</i> */
  55083. + uint32_t reserved0C;
  55084. + /** Device IN Endpoint Transfer Size
  55085. + * Register. <i>Offset:900h + (ep_num * 20h) + 10h</i> */
  55086. + volatile uint32_t dieptsiz;
  55087. + /** Device IN Endpoint DMA Address Register. <i>Offset:900h +
  55088. + * (ep_num * 20h) + 14h</i> */
  55089. + volatile uint32_t diepdma;
  55090. + /** Device IN Endpoint Transmit FIFO Status Register. <i>Offset:900h +
  55091. + * (ep_num * 20h) + 18h</i> */
  55092. + volatile uint32_t dtxfsts;
  55093. + /** Device IN Endpoint DMA Buffer Register. <i>Offset:900h +
  55094. + * (ep_num * 20h) + 1Ch</i> */
  55095. + volatile uint32_t diepdmab;
  55096. +} dwc_otg_dev_in_ep_regs_t;
  55097. +
  55098. +/**
  55099. + * Device Logical OUT Endpoint-Specific Registers. <i>Offsets:
  55100. + * B00h-CFCh</i>
  55101. + *
  55102. + * There will be one set of endpoint registers per logical endpoint
  55103. + * implemented.
  55104. + *
  55105. + * <i>These registers are visible only in Device mode and must not be
  55106. + * accessed in Host mode, as the results are unknown.</i>
  55107. + */
  55108. +typedef struct dwc_otg_dev_out_ep_regs {
  55109. + /** Device OUT Endpoint Control Register. <i>Offset:B00h +
  55110. + * (ep_num * 20h) + 00h</i> */
  55111. + volatile uint32_t doepctl;
  55112. + /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 04h</i> */
  55113. + uint32_t reserved04;
  55114. + /** Device OUT Endpoint Interrupt Register. <i>Offset:B00h +
  55115. + * (ep_num * 20h) + 08h</i> */
  55116. + volatile uint32_t doepint;
  55117. + /** Reserved. <i>Offset:B00h + (ep_num * 20h) + 0Ch</i> */
  55118. + uint32_t reserved0C;
  55119. + /** Device OUT Endpoint Transfer Size Register. <i>Offset:
  55120. + * B00h + (ep_num * 20h) + 10h</i> */
  55121. + volatile uint32_t doeptsiz;
  55122. + /** Device OUT Endpoint DMA Address Register. <i>Offset:B00h
  55123. + * + (ep_num * 20h) + 14h</i> */
  55124. + volatile uint32_t doepdma;
  55125. + /** Reserved. <i>Offset:B00h + * (ep_num * 20h) + 18h</i> */
  55126. + uint32_t unused;
  55127. + /** Device OUT Endpoint DMA Buffer Register. <i>Offset:B00h
  55128. + * + (ep_num * 20h) + 1Ch</i> */
  55129. + uint32_t doepdmab;
  55130. +} dwc_otg_dev_out_ep_regs_t;
  55131. +
  55132. +/**
  55133. + * This union represents the bit fields in the Device EP Control
  55134. + * Register. Read the register into the <i>d32</i> member then
  55135. + * set/clear the bits using the <i>b</i>it elements.
  55136. + */
  55137. +typedef union depctl_data {
  55138. + /** raw register data */
  55139. + uint32_t d32;
  55140. + /** register bits */
  55141. + struct {
  55142. + /** Maximum Packet Size
  55143. + * IN/OUT EPn
  55144. + * IN/OUT EP0 - 2 bits
  55145. + * 2'b00: 64 Bytes
  55146. + * 2'b01: 32
  55147. + * 2'b10: 16
  55148. + * 2'b11: 8 */
  55149. + unsigned mps:11;
  55150. +#define DWC_DEP0CTL_MPS_64 0
  55151. +#define DWC_DEP0CTL_MPS_32 1
  55152. +#define DWC_DEP0CTL_MPS_16 2
  55153. +#define DWC_DEP0CTL_MPS_8 3
  55154. +
  55155. + /** Next Endpoint
  55156. + * IN EPn/IN EP0
  55157. + * OUT EPn/OUT EP0 - reserved */
  55158. + unsigned nextep:4;
  55159. +
  55160. + /** USB Active Endpoint */
  55161. + unsigned usbactep:1;
  55162. +
  55163. + /** Endpoint DPID (INTR/Bulk IN and OUT endpoints)
  55164. + * This field contains the PID of the packet going to
  55165. + * be received or transmitted on this endpoint. The
  55166. + * application should program the PID of the first
  55167. + * packet going to be received or transmitted on this
  55168. + * endpoint , after the endpoint is
  55169. + * activated. Application use the SetD1PID and
  55170. + * SetD0PID fields of this register to program either
  55171. + * D0 or D1 PID.
  55172. + *
  55173. + * The encoding for this field is
  55174. + * - 0: D0
  55175. + * - 1: D1
  55176. + */
  55177. + unsigned dpid:1;
  55178. +
  55179. + /** NAK Status */
  55180. + unsigned naksts:1;
  55181. +
  55182. + /** Endpoint Type
  55183. + * 2'b00: Control
  55184. + * 2'b01: Isochronous
  55185. + * 2'b10: Bulk
  55186. + * 2'b11: Interrupt */
  55187. + unsigned eptype:2;
  55188. +
  55189. + /** Snoop Mode
  55190. + * OUT EPn/OUT EP0
  55191. + * IN EPn/IN EP0 - reserved */
  55192. + unsigned snp:1;
  55193. +
  55194. + /** Stall Handshake */
  55195. + unsigned stall:1;
  55196. +
  55197. + /** Tx Fifo Number
  55198. + * IN EPn/IN EP0
  55199. + * OUT EPn/OUT EP0 - reserved */
  55200. + unsigned txfnum:4;
  55201. +
  55202. + /** Clear NAK */
  55203. + unsigned cnak:1;
  55204. + /** Set NAK */
  55205. + unsigned snak:1;
  55206. + /** Set DATA0 PID (INTR/Bulk IN and OUT endpoints)
  55207. + * Writing to this field sets the Endpoint DPID (DPID)
  55208. + * field in this register to DATA0. Set Even
  55209. + * (micro)frame (SetEvenFr) (ISO IN and OUT Endpoints)
  55210. + * Writing to this field sets the Even/Odd
  55211. + * (micro)frame (EO_FrNum) field to even (micro)
  55212. + * frame.
  55213. + */
  55214. + unsigned setd0pid:1;
  55215. + /** Set DATA1 PID (INTR/Bulk IN and OUT endpoints)
  55216. + * Writing to this field sets the Endpoint DPID (DPID)
  55217. + * field in this register to DATA1 Set Odd
  55218. + * (micro)frame (SetOddFr) (ISO IN and OUT Endpoints)
  55219. + * Writing to this field sets the Even/Odd
  55220. + * (micro)frame (EO_FrNum) field to odd (micro) frame.
  55221. + */
  55222. + unsigned setd1pid:1;
  55223. +
  55224. + /** Endpoint Disable */
  55225. + unsigned epdis:1;
  55226. + /** Endpoint Enable */
  55227. + unsigned epena:1;
  55228. + } b;
  55229. +} depctl_data_t;
  55230. +
  55231. +/**
  55232. + * This union represents the bit fields in the Device EP Transfer
  55233. + * Size Register. Read the register into the <i>d32</i> member then
  55234. + * set/clear the bits using the <i>b</i>it elements.
  55235. + */
  55236. +typedef union deptsiz_data {
  55237. + /** raw register data */
  55238. + uint32_t d32;
  55239. + /** register bits */
  55240. + struct {
  55241. + /** Transfer size */
  55242. + unsigned xfersize:19;
  55243. +/** Max packet count for EP (pow(2,10)-1) */
  55244. +#define MAX_PKT_CNT 1023
  55245. + /** Packet Count */
  55246. + unsigned pktcnt:10;
  55247. + /** Multi Count - Periodic IN endpoints */
  55248. + unsigned mc:2;
  55249. + unsigned reserved:1;
  55250. + } b;
  55251. +} deptsiz_data_t;
  55252. +
  55253. +/**
  55254. + * This union represents the bit fields in the Device EP 0 Transfer
  55255. + * Size Register. Read the register into the <i>d32</i> member then
  55256. + * set/clear the bits using the <i>b</i>it elements.
  55257. + */
  55258. +typedef union deptsiz0_data {
  55259. + /** raw register data */
  55260. + uint32_t d32;
  55261. + /** register bits */
  55262. + struct {
  55263. + /** Transfer size */
  55264. + unsigned xfersize:7;
  55265. + /** Reserved */
  55266. + unsigned reserved7_18:12;
  55267. + /** Packet Count */
  55268. + unsigned pktcnt:2;
  55269. + /** Reserved */
  55270. + unsigned reserved21_28:8;
  55271. + /**Setup Packet Count (DOEPTSIZ0 Only) */
  55272. + unsigned supcnt:2;
  55273. + unsigned reserved31;
  55274. + } b;
  55275. +} deptsiz0_data_t;
  55276. +
  55277. +/////////////////////////////////////////////////
  55278. +// DMA Descriptor Specific Structures
  55279. +//
  55280. +
  55281. +/** Buffer status definitions */
  55282. +
  55283. +#define BS_HOST_READY 0x0
  55284. +#define BS_DMA_BUSY 0x1
  55285. +#define BS_DMA_DONE 0x2
  55286. +#define BS_HOST_BUSY 0x3
  55287. +
  55288. +/** Receive/Transmit status definitions */
  55289. +
  55290. +#define RTS_SUCCESS 0x0
  55291. +#define RTS_BUFFLUSH 0x1
  55292. +#define RTS_RESERVED 0x2
  55293. +#define RTS_BUFERR 0x3
  55294. +
  55295. +/**
  55296. + * This union represents the bit fields in the DMA Descriptor
  55297. + * status quadlet. Read the quadlet into the <i>d32</i> member then
  55298. + * set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and
  55299. + * <i>b_iso_in</i> elements.
  55300. + */
  55301. +typedef union dev_dma_desc_sts {
  55302. + /** raw register data */
  55303. + uint32_t d32;
  55304. + /** quadlet bits */
  55305. + struct {
  55306. + /** Received number of bytes */
  55307. + unsigned bytes:16;
  55308. + /** NAK bit - only for OUT EPs */
  55309. + unsigned nak:1;
  55310. + unsigned reserved17_22:6;
  55311. + /** Multiple Transfer - only for OUT EPs */
  55312. + unsigned mtrf:1;
  55313. + /** Setup Packet received - only for OUT EPs */
  55314. + unsigned sr:1;
  55315. + /** Interrupt On Complete */
  55316. + unsigned ioc:1;
  55317. + /** Short Packet */
  55318. + unsigned sp:1;
  55319. + /** Last */
  55320. + unsigned l:1;
  55321. + /** Receive Status */
  55322. + unsigned sts:2;
  55323. + /** Buffer Status */
  55324. + unsigned bs:2;
  55325. + } b;
  55326. +
  55327. +//#ifdef DWC_EN_ISOC
  55328. + /** iso out quadlet bits */
  55329. + struct {
  55330. + /** Received number of bytes */
  55331. + unsigned rxbytes:11;
  55332. +
  55333. + unsigned reserved11:1;
  55334. + /** Frame Number */
  55335. + unsigned framenum:11;
  55336. + /** Received ISO Data PID */
  55337. + unsigned pid:2;
  55338. + /** Interrupt On Complete */
  55339. + unsigned ioc:1;
  55340. + /** Short Packet */
  55341. + unsigned sp:1;
  55342. + /** Last */
  55343. + unsigned l:1;
  55344. + /** Receive Status */
  55345. + unsigned rxsts:2;
  55346. + /** Buffer Status */
  55347. + unsigned bs:2;
  55348. + } b_iso_out;
  55349. +
  55350. + /** iso in quadlet bits */
  55351. + struct {
  55352. + /** Transmited number of bytes */
  55353. + unsigned txbytes:12;
  55354. + /** Frame Number */
  55355. + unsigned framenum:11;
  55356. + /** Transmited ISO Data PID */
  55357. + unsigned pid:2;
  55358. + /** Interrupt On Complete */
  55359. + unsigned ioc:1;
  55360. + /** Short Packet */
  55361. + unsigned sp:1;
  55362. + /** Last */
  55363. + unsigned l:1;
  55364. + /** Transmit Status */
  55365. + unsigned txsts:2;
  55366. + /** Buffer Status */
  55367. + unsigned bs:2;
  55368. + } b_iso_in;
  55369. +//#endif /* DWC_EN_ISOC */
  55370. +} dev_dma_desc_sts_t;
  55371. +
  55372. +/**
  55373. + * DMA Descriptor structure
  55374. + *
  55375. + * DMA Descriptor structure contains two quadlets:
  55376. + * Status quadlet and Data buffer pointer.
  55377. + */
  55378. +typedef struct dwc_otg_dev_dma_desc {
  55379. + /** DMA Descriptor status quadlet */
  55380. + dev_dma_desc_sts_t status;
  55381. + /** DMA Descriptor data buffer pointer */
  55382. + uint32_t buf;
  55383. +} dwc_otg_dev_dma_desc_t;
  55384. +
  55385. +/**
  55386. + * The dwc_otg_dev_if structure contains information needed to manage
  55387. + * the DWC_otg controller acting in device mode. It represents the
  55388. + * programming view of the device-specific aspects of the controller.
  55389. + */
  55390. +typedef struct dwc_otg_dev_if {
  55391. + /** Pointer to device Global registers.
  55392. + * Device Global Registers starting at offset 800h
  55393. + */
  55394. + dwc_otg_device_global_regs_t *dev_global_regs;
  55395. +#define DWC_DEV_GLOBAL_REG_OFFSET 0x800
  55396. +
  55397. + /**
  55398. + * Device Logical IN Endpoint-Specific Registers 900h-AFCh
  55399. + */
  55400. + dwc_otg_dev_in_ep_regs_t *in_ep_regs[MAX_EPS_CHANNELS];
  55401. +#define DWC_DEV_IN_EP_REG_OFFSET 0x900
  55402. +#define DWC_EP_REG_OFFSET 0x20
  55403. +
  55404. + /** Device Logical OUT Endpoint-Specific Registers B00h-CFCh */
  55405. + dwc_otg_dev_out_ep_regs_t *out_ep_regs[MAX_EPS_CHANNELS];
  55406. +#define DWC_DEV_OUT_EP_REG_OFFSET 0xB00
  55407. +
  55408. + /* Device configuration information */
  55409. + uint8_t speed; /**< Device Speed 0: Unknown, 1: LS, 2:FS, 3: HS */
  55410. + uint8_t num_in_eps; /**< Number # of Tx EP range: 0-15 exept ep0 */
  55411. + uint8_t num_out_eps; /**< Number # of Rx EP range: 0-15 exept ep 0*/
  55412. +
  55413. + /** Size of periodic FIFOs (Bytes) */
  55414. + uint16_t perio_tx_fifo_size[MAX_PERIO_FIFOS];
  55415. +
  55416. + /** Size of Tx FIFOs (Bytes) */
  55417. + uint16_t tx_fifo_size[MAX_TX_FIFOS];
  55418. +
  55419. + /** Thresholding enable flags and length varaiables **/
  55420. + uint16_t rx_thr_en;
  55421. + uint16_t iso_tx_thr_en;
  55422. + uint16_t non_iso_tx_thr_en;
  55423. +
  55424. + uint16_t rx_thr_length;
  55425. + uint16_t tx_thr_length;
  55426. +
  55427. + /**
  55428. + * Pointers to the DMA Descriptors for EP0 Control
  55429. + * transfers (virtual and physical)
  55430. + */
  55431. +
  55432. + /** 2 descriptors for SETUP packets */
  55433. + dwc_dma_t dma_setup_desc_addr[2];
  55434. + dwc_otg_dev_dma_desc_t *setup_desc_addr[2];
  55435. +
  55436. + /** Pointer to Descriptor with latest SETUP packet */
  55437. + dwc_otg_dev_dma_desc_t *psetup;
  55438. +
  55439. + /** Index of current SETUP handler descriptor */
  55440. + uint32_t setup_desc_index;
  55441. +
  55442. + /** Descriptor for Data In or Status In phases */
  55443. + dwc_dma_t dma_in_desc_addr;
  55444. + dwc_otg_dev_dma_desc_t *in_desc_addr;
  55445. +
  55446. + /** Descriptor for Data Out or Status Out phases */
  55447. + dwc_dma_t dma_out_desc_addr;
  55448. + dwc_otg_dev_dma_desc_t *out_desc_addr;
  55449. +
  55450. + /** Setup Packet Detected - if set clear NAK when queueing */
  55451. + uint32_t spd;
  55452. + /** Isoc ep pointer on which incomplete happens */
  55453. + void *isoc_ep;
  55454. +
  55455. +} dwc_otg_dev_if_t;
  55456. +
  55457. +/////////////////////////////////////////////////
  55458. +// Host Mode Register Structures
  55459. +//
  55460. +/**
  55461. + * The Host Global Registers structure defines the size and relative
  55462. + * field offsets for the Host Mode Global Registers. Host Global
  55463. + * Registers offsets 400h-7FFh.
  55464. +*/
  55465. +typedef struct dwc_otg_host_global_regs {
  55466. + /** Host Configuration Register. <i>Offset: 400h</i> */
  55467. + volatile uint32_t hcfg;
  55468. + /** Host Frame Interval Register. <i>Offset: 404h</i> */
  55469. + volatile uint32_t hfir;
  55470. + /** Host Frame Number / Frame Remaining Register. <i>Offset: 408h</i> */
  55471. + volatile uint32_t hfnum;
  55472. + /** Reserved. <i>Offset: 40Ch</i> */
  55473. + uint32_t reserved40C;
  55474. + /** Host Periodic Transmit FIFO/ Queue Status Register. <i>Offset: 410h</i> */
  55475. + volatile uint32_t hptxsts;
  55476. + /** Host All Channels Interrupt Register. <i>Offset: 414h</i> */
  55477. + volatile uint32_t haint;
  55478. + /** Host All Channels Interrupt Mask Register. <i>Offset: 418h</i> */
  55479. + volatile uint32_t haintmsk;
  55480. + /** Host Frame List Base Address Register . <i>Offset: 41Ch</i> */
  55481. + volatile uint32_t hflbaddr;
  55482. +} dwc_otg_host_global_regs_t;
  55483. +
  55484. +/**
  55485. + * This union represents the bit fields in the Host Configuration Register.
  55486. + * Read the register into the <i>d32</i> member then set/clear the bits using
  55487. + * the <i>b</i>it elements. Write the <i>d32</i> member to the hcfg register.
  55488. + */
  55489. +typedef union hcfg_data {
  55490. + /** raw register data */
  55491. + uint32_t d32;
  55492. +
  55493. + /** register bits */
  55494. + struct {
  55495. + /** FS/LS Phy Clock Select */
  55496. + unsigned fslspclksel:2;
  55497. +#define DWC_HCFG_30_60_MHZ 0
  55498. +#define DWC_HCFG_48_MHZ 1
  55499. +#define DWC_HCFG_6_MHZ 2
  55500. +
  55501. + /** FS/LS Only Support */
  55502. + unsigned fslssupp:1;
  55503. + unsigned reserved3_6:4;
  55504. + /** Enable 32-KHz Suspend Mode */
  55505. + unsigned ena32khzs:1;
  55506. + /** Resume Validation Periiod */
  55507. + unsigned resvalid:8;
  55508. + unsigned reserved16_22:7;
  55509. + /** Enable Scatter/gather DMA in Host mode */
  55510. + unsigned descdma:1;
  55511. + /** Frame List Entries */
  55512. + unsigned frlisten:2;
  55513. + /** Enable Periodic Scheduling */
  55514. + unsigned perschedena:1;
  55515. + unsigned reserved27_30:4;
  55516. + unsigned modechtimen:1;
  55517. + } b;
  55518. +} hcfg_data_t;
  55519. +
  55520. +/**
  55521. + * This union represents the bit fields in the Host Frame Remaing/Number
  55522. + * Register.
  55523. + */
  55524. +typedef union hfir_data {
  55525. + /** raw register data */
  55526. + uint32_t d32;
  55527. +
  55528. + /** register bits */
  55529. + struct {
  55530. + unsigned frint:16;
  55531. + unsigned hfirrldctrl:1;
  55532. + unsigned reserved:15;
  55533. + } b;
  55534. +} hfir_data_t;
  55535. +
  55536. +/**
  55537. + * This union represents the bit fields in the Host Frame Remaing/Number
  55538. + * Register.
  55539. + */
  55540. +typedef union hfnum_data {
  55541. + /** raw register data */
  55542. + uint32_t d32;
  55543. +
  55544. + /** register bits */
  55545. + struct {
  55546. + unsigned frnum:16;
  55547. +#define DWC_HFNUM_MAX_FRNUM 0x3FFF
  55548. + unsigned frrem:16;
  55549. + } b;
  55550. +} hfnum_data_t;
  55551. +
  55552. +typedef union hptxsts_data {
  55553. + /** raw register data */
  55554. + uint32_t d32;
  55555. +
  55556. + /** register bits */
  55557. + struct {
  55558. + unsigned ptxfspcavail:16;
  55559. + unsigned ptxqspcavail:8;
  55560. + /** Top of the Periodic Transmit Request Queue
  55561. + * - bit 24 - Terminate (last entry for the selected channel)
  55562. + * - bits 26:25 - Token Type
  55563. + * - 2'b00 - Zero length
  55564. + * - 2'b01 - Ping
  55565. + * - 2'b10 - Disable
  55566. + * - bits 30:27 - Channel Number
  55567. + * - bit 31 - Odd/even microframe
  55568. + */
  55569. + unsigned ptxqtop_terminate:1;
  55570. + unsigned ptxqtop_token:2;
  55571. + unsigned ptxqtop_chnum:4;
  55572. + unsigned ptxqtop_odd:1;
  55573. + } b;
  55574. +} hptxsts_data_t;
  55575. +
  55576. +/**
  55577. + * This union represents the bit fields in the Host Port Control and Status
  55578. + * Register. Read the register into the <i>d32</i> member then set/clear the
  55579. + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
  55580. + * hprt0 register.
  55581. + */
  55582. +typedef union hprt0_data {
  55583. + /** raw register data */
  55584. + uint32_t d32;
  55585. + /** register bits */
  55586. + struct {
  55587. + unsigned prtconnsts:1;
  55588. + unsigned prtconndet:1;
  55589. + unsigned prtena:1;
  55590. + unsigned prtenchng:1;
  55591. + unsigned prtovrcurract:1;
  55592. + unsigned prtovrcurrchng:1;
  55593. + unsigned prtres:1;
  55594. + unsigned prtsusp:1;
  55595. + unsigned prtrst:1;
  55596. + unsigned reserved9:1;
  55597. + unsigned prtlnsts:2;
  55598. + unsigned prtpwr:1;
  55599. + unsigned prttstctl:4;
  55600. + unsigned prtspd:2;
  55601. +#define DWC_HPRT0_PRTSPD_HIGH_SPEED 0
  55602. +#define DWC_HPRT0_PRTSPD_FULL_SPEED 1
  55603. +#define DWC_HPRT0_PRTSPD_LOW_SPEED 2
  55604. + unsigned reserved19_31:13;
  55605. + } b;
  55606. +} hprt0_data_t;
  55607. +
  55608. +/**
  55609. + * This union represents the bit fields in the Host All Interrupt
  55610. + * Register.
  55611. + */
  55612. +typedef union haint_data {
  55613. + /** raw register data */
  55614. + uint32_t d32;
  55615. + /** register bits */
  55616. + struct {
  55617. + unsigned ch0:1;
  55618. + unsigned ch1:1;
  55619. + unsigned ch2:1;
  55620. + unsigned ch3:1;
  55621. + unsigned ch4:1;
  55622. + unsigned ch5:1;
  55623. + unsigned ch6:1;
  55624. + unsigned ch7:1;
  55625. + unsigned ch8:1;
  55626. + unsigned ch9:1;
  55627. + unsigned ch10:1;
  55628. + unsigned ch11:1;
  55629. + unsigned ch12:1;
  55630. + unsigned ch13:1;
  55631. + unsigned ch14:1;
  55632. + unsigned ch15:1;
  55633. + unsigned reserved:16;
  55634. + } b;
  55635. +
  55636. + struct {
  55637. + unsigned chint:16;
  55638. + unsigned reserved:16;
  55639. + } b2;
  55640. +} haint_data_t;
  55641. +
  55642. +/**
  55643. + * This union represents the bit fields in the Host All Interrupt
  55644. + * Register.
  55645. + */
  55646. +typedef union haintmsk_data {
  55647. + /** raw register data */
  55648. + uint32_t d32;
  55649. + /** register bits */
  55650. + struct {
  55651. + unsigned ch0:1;
  55652. + unsigned ch1:1;
  55653. + unsigned ch2:1;
  55654. + unsigned ch3:1;
  55655. + unsigned ch4:1;
  55656. + unsigned ch5:1;
  55657. + unsigned ch6:1;
  55658. + unsigned ch7:1;
  55659. + unsigned ch8:1;
  55660. + unsigned ch9:1;
  55661. + unsigned ch10:1;
  55662. + unsigned ch11:1;
  55663. + unsigned ch12:1;
  55664. + unsigned ch13:1;
  55665. + unsigned ch14:1;
  55666. + unsigned ch15:1;
  55667. + unsigned reserved:16;
  55668. + } b;
  55669. +
  55670. + struct {
  55671. + unsigned chint:16;
  55672. + unsigned reserved:16;
  55673. + } b2;
  55674. +} haintmsk_data_t;
  55675. +
  55676. +/**
  55677. + * Host Channel Specific Registers. <i>500h-5FCh</i>
  55678. + */
  55679. +typedef struct dwc_otg_hc_regs {
  55680. + /** Host Channel 0 Characteristic Register. <i>Offset: 500h + (chan_num * 20h) + 00h</i> */
  55681. + volatile uint32_t hcchar;
  55682. + /** Host Channel 0 Split Control Register. <i>Offset: 500h + (chan_num * 20h) + 04h</i> */
  55683. + volatile uint32_t hcsplt;
  55684. + /** Host Channel 0 Interrupt Register. <i>Offset: 500h + (chan_num * 20h) + 08h</i> */
  55685. + volatile uint32_t hcint;
  55686. + /** Host Channel 0 Interrupt Mask Register. <i>Offset: 500h + (chan_num * 20h) + 0Ch</i> */
  55687. + volatile uint32_t hcintmsk;
  55688. + /** Host Channel 0 Transfer Size Register. <i>Offset: 500h + (chan_num * 20h) + 10h</i> */
  55689. + volatile uint32_t hctsiz;
  55690. + /** Host Channel 0 DMA Address Register. <i>Offset: 500h + (chan_num * 20h) + 14h</i> */
  55691. + volatile uint32_t hcdma;
  55692. + volatile uint32_t reserved;
  55693. + /** Host Channel 0 DMA Buffer Address Register. <i>Offset: 500h + (chan_num * 20h) + 1Ch</i> */
  55694. + volatile uint32_t hcdmab;
  55695. +} dwc_otg_hc_regs_t;
  55696. +
  55697. +/**
  55698. + * This union represents the bit fields in the Host Channel Characteristics
  55699. + * Register. Read the register into the <i>d32</i> member then set/clear the
  55700. + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
  55701. + * hcchar register.
  55702. + */
  55703. +typedef union hcchar_data {
  55704. + /** raw register data */
  55705. + uint32_t d32;
  55706. +
  55707. + /** register bits */
  55708. + struct {
  55709. + /** Maximum packet size in bytes */
  55710. + unsigned mps:11;
  55711. +
  55712. + /** Endpoint number */
  55713. + unsigned epnum:4;
  55714. +
  55715. + /** 0: OUT, 1: IN */
  55716. + unsigned epdir:1;
  55717. +
  55718. + unsigned reserved:1;
  55719. +
  55720. + /** 0: Full/high speed device, 1: Low speed device */
  55721. + unsigned lspddev:1;
  55722. +
  55723. + /** 0: Control, 1: Isoc, 2: Bulk, 3: Intr */
  55724. + unsigned eptype:2;
  55725. +
  55726. + /** Packets per frame for periodic transfers. 0 is reserved. */
  55727. + unsigned multicnt:2;
  55728. +
  55729. + /** Device address */
  55730. + unsigned devaddr:7;
  55731. +
  55732. + /**
  55733. + * Frame to transmit periodic transaction.
  55734. + * 0: even, 1: odd
  55735. + */
  55736. + unsigned oddfrm:1;
  55737. +
  55738. + /** Channel disable */
  55739. + unsigned chdis:1;
  55740. +
  55741. + /** Channel enable */
  55742. + unsigned chen:1;
  55743. + } b;
  55744. +} hcchar_data_t;
  55745. +
  55746. +typedef union hcsplt_data {
  55747. + /** raw register data */
  55748. + uint32_t d32;
  55749. +
  55750. + /** register bits */
  55751. + struct {
  55752. + /** Port Address */
  55753. + unsigned prtaddr:7;
  55754. +
  55755. + /** Hub Address */
  55756. + unsigned hubaddr:7;
  55757. +
  55758. + /** Transaction Position */
  55759. + unsigned xactpos:2;
  55760. +#define DWC_HCSPLIT_XACTPOS_MID 0
  55761. +#define DWC_HCSPLIT_XACTPOS_END 1
  55762. +#define DWC_HCSPLIT_XACTPOS_BEGIN 2
  55763. +#define DWC_HCSPLIT_XACTPOS_ALL 3
  55764. +
  55765. + /** Do Complete Split */
  55766. + unsigned compsplt:1;
  55767. +
  55768. + /** Reserved */
  55769. + unsigned reserved:14;
  55770. +
  55771. + /** Split Enble */
  55772. + unsigned spltena:1;
  55773. + } b;
  55774. +} hcsplt_data_t;
  55775. +
  55776. +/**
  55777. + * This union represents the bit fields in the Host All Interrupt
  55778. + * Register.
  55779. + */
  55780. +typedef union hcint_data {
  55781. + /** raw register data */
  55782. + uint32_t d32;
  55783. + /** register bits */
  55784. + struct {
  55785. + /** Transfer Complete */
  55786. + unsigned xfercomp:1;
  55787. + /** Channel Halted */
  55788. + unsigned chhltd:1;
  55789. + /** AHB Error */
  55790. + unsigned ahberr:1;
  55791. + /** STALL Response Received */
  55792. + unsigned stall:1;
  55793. + /** NAK Response Received */
  55794. + unsigned nak:1;
  55795. + /** ACK Response Received */
  55796. + unsigned ack:1;
  55797. + /** NYET Response Received */
  55798. + unsigned nyet:1;
  55799. + /** Transaction Err */
  55800. + unsigned xacterr:1;
  55801. + /** Babble Error */
  55802. + unsigned bblerr:1;
  55803. + /** Frame Overrun */
  55804. + unsigned frmovrun:1;
  55805. + /** Data Toggle Error */
  55806. + unsigned datatglerr:1;
  55807. + /** Buffer Not Available (only for DDMA mode) */
  55808. + unsigned bna:1;
  55809. + /** Exessive transaction error (only for DDMA mode) */
  55810. + unsigned xcs_xact:1;
  55811. + /** Frame List Rollover interrupt */
  55812. + unsigned frm_list_roll:1;
  55813. + /** Reserved */
  55814. + unsigned reserved14_31:18;
  55815. + } b;
  55816. +} hcint_data_t;
  55817. +
  55818. +/**
  55819. + * This union represents the bit fields in the Host Channel Interrupt Mask
  55820. + * Register. Read the register into the <i>d32</i> member then set/clear the
  55821. + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
  55822. + * hcintmsk register.
  55823. + */
  55824. +typedef union hcintmsk_data {
  55825. + /** raw register data */
  55826. + uint32_t d32;
  55827. +
  55828. + /** register bits */
  55829. + struct {
  55830. + unsigned xfercompl:1;
  55831. + unsigned chhltd:1;
  55832. + unsigned ahberr:1;
  55833. + unsigned stall:1;
  55834. + unsigned nak:1;
  55835. + unsigned ack:1;
  55836. + unsigned nyet:1;
  55837. + unsigned xacterr:1;
  55838. + unsigned bblerr:1;
  55839. + unsigned frmovrun:1;
  55840. + unsigned datatglerr:1;
  55841. + unsigned bna:1;
  55842. + unsigned xcs_xact:1;
  55843. + unsigned frm_list_roll:1;
  55844. + unsigned reserved14_31:18;
  55845. + } b;
  55846. +} hcintmsk_data_t;
  55847. +
  55848. +/**
  55849. + * This union represents the bit fields in the Host Channel Transfer Size
  55850. + * Register. Read the register into the <i>d32</i> member then set/clear the
  55851. + * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
  55852. + * hcchar register.
  55853. + */
  55854. +
  55855. +typedef union hctsiz_data {
  55856. + /** raw register data */
  55857. + uint32_t d32;
  55858. +
  55859. + /** register bits */
  55860. + struct {
  55861. + /** Total transfer size in bytes */
  55862. + unsigned xfersize:19;
  55863. +
  55864. + /** Data packets to transfer */
  55865. + unsigned pktcnt:10;
  55866. +
  55867. + /**
  55868. + * Packet ID for next data packet
  55869. + * 0: DATA0
  55870. + * 1: DATA2
  55871. + * 2: DATA1
  55872. + * 3: MDATA (non-Control), SETUP (Control)
  55873. + */
  55874. + unsigned pid:2;
  55875. +#define DWC_HCTSIZ_DATA0 0
  55876. +#define DWC_HCTSIZ_DATA1 2
  55877. +#define DWC_HCTSIZ_DATA2 1
  55878. +#define DWC_HCTSIZ_MDATA 3
  55879. +#define DWC_HCTSIZ_SETUP 3
  55880. +
  55881. + /** Do PING protocol when 1 */
  55882. + unsigned dopng:1;
  55883. + } b;
  55884. +
  55885. + /** register bits */
  55886. + struct {
  55887. + /** Scheduling information */
  55888. + unsigned schinfo:8;
  55889. +
  55890. + /** Number of transfer descriptors.
  55891. + * Max value:
  55892. + * 64 in general,
  55893. + * 256 only for HS isochronous endpoint.
  55894. + */
  55895. + unsigned ntd:8;
  55896. +
  55897. + /** Data packets to transfer */
  55898. + unsigned reserved16_28:13;
  55899. +
  55900. + /**
  55901. + * Packet ID for next data packet
  55902. + * 0: DATA0
  55903. + * 1: DATA2
  55904. + * 2: DATA1
  55905. + * 3: MDATA (non-Control)
  55906. + */
  55907. + unsigned pid:2;
  55908. +
  55909. + /** Do PING protocol when 1 */
  55910. + unsigned dopng:1;
  55911. + } b_ddma;
  55912. +} hctsiz_data_t;
  55913. +
  55914. +/**
  55915. + * This union represents the bit fields in the Host DMA Address
  55916. + * Register used in Descriptor DMA mode.
  55917. + */
  55918. +typedef union hcdma_data {
  55919. + /** raw register data */
  55920. + uint32_t d32;
  55921. + /** register bits */
  55922. + struct {
  55923. + unsigned reserved0_2:3;
  55924. + /** Current Transfer Descriptor. Not used for ISOC */
  55925. + unsigned ctd:8;
  55926. + /** Start Address of Descriptor List */
  55927. + unsigned dma_addr:21;
  55928. + } b;
  55929. +} hcdma_data_t;
  55930. +
  55931. +/**
  55932. + * This union represents the bit fields in the DMA Descriptor
  55933. + * status quadlet for host mode. Read the quadlet into the <i>d32</i> member then
  55934. + * set/clear the bits using the <i>b</i>it elements.
  55935. + */
  55936. +typedef union host_dma_desc_sts {
  55937. + /** raw register data */
  55938. + uint32_t d32;
  55939. + /** quadlet bits */
  55940. +
  55941. + /* for non-isochronous */
  55942. + struct {
  55943. + /** Number of bytes */
  55944. + unsigned n_bytes:17;
  55945. + /** QTD offset to jump when Short Packet received - only for IN EPs */
  55946. + unsigned qtd_offset:6;
  55947. + /**
  55948. + * Set to request the core to jump to alternate QTD if
  55949. + * Short Packet received - only for IN EPs
  55950. + */
  55951. + unsigned a_qtd:1;
  55952. + /**
  55953. + * Setup Packet bit. When set indicates that buffer contains
  55954. + * setup packet.
  55955. + */
  55956. + unsigned sup:1;
  55957. + /** Interrupt On Complete */
  55958. + unsigned ioc:1;
  55959. + /** End of List */
  55960. + unsigned eol:1;
  55961. + unsigned reserved27:1;
  55962. + /** Rx/Tx Status */
  55963. + unsigned sts:2;
  55964. +#define DMA_DESC_STS_PKTERR 1
  55965. + unsigned reserved30:1;
  55966. + /** Active Bit */
  55967. + unsigned a:1;
  55968. + } b;
  55969. + /* for isochronous */
  55970. + struct {
  55971. + /** Number of bytes */
  55972. + unsigned n_bytes:12;
  55973. + unsigned reserved12_24:13;
  55974. + /** Interrupt On Complete */
  55975. + unsigned ioc:1;
  55976. + unsigned reserved26_27:2;
  55977. + /** Rx/Tx Status */
  55978. + unsigned sts:2;
  55979. + unsigned reserved30:1;
  55980. + /** Active Bit */
  55981. + unsigned a:1;
  55982. + } b_isoc;
  55983. +} host_dma_desc_sts_t;
  55984. +
  55985. +#define MAX_DMA_DESC_SIZE 131071
  55986. +#define MAX_DMA_DESC_NUM_GENERIC 64
  55987. +#define MAX_DMA_DESC_NUM_HS_ISOC 256
  55988. +#define MAX_FRLIST_EN_NUM 64
  55989. +/**
  55990. + * Host-mode DMA Descriptor structure
  55991. + *
  55992. + * DMA Descriptor structure contains two quadlets:
  55993. + * Status quadlet and Data buffer pointer.
  55994. + */
  55995. +typedef struct dwc_otg_host_dma_desc {
  55996. + /** DMA Descriptor status quadlet */
  55997. + host_dma_desc_sts_t status;
  55998. + /** DMA Descriptor data buffer pointer */
  55999. + uint32_t buf;
  56000. +} dwc_otg_host_dma_desc_t;
  56001. +
  56002. +/** OTG Host Interface Structure.
  56003. + *
  56004. + * The OTG Host Interface Structure structure contains information
  56005. + * needed to manage the DWC_otg controller acting in host mode. It
  56006. + * represents the programming view of the host-specific aspects of the
  56007. + * controller.
  56008. + */
  56009. +typedef struct dwc_otg_host_if {
  56010. + /** Host Global Registers starting at offset 400h.*/
  56011. + dwc_otg_host_global_regs_t *host_global_regs;
  56012. +#define DWC_OTG_HOST_GLOBAL_REG_OFFSET 0x400
  56013. +
  56014. + /** Host Port 0 Control and Status Register */
  56015. + volatile uint32_t *hprt0;
  56016. +#define DWC_OTG_HOST_PORT_REGS_OFFSET 0x440
  56017. +
  56018. + /** Host Channel Specific Registers at offsets 500h-5FCh. */
  56019. + dwc_otg_hc_regs_t *hc_regs[MAX_EPS_CHANNELS];
  56020. +#define DWC_OTG_HOST_CHAN_REGS_OFFSET 0x500
  56021. +#define DWC_OTG_CHAN_REGS_OFFSET 0x20
  56022. +
  56023. + /* Host configuration information */
  56024. + /** Number of Host Channels (range: 1-16) */
  56025. + uint8_t num_host_channels;
  56026. + /** Periodic EPs supported (0: no, 1: yes) */
  56027. + uint8_t perio_eps_supported;
  56028. + /** Periodic Tx FIFO Size (Only 1 host periodic Tx FIFO) */
  56029. + uint16_t perio_tx_fifo_size;
  56030. +
  56031. +} dwc_otg_host_if_t;
  56032. +
  56033. +/**
  56034. + * This union represents the bit fields in the Power and Clock Gating Control
  56035. + * Register. Read the register into the <i>d32</i> member then set/clear the
  56036. + * bits using the <i>b</i>it elements.
  56037. + */
  56038. +typedef union pcgcctl_data {
  56039. + /** raw register data */
  56040. + uint32_t d32;
  56041. +
  56042. + /** register bits */
  56043. + struct {
  56044. + /** Stop Pclk */
  56045. + unsigned stoppclk:1;
  56046. + /** Gate Hclk */
  56047. + unsigned gatehclk:1;
  56048. + /** Power Clamp */
  56049. + unsigned pwrclmp:1;
  56050. + /** Reset Power Down Modules */
  56051. + unsigned rstpdwnmodule:1;
  56052. + /** Reserved */
  56053. + unsigned reserved:1;
  56054. + /** Enable Sleep Clock Gating (Enbl_L1Gating) */
  56055. + unsigned enbl_sleep_gating:1;
  56056. + /** PHY In Sleep (PhySleep) */
  56057. + unsigned phy_in_sleep:1;
  56058. + /** Deep Sleep*/
  56059. + unsigned deep_sleep:1;
  56060. + unsigned resetaftsusp:1;
  56061. + unsigned restoremode:1;
  56062. + unsigned enbl_extnd_hiber:1;
  56063. + unsigned extnd_hiber_pwrclmp:1;
  56064. + unsigned extnd_hiber_switch:1;
  56065. + unsigned ess_reg_restored:1;
  56066. + unsigned prt_clk_sel:2;
  56067. + unsigned port_power:1;
  56068. + unsigned max_xcvrselect:2;
  56069. + unsigned max_termsel:1;
  56070. + unsigned mac_dev_addr:7;
  56071. + unsigned p2hd_dev_enum_spd:2;
  56072. + unsigned p2hd_prt_spd:2;
  56073. + unsigned if_dev_mode:1;
  56074. + } b;
  56075. +} pcgcctl_data_t;
  56076. +
  56077. +/**
  56078. + * This union represents the bit fields in the Global Data FIFO Software
  56079. + * Configuration Register. Read the register into the <i>d32</i> member then
  56080. + * set/clear the bits using the <i>b</i>it elements.
  56081. + */
  56082. +typedef union gdfifocfg_data {
  56083. + /* raw register data */
  56084. + uint32_t d32;
  56085. + /** register bits */
  56086. + struct {
  56087. + /** OTG Data FIFO depth */
  56088. + unsigned gdfifocfg:16;
  56089. + /** Start address of EP info controller */
  56090. + unsigned epinfobase:16;
  56091. + } b;
  56092. +} gdfifocfg_data_t;
  56093. +
  56094. +/**
  56095. + * This union represents the bit fields in the Global Power Down Register
  56096. + * Register. Read the register into the <i>d32</i> member then set/clear the
  56097. + * bits using the <i>b</i>it elements.
  56098. + */
  56099. +typedef union gpwrdn_data {
  56100. + /* raw register data */
  56101. + uint32_t d32;
  56102. +
  56103. + /** register bits */
  56104. + struct {
  56105. + /** PMU Interrupt Select */
  56106. + unsigned pmuintsel:1;
  56107. + /** PMU Active */
  56108. + unsigned pmuactv:1;
  56109. + /** Restore */
  56110. + unsigned restore:1;
  56111. + /** Power Down Clamp */
  56112. + unsigned pwrdnclmp:1;
  56113. + /** Power Down Reset */
  56114. + unsigned pwrdnrstn:1;
  56115. + /** Power Down Switch */
  56116. + unsigned pwrdnswtch:1;
  56117. + /** Disable VBUS */
  56118. + unsigned dis_vbus:1;
  56119. + /** Line State Change */
  56120. + unsigned lnstschng:1;
  56121. + /** Line state change mask */
  56122. + unsigned lnstchng_msk:1;
  56123. + /** Reset Detected */
  56124. + unsigned rst_det:1;
  56125. + /** Reset Detect mask */
  56126. + unsigned rst_det_msk:1;
  56127. + /** Disconnect Detected */
  56128. + unsigned disconn_det:1;
  56129. + /** Disconnect Detect mask */
  56130. + unsigned disconn_det_msk:1;
  56131. + /** Connect Detected*/
  56132. + unsigned connect_det:1;
  56133. + /** Connect Detected Mask*/
  56134. + unsigned connect_det_msk:1;
  56135. + /** SRP Detected */
  56136. + unsigned srp_det:1;
  56137. + /** SRP Detect mask */
  56138. + unsigned srp_det_msk:1;
  56139. + /** Status Change Interrupt */
  56140. + unsigned sts_chngint:1;
  56141. + /** Status Change Interrupt Mask */
  56142. + unsigned sts_chngint_msk:1;
  56143. + /** Line State */
  56144. + unsigned linestate:2;
  56145. + /** Indicates current mode(status of IDDIG signal) */
  56146. + unsigned idsts:1;
  56147. + /** B Session Valid signal status*/
  56148. + unsigned bsessvld:1;
  56149. + /** ADP Event Detected */
  56150. + unsigned adp_int:1;
  56151. + /** Multi Valued ID pin */
  56152. + unsigned mult_val_id_bc:5;
  56153. + /** Reserved 24_31 */
  56154. + unsigned reserved29_31:3;
  56155. + } b;
  56156. +} gpwrdn_data_t;
  56157. +
  56158. +#endif
  56159. --- /dev/null
  56160. +++ b/drivers/usb/host/dwc_otg/test/Makefile
  56161. @@ -0,0 +1,16 @@
  56162. +
  56163. +PERL=/usr/bin/perl
  56164. +PL_TESTS=test_sysfs.pl test_mod_param.pl
  56165. +
  56166. +.PHONY : test
  56167. +test : perl_tests
  56168. +
  56169. +perl_tests :
  56170. + @echo
  56171. + @echo Running perl tests
  56172. + @for test in $(PL_TESTS); do \
  56173. + if $(PERL) ./$$test ; then \
  56174. + echo "=======> $$test, PASSED" ; \
  56175. + else echo "=======> $$test, FAILED" ; \
  56176. + fi \
  56177. + done
  56178. --- /dev/null
  56179. +++ b/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
  56180. @@ -0,0 +1,337 @@
  56181. +package dwc_otg_test;
  56182. +
  56183. +use strict;
  56184. +use Exporter ();
  56185. +
  56186. +use vars qw(@ISA @EXPORT
  56187. +$sysfsdir $paramdir $errors $params
  56188. +);
  56189. +
  56190. +@ISA = qw(Exporter);
  56191. +
  56192. +#
  56193. +# Globals
  56194. +#
  56195. +$sysfsdir = "/sys/devices/lm0";
  56196. +$paramdir = "/sys/module/dwc_otg";
  56197. +$errors = 0;
  56198. +
  56199. +$params = [
  56200. + {
  56201. + NAME => "otg_cap",
  56202. + DEFAULT => 0,
  56203. + ENUM => [],
  56204. + LOW => 0,
  56205. + HIGH => 2
  56206. + },
  56207. + {
  56208. + NAME => "dma_enable",
  56209. + DEFAULT => 0,
  56210. + ENUM => [],
  56211. + LOW => 0,
  56212. + HIGH => 1
  56213. + },
  56214. + {
  56215. + NAME => "dma_burst_size",
  56216. + DEFAULT => 32,
  56217. + ENUM => [1, 4, 8, 16, 32, 64, 128, 256],
  56218. + LOW => 1,
  56219. + HIGH => 256
  56220. + },
  56221. + {
  56222. + NAME => "host_speed",
  56223. + DEFAULT => 0,
  56224. + ENUM => [],
  56225. + LOW => 0,
  56226. + HIGH => 1
  56227. + },
  56228. + {
  56229. + NAME => "host_support_fs_ls_low_power",
  56230. + DEFAULT => 0,
  56231. + ENUM => [],
  56232. + LOW => 0,
  56233. + HIGH => 1
  56234. + },
  56235. + {
  56236. + NAME => "host_ls_low_power_phy_clk",
  56237. + DEFAULT => 0,
  56238. + ENUM => [],
  56239. + LOW => 0,
  56240. + HIGH => 1
  56241. + },
  56242. + {
  56243. + NAME => "dev_speed",
  56244. + DEFAULT => 0,
  56245. + ENUM => [],
  56246. + LOW => 0,
  56247. + HIGH => 1
  56248. + },
  56249. + {
  56250. + NAME => "enable_dynamic_fifo",
  56251. + DEFAULT => 1,
  56252. + ENUM => [],
  56253. + LOW => 0,
  56254. + HIGH => 1
  56255. + },
  56256. + {
  56257. + NAME => "data_fifo_size",
  56258. + DEFAULT => 8192,
  56259. + ENUM => [],
  56260. + LOW => 32,
  56261. + HIGH => 32768
  56262. + },
  56263. + {
  56264. + NAME => "dev_rx_fifo_size",
  56265. + DEFAULT => 1064,
  56266. + ENUM => [],
  56267. + LOW => 16,
  56268. + HIGH => 32768
  56269. + },
  56270. + {
  56271. + NAME => "dev_nperio_tx_fifo_size",
  56272. + DEFAULT => 1024,
  56273. + ENUM => [],
  56274. + LOW => 16,
  56275. + HIGH => 32768
  56276. + },
  56277. + {
  56278. + NAME => "dev_perio_tx_fifo_size_1",
  56279. + DEFAULT => 256,
  56280. + ENUM => [],
  56281. + LOW => 4,
  56282. + HIGH => 768
  56283. + },
  56284. + {
  56285. + NAME => "dev_perio_tx_fifo_size_2",
  56286. + DEFAULT => 256,
  56287. + ENUM => [],
  56288. + LOW => 4,
  56289. + HIGH => 768
  56290. + },
  56291. + {
  56292. + NAME => "dev_perio_tx_fifo_size_3",
  56293. + DEFAULT => 256,
  56294. + ENUM => [],
  56295. + LOW => 4,
  56296. + HIGH => 768
  56297. + },
  56298. + {
  56299. + NAME => "dev_perio_tx_fifo_size_4",
  56300. + DEFAULT => 256,
  56301. + ENUM => [],
  56302. + LOW => 4,
  56303. + HIGH => 768
  56304. + },
  56305. + {
  56306. + NAME => "dev_perio_tx_fifo_size_5",
  56307. + DEFAULT => 256,
  56308. + ENUM => [],
  56309. + LOW => 4,
  56310. + HIGH => 768
  56311. + },
  56312. + {
  56313. + NAME => "dev_perio_tx_fifo_size_6",
  56314. + DEFAULT => 256,
  56315. + ENUM => [],
  56316. + LOW => 4,
  56317. + HIGH => 768
  56318. + },
  56319. + {
  56320. + NAME => "dev_perio_tx_fifo_size_7",
  56321. + DEFAULT => 256,
  56322. + ENUM => [],
  56323. + LOW => 4,
  56324. + HIGH => 768
  56325. + },
  56326. + {
  56327. + NAME => "dev_perio_tx_fifo_size_8",
  56328. + DEFAULT => 256,
  56329. + ENUM => [],
  56330. + LOW => 4,
  56331. + HIGH => 768
  56332. + },
  56333. + {
  56334. + NAME => "dev_perio_tx_fifo_size_9",
  56335. + DEFAULT => 256,
  56336. + ENUM => [],
  56337. + LOW => 4,
  56338. + HIGH => 768
  56339. + },
  56340. + {
  56341. + NAME => "dev_perio_tx_fifo_size_10",
  56342. + DEFAULT => 256,
  56343. + ENUM => [],
  56344. + LOW => 4,
  56345. + HIGH => 768
  56346. + },
  56347. + {
  56348. + NAME => "dev_perio_tx_fifo_size_11",
  56349. + DEFAULT => 256,
  56350. + ENUM => [],
  56351. + LOW => 4,
  56352. + HIGH => 768
  56353. + },
  56354. + {
  56355. + NAME => "dev_perio_tx_fifo_size_12",
  56356. + DEFAULT => 256,
  56357. + ENUM => [],
  56358. + LOW => 4,
  56359. + HIGH => 768
  56360. + },
  56361. + {
  56362. + NAME => "dev_perio_tx_fifo_size_13",
  56363. + DEFAULT => 256,
  56364. + ENUM => [],
  56365. + LOW => 4,
  56366. + HIGH => 768
  56367. + },
  56368. + {
  56369. + NAME => "dev_perio_tx_fifo_size_14",
  56370. + DEFAULT => 256,
  56371. + ENUM => [],
  56372. + LOW => 4,
  56373. + HIGH => 768
  56374. + },
  56375. + {
  56376. + NAME => "dev_perio_tx_fifo_size_15",
  56377. + DEFAULT => 256,
  56378. + ENUM => [],
  56379. + LOW => 4,
  56380. + HIGH => 768
  56381. + },
  56382. + {
  56383. + NAME => "host_rx_fifo_size",
  56384. + DEFAULT => 1024,
  56385. + ENUM => [],
  56386. + LOW => 16,
  56387. + HIGH => 32768
  56388. + },
  56389. + {
  56390. + NAME => "host_nperio_tx_fifo_size",
  56391. + DEFAULT => 1024,
  56392. + ENUM => [],
  56393. + LOW => 16,
  56394. + HIGH => 32768
  56395. + },
  56396. + {
  56397. + NAME => "host_perio_tx_fifo_size",
  56398. + DEFAULT => 1024,
  56399. + ENUM => [],
  56400. + LOW => 16,
  56401. + HIGH => 32768
  56402. + },
  56403. + {
  56404. + NAME => "max_transfer_size",
  56405. + DEFAULT => 65535,
  56406. + ENUM => [],
  56407. + LOW => 2047,
  56408. + HIGH => 65535
  56409. + },
  56410. + {
  56411. + NAME => "max_packet_count",
  56412. + DEFAULT => 511,
  56413. + ENUM => [],
  56414. + LOW => 15,
  56415. + HIGH => 511
  56416. + },
  56417. + {
  56418. + NAME => "host_channels",
  56419. + DEFAULT => 12,
  56420. + ENUM => [],
  56421. + LOW => 1,
  56422. + HIGH => 16
  56423. + },
  56424. + {
  56425. + NAME => "dev_endpoints",
  56426. + DEFAULT => 6,
  56427. + ENUM => [],
  56428. + LOW => 1,
  56429. + HIGH => 15
  56430. + },
  56431. + {
  56432. + NAME => "phy_type",
  56433. + DEFAULT => 1,
  56434. + ENUM => [],
  56435. + LOW => 0,
  56436. + HIGH => 2
  56437. + },
  56438. + {
  56439. + NAME => "phy_utmi_width",
  56440. + DEFAULT => 16,
  56441. + ENUM => [8, 16],
  56442. + LOW => 8,
  56443. + HIGH => 16
  56444. + },
  56445. + {
  56446. + NAME => "phy_ulpi_ddr",
  56447. + DEFAULT => 0,
  56448. + ENUM => [],
  56449. + LOW => 0,
  56450. + HIGH => 1
  56451. + },
  56452. + ];
  56453. +
  56454. +
  56455. +#
  56456. +#
  56457. +sub check_arch {
  56458. + $_ = `uname -m`;
  56459. + chomp;
  56460. + unless (m/armv4tl/) {
  56461. + warn "# \n# Can't execute on $_. Run on integrator platform.\n# \n";
  56462. + return 0;
  56463. + }
  56464. + return 1;
  56465. +}
  56466. +
  56467. +#
  56468. +#
  56469. +sub load_module {
  56470. + my $params = shift;
  56471. + print "\nRemoving Module\n";
  56472. + system "rmmod dwc_otg";
  56473. + print "Loading Module\n";
  56474. + if ($params ne "") {
  56475. + print "Module Parameters: $params\n";
  56476. + }
  56477. + if (system("modprobe dwc_otg $params")) {
  56478. + warn "Unable to load module\n";
  56479. + return 0;
  56480. + }
  56481. + return 1;
  56482. +}
  56483. +
  56484. +#
  56485. +#
  56486. +sub test_status {
  56487. + my $arg = shift;
  56488. +
  56489. + print "\n";
  56490. +
  56491. + if (defined $arg) {
  56492. + warn "WARNING: $arg\n";
  56493. + }
  56494. +
  56495. + if ($errors > 0) {
  56496. + warn "TEST FAILED with $errors errors\n";
  56497. + return 0;
  56498. + } else {
  56499. + print "TEST PASSED\n";
  56500. + return 0 if (defined $arg);
  56501. + }
  56502. + return 1;
  56503. +}
  56504. +
  56505. +#
  56506. +#
  56507. +@EXPORT = qw(
  56508. +$sysfsdir
  56509. +$paramdir
  56510. +$params
  56511. +$errors
  56512. +check_arch
  56513. +load_module
  56514. +test_status
  56515. +);
  56516. +
  56517. +1;
  56518. --- /dev/null
  56519. +++ b/drivers/usb/host/dwc_otg/test/test_mod_param.pl
  56520. @@ -0,0 +1,133 @@
  56521. +#!/usr/bin/perl -w
  56522. +#
  56523. +# Run this program on the integrator.
  56524. +#
  56525. +# - Tests module parameter default values.
  56526. +# - Tests setting of valid module parameter values via modprobe.
  56527. +# - Tests invalid module parameter values.
  56528. +# -----------------------------------------------------------------------------
  56529. +use strict;
  56530. +use dwc_otg_test;
  56531. +
  56532. +check_arch() or die;
  56533. +
  56534. +#
  56535. +#
  56536. +sub test {
  56537. + my ($param,$expected) = @_;
  56538. + my $value = get($param);
  56539. +
  56540. + if ($value == $expected) {
  56541. + print "$param = $value, okay\n";
  56542. + }
  56543. +
  56544. + else {
  56545. + warn "ERROR: value of $param != $expected, $value\n";
  56546. + $errors ++;
  56547. + }
  56548. +}
  56549. +
  56550. +#
  56551. +#
  56552. +sub get {
  56553. + my $param = shift;
  56554. + my $tmp = `cat $paramdir/$param`;
  56555. + chomp $tmp;
  56556. + return $tmp;
  56557. +}
  56558. +
  56559. +#
  56560. +#
  56561. +sub test_main {
  56562. +
  56563. + print "\nTesting Module Parameters\n";
  56564. +
  56565. + load_module("") or die;
  56566. +
  56567. + # Test initial values
  56568. + print "\nTesting Default Values\n";
  56569. + foreach (@{$params}) {
  56570. + test ($_->{NAME}, $_->{DEFAULT});
  56571. + }
  56572. +
  56573. + # Test low value
  56574. + print "\nTesting Low Value\n";
  56575. + my $cmd_params = "";
  56576. + foreach (@{$params}) {
  56577. + $cmd_params = $cmd_params . "$_->{NAME}=$_->{LOW} ";
  56578. + }
  56579. + load_module($cmd_params) or die;
  56580. +
  56581. + foreach (@{$params}) {
  56582. + test ($_->{NAME}, $_->{LOW});
  56583. + }
  56584. +
  56585. + # Test high value
  56586. + print "\nTesting High Value\n";
  56587. + $cmd_params = "";
  56588. + foreach (@{$params}) {
  56589. + $cmd_params = $cmd_params . "$_->{NAME}=$_->{HIGH} ";
  56590. + }
  56591. + load_module($cmd_params) or die;
  56592. +
  56593. + foreach (@{$params}) {
  56594. + test ($_->{NAME}, $_->{HIGH});
  56595. + }
  56596. +
  56597. + # Test Enum
  56598. + print "\nTesting Enumerated\n";
  56599. + foreach (@{$params}) {
  56600. + if (defined $_->{ENUM}) {
  56601. + my $value;
  56602. + foreach $value (@{$_->{ENUM}}) {
  56603. + $cmd_params = "$_->{NAME}=$value";
  56604. + load_module($cmd_params) or die;
  56605. + test ($_->{NAME}, $value);
  56606. + }
  56607. + }
  56608. + }
  56609. +
  56610. + # Test Invalid Values
  56611. + print "\nTesting Invalid Values\n";
  56612. + $cmd_params = "";
  56613. + foreach (@{$params}) {
  56614. + $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{LOW}-1;
  56615. + }
  56616. + load_module($cmd_params) or die;
  56617. +
  56618. + foreach (@{$params}) {
  56619. + test ($_->{NAME}, $_->{DEFAULT});
  56620. + }
  56621. +
  56622. + $cmd_params = "";
  56623. + foreach (@{$params}) {
  56624. + $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{HIGH}+1;
  56625. + }
  56626. + load_module($cmd_params) or die;
  56627. +
  56628. + foreach (@{$params}) {
  56629. + test ($_->{NAME}, $_->{DEFAULT});
  56630. + }
  56631. +
  56632. + print "\nTesting Enumerated\n";
  56633. + foreach (@{$params}) {
  56634. + if (defined $_->{ENUM}) {
  56635. + my $value;
  56636. + foreach $value (@{$_->{ENUM}}) {
  56637. + $value = $value + 1;
  56638. + $cmd_params = "$_->{NAME}=$value";
  56639. + load_module($cmd_params) or die;
  56640. + test ($_->{NAME}, $_->{DEFAULT});
  56641. + $value = $value - 2;
  56642. + $cmd_params = "$_->{NAME}=$value";
  56643. + load_module($cmd_params) or die;
  56644. + test ($_->{NAME}, $_->{DEFAULT});
  56645. + }
  56646. + }
  56647. + }
  56648. +
  56649. + test_status() or die;
  56650. +}
  56651. +
  56652. +test_main();
  56653. +0;
  56654. --- /dev/null
  56655. +++ b/drivers/usb/host/dwc_otg/test/test_sysfs.pl
  56656. @@ -0,0 +1,193 @@
  56657. +#!/usr/bin/perl -w
  56658. +#
  56659. +# Run this program on the integrator
  56660. +# - Tests select sysfs attributes.
  56661. +# - Todo ... test more attributes, hnp/srp, buspower/bussuspend, etc.
  56662. +# -----------------------------------------------------------------------------
  56663. +use strict;
  56664. +use dwc_otg_test;
  56665. +
  56666. +check_arch() or die;
  56667. +
  56668. +#
  56669. +#
  56670. +sub test {
  56671. + my ($attr,$expected) = @_;
  56672. + my $string = get($attr);
  56673. +
  56674. + if ($string eq $expected) {
  56675. + printf("$attr = $string, okay\n");
  56676. + }
  56677. + else {
  56678. + warn "ERROR: value of $attr != $expected, $string\n";
  56679. + $errors ++;
  56680. + }
  56681. +}
  56682. +
  56683. +#
  56684. +#
  56685. +sub set {
  56686. + my ($reg, $value) = @_;
  56687. + system "echo $value > $sysfsdir/$reg";
  56688. +}
  56689. +
  56690. +#
  56691. +#
  56692. +sub get {
  56693. + my $attr = shift;
  56694. + my $string = `cat $sysfsdir/$attr`;
  56695. + chomp $string;
  56696. + if ($string =~ m/\s\=\s/) {
  56697. + my $tmp;
  56698. + ($tmp, $string) = split /\s=\s/, $string;
  56699. + }
  56700. + return $string;
  56701. +}
  56702. +
  56703. +#
  56704. +#
  56705. +sub test_main {
  56706. + print("\nTesting Sysfs Attributes\n");
  56707. +
  56708. + load_module("") or die;
  56709. +
  56710. + # Test initial values of regoffset/regvalue/guid/gsnpsid
  56711. + print("\nTesting Default Values\n");
  56712. +
  56713. + test("regoffset", "0xffffffff");
  56714. + test("regvalue", "invalid offset");
  56715. + test("guid", "0x12345678"); # this will fail if it has been changed
  56716. + test("gsnpsid", "0x4f54200a");
  56717. +
  56718. + # Test operation of regoffset/regvalue
  56719. + print("\nTesting regoffset\n");
  56720. + set('regoffset', '5a5a5a5a');
  56721. + test("regoffset", "0xffffffff");
  56722. +
  56723. + set('regoffset', '0');
  56724. + test("regoffset", "0x00000000");
  56725. +
  56726. + set('regoffset', '40000');
  56727. + test("regoffset", "0x00000000");
  56728. +
  56729. + set('regoffset', '3ffff');
  56730. + test("regoffset", "0x0003ffff");
  56731. +
  56732. + set('regoffset', '1');
  56733. + test("regoffset", "0x00000001");
  56734. +
  56735. + print("\nTesting regvalue\n");
  56736. + set('regoffset', '3c');
  56737. + test("regvalue", "0x12345678");
  56738. + set('regvalue', '5a5a5a5a');
  56739. + test("regvalue", "0x5a5a5a5a");
  56740. + set('regvalue','a5a5a5a5');
  56741. + test("regvalue", "0xa5a5a5a5");
  56742. + set('guid','12345678');
  56743. +
  56744. + # Test HNP Capable
  56745. + print("\nTesting HNP Capable bit\n");
  56746. + set('hnpcapable', '1');
  56747. + test("hnpcapable", "0x1");
  56748. + set('hnpcapable','0');
  56749. + test("hnpcapable", "0x0");
  56750. +
  56751. + set('regoffset','0c');
  56752. +
  56753. + my $old = get('gusbcfg');
  56754. + print("setting hnpcapable\n");
  56755. + set('hnpcapable', '1');
  56756. + test("hnpcapable", "0x1");
  56757. + test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<9)));
  56758. + test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<9)));
  56759. +
  56760. + $old = get('gusbcfg');
  56761. + print("clearing hnpcapable\n");
  56762. + set('hnpcapable', '0');
  56763. + test("hnpcapable", "0x0");
  56764. + test ('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<9)));
  56765. + test ('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<9)));
  56766. +
  56767. + # Test SRP Capable
  56768. + print("\nTesting SRP Capable bit\n");
  56769. + set('srpcapable', '1');
  56770. + test("srpcapable", "0x1");
  56771. + set('srpcapable','0');
  56772. + test("srpcapable", "0x0");
  56773. +
  56774. + set('regoffset','0c');
  56775. +
  56776. + $old = get('gusbcfg');
  56777. + print("setting srpcapable\n");
  56778. + set('srpcapable', '1');
  56779. + test("srpcapable", "0x1");
  56780. + test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<8)));
  56781. + test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<8)));
  56782. +
  56783. + $old = get('gusbcfg');
  56784. + print("clearing srpcapable\n");
  56785. + set('srpcapable', '0');
  56786. + test("srpcapable", "0x0");
  56787. + test('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<8)));
  56788. + test('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<8)));
  56789. +
  56790. + # Test GGPIO
  56791. + print("\nTesting GGPIO\n");
  56792. + set('ggpio','5a5a5a5a');
  56793. + test('ggpio','0x5a5a0000');
  56794. + set('ggpio','a5a5a5a5');
  56795. + test('ggpio','0xa5a50000');
  56796. + set('ggpio','11110000');
  56797. + test('ggpio','0x11110000');
  56798. + set('ggpio','00001111');
  56799. + test('ggpio','0x00000000');
  56800. +
  56801. + # Test DEVSPEED
  56802. + print("\nTesting DEVSPEED\n");
  56803. + set('regoffset','800');
  56804. + $old = get('regvalue');
  56805. + set('devspeed','0');
  56806. + test('devspeed','0x0');
  56807. + test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3)));
  56808. + set('devspeed','1');
  56809. + test('devspeed','0x1');
  56810. + test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1));
  56811. + set('devspeed','2');
  56812. + test('devspeed','0x2');
  56813. + test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 2));
  56814. + set('devspeed','3');
  56815. + test('devspeed','0x3');
  56816. + test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 3));
  56817. + set('devspeed','4');
  56818. + test('devspeed','0x0');
  56819. + test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3)));
  56820. + set('devspeed','5');
  56821. + test('devspeed','0x1');
  56822. + test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1));
  56823. +
  56824. +
  56825. + # mode Returns the current mode:0 for device mode1 for host mode Read
  56826. + # hnp Initiate the Host Negotiation Protocol. Read returns the status. Read/Write
  56827. + # srp Initiate the Session Request Protocol. Read returns the status. Read/Write
  56828. + # buspower Get or Set the Power State of the bus (0 - Off or 1 - On) Read/Write
  56829. + # bussuspend Suspend the USB bus. Read/Write
  56830. + # busconnected Get the connection status of the bus Read
  56831. +
  56832. + # gotgctl Get or set the Core Control Status Register. Read/Write
  56833. + ## gusbcfg Get or set the Core USB Configuration Register Read/Write
  56834. + # grxfsiz Get or set the Receive FIFO Size Register Read/Write
  56835. + # gnptxfsiz Get or set the non-periodic Transmit Size Register Read/Write
  56836. + # gpvndctl Get or set the PHY Vendor Control Register Read/Write
  56837. + ## ggpio Get the value in the lower 16-bits of the General Purpose IO Register or Set the upper 16 bits. Read/Write
  56838. + ## guid Get or set the value of the User ID Register Read/Write
  56839. + ## gsnpsid Get the value of the Synopsys ID Regester Read
  56840. + ## devspeed Get or set the device speed setting in the DCFG register Read/Write
  56841. + # enumspeed Gets the device enumeration Speed. Read
  56842. + # hptxfsiz Get the value of the Host Periodic Transmit FIFO Read
  56843. + # hprt0 Get or Set the value in the Host Port Control and Status Register Read/Write
  56844. +
  56845. + test_status("TEST NYI") or die;
  56846. +}
  56847. +
  56848. +test_main();
  56849. +0;